Skip to content

Commit 107c2a9

Browse files
committed
Added Dark Mode Context Menu
1 parent a27b94e commit 107c2a9

14 files changed

+313
-10
lines changed
Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,29 @@
11
<script lang="ts">
22
import IconMoonWaningCrescent from '~icons/mdi/moon-waning-crescent';
33
import IconWhiteBalanceSunny from '~icons/mdi/white-balance-sunny';
4+
import * as ContextMenu from '$lib/components/ui/context-menu';
45
import { Button } from '$comp/ui/button';
56
6-
import { toggleMode } from 'mode-watcher';
7+
import { setMode, toggleMode, userPrefersMode } from 'mode-watcher';
78
</script>
89

9-
<Button on:click={toggleMode} variant="outline" size="icon" title="Toggle dark mode">
10-
<IconWhiteBalanceSunny
11-
class="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0"
12-
/>
13-
<IconMoonWaningCrescent
14-
class="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100"
15-
/>
16-
<span class="sr-only">Toggle theme</span>
17-
</Button>
10+
<ContextMenu.Root>
11+
<ContextMenu.Trigger>
12+
<Button on:click={toggleMode} variant="outline" size="icon" title="Toggle dark mode">
13+
<IconWhiteBalanceSunny
14+
class="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0"
15+
/>
16+
<IconMoonWaningCrescent
17+
class="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100"
18+
/>
19+
<span class="sr-only">Toggle theme</span>
20+
</Button>
21+
</ContextMenu.Trigger>
22+
<ContextMenu.Content>
23+
<ContextMenu.RadioGroup bind:value={$userPrefersMode} onValueChange={setMode}>
24+
<ContextMenu.RadioItem value="light">Light</ContextMenu.RadioItem>
25+
<ContextMenu.RadioItem value="dark">Dark</ContextMenu.RadioItem>
26+
<ContextMenu.RadioItem value="system">System</ContextMenu.RadioItem>
27+
</ContextMenu.RadioGroup>
28+
</ContextMenu.Content>
29+
</ContextMenu.Root>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<script lang="ts">
2+
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
3+
import { cn } from '$lib/utils';
4+
import { Check } from 'radix-icons-svelte';
5+
6+
type $$Props = ContextMenuPrimitive.CheckboxItemProps;
7+
8+
let className: $$Props['class'] = undefined;
9+
export { className as class };
10+
export let checked: $$Props['checked'] = undefined;
11+
</script>
12+
13+
<ContextMenuPrimitive.CheckboxItem
14+
bind:checked
15+
class={cn(
16+
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
17+
className
18+
)}
19+
{...$$restProps}
20+
on:click
21+
on:keydown
22+
on:focusin
23+
on:focusout
24+
on:pointerdown
25+
on:pointerleave
26+
on:pointermove
27+
>
28+
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
29+
<ContextMenuPrimitive.CheckboxIndicator>
30+
<Check class="w-4 h-4" />
31+
</ContextMenuPrimitive.CheckboxIndicator>
32+
</span>
33+
<slot />
34+
</ContextMenuPrimitive.CheckboxItem>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<script lang="ts">
2+
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
3+
import { cn, flyAndScale } from '$lib/utils';
4+
5+
type $$Props = ContextMenuPrimitive.ContentProps;
6+
7+
let className: $$Props['class'] = undefined;
8+
export let transition: $$Props['transition'] = flyAndScale;
9+
export let transitionConfig: $$Props['transitionConfig'] = undefined;
10+
export { className as class };
11+
</script>
12+
13+
<ContextMenuPrimitive.Content
14+
{transition}
15+
{transitionConfig}
16+
class={cn(
17+
'z-50 min-w-[8rem] rounded-md border bg-popover p-1 text-popover-foreground shadow-md focus:outline-none',
18+
className
19+
)}
20+
{...$$restProps}
21+
on:keydown
22+
>
23+
<slot />
24+
</ContextMenuPrimitive.Content>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<script lang="ts">
2+
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
3+
import { cn } from '$lib/utils';
4+
5+
type $$Props = ContextMenuPrimitive.ItemProps & {
6+
inset?: boolean;
7+
};
8+
9+
let className: $$Props['class'] = undefined;
10+
export let inset: $$Props['inset'] = undefined;
11+
export { className as class };
12+
</script>
13+
14+
<ContextMenuPrimitive.Item
15+
class={cn(
16+
'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
17+
inset && 'pl-8',
18+
className
19+
)}
20+
{...$$restProps}
21+
on:click
22+
on:keydown
23+
on:focusin
24+
on:focusout
25+
on:pointerdown
26+
on:pointerleave
27+
on:pointermove
28+
>
29+
<slot />
30+
</ContextMenuPrimitive.Item>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<script lang="ts">
2+
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
3+
import { cn } from '$lib/utils';
4+
5+
type $$Props = ContextMenuPrimitive.LabelProps & {
6+
inset?: boolean;
7+
};
8+
9+
let className: $$Props['class'] = undefined;
10+
export let inset: $$Props['inset'] = undefined;
11+
export { className as class };
12+
</script>
13+
14+
<ContextMenuPrimitive.Label
15+
class={cn('px-2 py-1.5 text-sm font-semibold text-foreground', inset && 'pl-8', className)}
16+
{...$$restProps}
17+
>
18+
<slot />
19+
</ContextMenuPrimitive.Label>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<script lang="ts">
2+
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
3+
4+
type $$Props = ContextMenuPrimitive.RadioGroupProps;
5+
6+
export let value: $$Props['value'] = undefined;
7+
</script>
8+
9+
<ContextMenuPrimitive.RadioGroup {...$$restProps} bind:value>
10+
<slot />
11+
</ContextMenuPrimitive.RadioGroup>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<script lang="ts">
2+
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
3+
import { cn } from '$lib/utils';
4+
import { DotFilled } from 'radix-icons-svelte';
5+
6+
type $$Props = ContextMenuPrimitive.RadioItemProps;
7+
8+
let className: $$Props['class'] = undefined;
9+
export let value: $$Props['value'];
10+
export { className as class };
11+
</script>
12+
13+
<ContextMenuPrimitive.RadioItem
14+
class={cn(
15+
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
16+
className
17+
)}
18+
{value}
19+
{...$$restProps}
20+
on:click
21+
on:keydown
22+
on:focusin
23+
on:focusout
24+
on:pointerdown
25+
on:pointerleave
26+
on:pointermove
27+
>
28+
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
29+
<ContextMenuPrimitive.RadioIndicator>
30+
<DotFilled class="w-4 h-4 fill-current" />
31+
</ContextMenuPrimitive.RadioIndicator>
32+
</span>
33+
<slot />
34+
</ContextMenuPrimitive.RadioItem>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<script lang="ts">
2+
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
3+
import { cn } from '$lib/utils';
4+
5+
type $$Props = ContextMenuPrimitive.SeparatorProps;
6+
7+
let className: $$Props['class'] = undefined;
8+
export { className as class };
9+
</script>
10+
11+
<ContextMenuPrimitive.Separator
12+
class={cn('-mx-1 my-1 h-px bg-border', className)}
13+
{...$$restProps}
14+
/>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<script lang="ts">
2+
import { cn } from '$lib/utils';
3+
import type { HTMLAttributes } from 'svelte/elements';
4+
5+
type $$Props = HTMLAttributes<HTMLSpanElement>;
6+
7+
let className: $$Props['class'] = undefined;
8+
export { className as class };
9+
</script>
10+
11+
<span
12+
class={cn('ml-auto text-xs tracking-widest text-muted-foreground', className)}
13+
{...$$restProps}
14+
>
15+
<slot />
16+
</span>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<script lang="ts">
2+
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
3+
import { cn, flyAndScale } from '$lib/utils';
4+
5+
type $$Props = ContextMenuPrimitive.SubContentProps;
6+
7+
let className: $$Props['class'] = undefined;
8+
export let transition: $$Props['transition'] = flyAndScale;
9+
export let transitionConfig: $$Props['transitionConfig'] = undefined;
10+
export { className as class };
11+
</script>
12+
13+
<ContextMenuPrimitive.SubContent
14+
{transition}
15+
{transitionConfig}
16+
class={cn(
17+
'z-50 min-w-[8rem] rounded-md border bg-popover p-1 text-popover-foreground shadow-lg focus:outline-none',
18+
className
19+
)}
20+
{...$$restProps}
21+
on:keydown
22+
on:focusout
23+
on:pointermove
24+
>
25+
<slot />
26+
</ContextMenuPrimitive.SubContent>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<script lang="ts">
2+
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
3+
import { cn } from '$lib/utils';
4+
import { ChevronRight } from 'radix-icons-svelte';
5+
6+
type $$Props = ContextMenuPrimitive.SubTriggerProps & {
7+
inset?: boolean;
8+
};
9+
10+
let className: $$Props['class'] = undefined;
11+
export let inset: $$Props['inset'] = undefined;
12+
export { className as class };
13+
</script>
14+
15+
<ContextMenuPrimitive.SubTrigger
16+
class={cn(
17+
'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',
18+
inset && 'pl-8',
19+
className
20+
)}
21+
{...$$restProps}
22+
on:click
23+
on:keydown
24+
on:focusin
25+
on:focusout
26+
on:pointerleave
27+
on:pointermove
28+
>
29+
<slot />
30+
<ChevronRight class="w-4 h-4 ml-auto" />
31+
</ContextMenuPrimitive.SubTrigger>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
2+
3+
import Item from './context-menu-item.svelte';
4+
import Label from './context-menu-label.svelte';
5+
import Content from './context-menu-content.svelte';
6+
import Shortcut from './context-menu-shortcut.svelte';
7+
import RadioItem from './context-menu-radio-item.svelte';
8+
import Separator from './context-menu-separator.svelte';
9+
import RadioGroup from './context-menu-radio-group.svelte';
10+
import SubContent from './context-menu-sub-content.svelte';
11+
import SubTrigger from './context-menu-sub-trigger.svelte';
12+
import CheckboxItem from './context-menu-checkbox-item.svelte';
13+
14+
const Sub = ContextMenuPrimitive.Sub;
15+
const Root = ContextMenuPrimitive.Root;
16+
const Trigger = ContextMenuPrimitive.Trigger;
17+
const Group = ContextMenuPrimitive.Group;
18+
19+
export {
20+
Sub,
21+
Root,
22+
Item,
23+
Label,
24+
Group,
25+
Trigger,
26+
Content,
27+
Shortcut,
28+
Separator,
29+
RadioItem,
30+
SubContent,
31+
SubTrigger,
32+
RadioGroup,
33+
CheckboxItem,
34+
//
35+
Root as ContextMenu,
36+
Sub as ContextMenuSub,
37+
Item as ContextMenuItem,
38+
Label as ContextMenuLabel,
39+
Group as ContextMenuGroup,
40+
Content as ContextMenuContent,
41+
Trigger as ContextMenuTrigger,
42+
Shortcut as ContextMenuShortcut,
43+
RadioItem as ContextMenuRadioItem,
44+
Separator as ContextMenuSeparator,
45+
RadioGroup as ContextMenuRadioGroup,
46+
SubContent as ContextMenuSubContent,
47+
SubTrigger as ContextMenuSubTrigger,
48+
CheckboxItem as ContextMenuCheckboxItem
49+
};

src/Exceptionless.Web/ClientApp/src/lib/components/ui/table/table-header.svelte

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
export { className as class };
99
</script>
1010

11+
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
1112
<thead class={cn('[&_tr]:border-b', className)} {...$$restProps} on:click on:keydown>
1213
<slot />
1314
</thead>

src/Exceptionless.Web/ClientApp/src/routes/+layout.svelte

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616

1717
<div class="bg-background text-foreground">
1818
<ModeWatcher defaultMode={'dark'} />
19+
1920
<QueryClientProvider client={queryClient}>
2021
<slot />
22+
2123
<SvelteQueryDevtools />
2224
</QueryClientProvider>
2325

0 commit comments

Comments
 (0)