Skip to content

Commit

Permalink
component: Context Menu (#11)
Browse files Browse the repository at this point in the history
* component: Context Menu

* meh

* more

* more

---------

Co-authored-by: Davis SHYAKA <87414827+davis-shyaka@users.noreply.github.com>
  • Loading branch information
shyakadavis and shyakadavis authored Jul 18, 2024
1 parent a35938e commit 11c72e1
Show file tree
Hide file tree
Showing 26 changed files with 581 additions and 5 deletions.
3 changes: 3 additions & 0 deletions src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@
--shadow-border: 0 0 0 1px rgba(0, 0, 0, 0.08);
--shadow-small: 0px 1px 2px rgba(0, 0, 0, 0.16);
--shadow-border-small: var(--shadow-border), var(--shadow-small);
--shadow-menu: var(--shadow-border), 0px 1px 1px rgba(0, 0, 0, 0.02),
0px 4px 8px -4px rgba(0, 0, 0, 0.04), 0px 16px 24px -8px rgba(0, 0, 0, 0.06);
}

.dark {
Expand Down Expand Up @@ -226,6 +228,7 @@
--focus-color: var(--blue-900);

/* Shadows */
--shadow-border: 0 0 0 1px hsla(0, 0%, 100%, 0.145);
--focus-border: 0 0 0 1px var(--gray-alpha-600), 0px 0px 0px 4px hsla(0, 0%, 100%, 0.24);
--shadow-border-inset: inset 0 0 0 1px hsla(0, 0%, 100%, 0.1);
--shadow-border-small: var(--shadow-border), 0px 1px 2px rgba(0, 0, 0, 0.16);
Expand Down
4 changes: 4 additions & 0 deletions src/lib/assets/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import LogoGitlab from './logo-gitlab.svg?component';
import LogoNext from './logo-next.svg?component';
import LogoTurborepo from './logo-turborepo.svg?component';
import LogoV0 from './logo-v0.svg?component';
import LogoVercelCircle from './logo-vercel-circle.svg?component';
import LogoVercel from './logo-vercel.svg?component';
import Minus from './minus.svg?component';
import Notification from './notification.svg?component';
Expand All @@ -41,6 +42,7 @@ import PencilEdit from './pencil-edit.svg?component';
import Router from './router.svg?component';
import SettingsSliders from './settings-sliders.svg?component';
import Shield from './shield.svg?component';
import Status from './status.svg?component';
import Tabs from './tabs.svg?component';
import ThemeSwitchDark from './theme-switch-dark.svg?component';
import ThemeSwitchLight from './theme-switch-light.svg?component';
Expand Down Expand Up @@ -82,6 +84,7 @@ export const Icons = {
LogoNext,
LogoTurborepo,
LogoV0,
LogoVercelCircle,
LogoVercel,
Minus,
Notification,
Expand All @@ -90,6 +93,7 @@ export const Icons = {
Router,
SettingsSliders,
Shield,
Status,
Tabs,
ThemeSwitchDark,
ThemeSwitchLight,
Expand Down
11 changes: 11 additions & 0 deletions src/lib/assets/icons/logo-vercel-circle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/lib/assets/icons/status.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/lib/components/shared/demo.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
</p>
</summary>
<div
class="content prose prose-invert relative max-w-none p-6 dark:prose-invert prose-pre:bg-transparent"
class="content relative p-6 font-mono text-sm [&>pre>code]:whitespace-pre-wrap [&>pre>code]:break-words"
>
{@html highlighted_code}

Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/ui/button/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const button_variants = tv({
variant: {
default: 'bg-gray-1000 text-background-100',
secondary: 'border border-gray-alpha-400 bg-background-100 hover:bg-gray-alpha-100',
tertiary: 'hover:text-accent-foreground bg-transparent hover:bg-gray-alpha-200',
tertiary: 'bg-transparent hover:bg-gray-alpha-200',
error: 'bg-red-800 text-contrast-fg hover:bg-red-900',
warning: 'active:bg-[#a35200; bg-amber-800 text-[#0a0a0a] hover:bg-[#d27504]'
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script lang="ts">
import { Icons } from '$lib/assets/icons';
import { cn } from '$lib/utils.js';
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
type $$Props = ContextMenuPrimitive.CheckboxItemProps;
type $$Events = ContextMenuPrimitive.CheckboxItemEvents;
let className: $$Props['class'] = undefined;
export let checked: $$Props['checked'] = undefined;
export { className as class };
</script>

<ContextMenuPrimitive.CheckboxItem
bind:checked
class={cn(
'relative flex h-10 cursor-pointer select-none items-center rounded-md pl-8 pr-2 text-sm outline-none data-[disabled]:cursor-default data-[highlighted]:bg-gray-200 data-[disabled]:text-gray-700',
className
)}
{...$$restProps}
on:click
on:keydown
on:focusin
on:focusout
on:pointerdown
on:pointerleave
on:pointermove
>
<span class="absolute left-2 flex size-3.5 items-center justify-center">
<ContextMenuPrimitive.CheckboxIndicator>
<Icons.Check class="size-3" />
</ContextMenuPrimitive.CheckboxIndicator>
</span>
<slot />
</ContextMenuPrimitive.CheckboxItem>
24 changes: 24 additions & 0 deletions src/lib/components/ui/context-menu/context-menu-content.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<script lang="ts">
import { cn, flyAndScale } from '$lib/utils.js';
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
type $$Props = ContextMenuPrimitive.ContentProps;
let className: $$Props['class'] = undefined;
export let transition: $$Props['transition'] = flyAndScale;
export let transitionConfig: $$Props['transitionConfig'] = undefined;
export { className as class };
</script>

<ContextMenuPrimitive.Content
{transition}
{transitionConfig}
class={cn(
'z-50 min-w-[10rem] rounded-xl bg-background-100 p-2 text-sm text-gray-1000 shadow-shadow-menu focus:outline-none',
className
)}
{...$$restProps}
on:keydown
>
<slot />
</ContextMenuPrimitive.Content>
42 changes: 42 additions & 0 deletions src/lib/components/ui/context-menu/context-menu-item.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<script lang="ts">
import type { Icons } from '$lib/assets/icons';
import { cn } from '$lib/utils.js';
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
type $$Props = ContextMenuPrimitive.ItemProps & {
inset?: boolean;
affix?: typeof Icons.ArrowLeft;
suffix?: typeof Icons.ArrowLeft;
};
type $$Events = ContextMenuPrimitive.ItemEvents;
let className: $$Props['class'] = undefined;
export let inset: $$Props['inset'] = undefined;
export let affix: $$Props['affix'] = undefined;
export let suffix: $$Props['suffix'] = undefined;
export { className as class };
</script>

<ContextMenuPrimitive.Item
class={cn(
'relative flex h-10 select-none items-center gap-2 rounded-md px-2 text-sm outline-none data-[disabled]:cursor-default data-[highlighted]:cursor-pointer data-[highlighted]:bg-gray-200 data-[disabled]:text-gray-700',
inset && 'pl-8',
className
)}
{...$$restProps}
on:click
on:keydown
on:focusin
on:focusout
on:pointerdown
on:pointerleave
on:pointermove
>
{#if affix}
<svelte:component this={affix} class="size-4" aria-hidden="true" />
{/if}
<slot />
{#if suffix}
<svelte:component this={suffix} class="ml-auto size-4" aria-hidden="true" />
{/if}
</ContextMenuPrimitive.Item>
23 changes: 23 additions & 0 deletions src/lib/components/ui/context-menu/context-menu-label.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script lang="ts">
import { cn } from '$lib/utils.js';
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
type $$Props = ContextMenuPrimitive.LabelProps & {
inset?: boolean;
};
let className: $$Props['class'] = undefined;
export let inset: $$Props['inset'] = undefined;
export { className as class };
</script>

<ContextMenuPrimitive.Label
class={cn(
'inline-flex h-10 items-center px-2 text-sm font-semibold text-gray-1000',
inset && 'pl-8',
className
)}
{...$$restProps}
>
<slot />
</ContextMenuPrimitive.Label>
11 changes: 11 additions & 0 deletions src/lib/components/ui/context-menu/context-menu-radio-group.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script lang="ts">
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
type $$Props = ContextMenuPrimitive.RadioGroupProps;
export let value: $$Props['value'] = undefined;
</script>

<ContextMenuPrimitive.RadioGroup {...$$restProps} bind:value>
<slot />
</ContextMenuPrimitive.RadioGroup>
35 changes: 35 additions & 0 deletions src/lib/components/ui/context-menu/context-menu-radio-item.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script lang="ts">
import { Icons } from '$lib/assets/icons';
import { cn } from '$lib/utils.js';
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
type $$Props = ContextMenuPrimitive.RadioItemProps;
type $$Events = ContextMenuPrimitive.RadioItemEvents;
let className: $$Props['class'] = undefined;
export let value: ContextMenuPrimitive.RadioItemProps['value'];
export { className as class };
</script>

<ContextMenuPrimitive.RadioItem
class={cn(
'relative flex h-10 cursor-pointer select-none items-center rounded-md pl-8 pr-2 text-sm outline-none data-[disabled]:cursor-default data-[highlighted]:bg-gray-200',
className
)}
{value}
{...$$restProps}
on:click
on:keydown
on:focusin
on:focusout
on:pointerdown
on:pointerleave
on:pointermove
>
<span class="absolute left-2 flex size-3.5 items-center justify-center">
<ContextMenuPrimitive.RadioIndicator>
<Icons.Status class="size-3 fill-current" />
</ContextMenuPrimitive.RadioIndicator>
</span>
<slot />
</ContextMenuPrimitive.RadioItem>
14 changes: 14 additions & 0 deletions src/lib/components/ui/context-menu/context-menu-separator.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<script lang="ts">
import { cn } from '$lib/utils.js';
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
type $$Props = ContextMenuPrimitive.SeparatorProps;
let className: $$Props['class'] = undefined;
export { className as class };
</script>

<ContextMenuPrimitive.Separator
class={cn('-mx-1 my-1 h-px bg-gray-400', className)}
{...$$restProps}
/>
13 changes: 13 additions & 0 deletions src/lib/components/ui/context-menu/context-menu-shortcut.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<script lang="ts">
import { cn } from '$lib/utils.js';
import type { HTMLAttributes } from 'svelte/elements';
type $$Props = HTMLAttributes<HTMLSpanElement>;
let className: $$Props['class'] = undefined;
export { className as class };
</script>

<span class={cn('ml-auto text-xs tracking-widest text-gray-700', className)} {...$$restProps}>
<slot />
</span>
29 changes: 29 additions & 0 deletions src/lib/components/ui/context-menu/context-menu-sub-content.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<script lang="ts">
import { cn, flyAndScale } from '$lib/utils.js';
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
type $$Props = ContextMenuPrimitive.SubContentProps;
let className: $$Props['class'] = undefined;
export let transition: $$Props['transition'] = flyAndScale;
export let transitionConfig: $$Props['transitionConfig'] = {
x: -10,
y: 0
};
export { className as class };
</script>

<ContextMenuPrimitive.SubContent
{transition}
{transitionConfig}
class={cn(
'z-50 min-w-[10rem] overflow-hidden rounded-xl bg-background-100 p-2 text-sm text-gray-1000 shadow-shadow-menu focus:outline-none',
className
)}
{...$$restProps}
on:keydown
on:focusout
on:pointermove
>
<slot />
</ContextMenuPrimitive.SubContent>
32 changes: 32 additions & 0 deletions src/lib/components/ui/context-menu/context-menu-sub-trigger.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<script lang="ts">
import { Icons } from '$lib/assets/icons';
import { cn } from '$lib/utils.js';
import { ContextMenu as ContextMenuPrimitive } from 'bits-ui';
type $$Props = ContextMenuPrimitive.SubTriggerProps & {
inset?: boolean;
};
type $$Events = ContextMenuPrimitive.SubTriggerEvents;
let className: $$Props['class'] = undefined;
export let inset: $$Props['inset'] = undefined;
export { className as class };
</script>

<ContextMenuPrimitive.SubTrigger
class={cn(
'flex h-10 cursor-pointer select-none items-center rounded-md px-2 text-sm outline-none data-[highlighted]:bg-gray-200 data-[state=open]:bg-gray-200',
inset && 'pl-8',
className
)}
{...$$restProps}
on:click
on:keydown
on:focusin
on:focusout
on:pointerleave
on:pointermove
>
<slot />
<Icons.ChevronRight class="ml-auto size-4" />
</ContextMenuPrimitive.SubTrigger>
Loading

0 comments on commit 11c72e1

Please sign in to comment.