diff options
| author | ivar <i@oiee.no> | 2024-04-28 22:37:30 +0200 |
|---|---|---|
| committer | ivar <i@oiee.no> | 2024-04-28 22:37:30 +0200 |
| commit | ced66c5807575cd29f6aa5632e8ad02b38c8448a (patch) | |
| tree | 01760648ee293a2aef2288328014b5747d2192b4 /code/frontend/src/components/ui | |
| parent | 691ad60d7bff5934053d87267c4e303ef3ed5f97 (diff) | |
| download | greatoffice-ced66c5807575cd29f6aa5632e8ad02b38c8448a.tar.xz greatoffice-ced66c5807575cd29f6aa5632e8ad02b38c8448a.zip | |
WIP new frontend
Diffstat (limited to 'code/frontend/src/components/ui')
13 files changed, 363 insertions, 0 deletions
diff --git a/code/frontend/src/components/ui/button/button.svelte b/code/frontend/src/components/ui/button/button.svelte new file mode 100644 index 0000000..196ae77 --- /dev/null +++ b/code/frontend/src/components/ui/button/button.svelte @@ -0,0 +1,25 @@ +<script lang="ts"> + import { Button as ButtonPrimitive } from 'bits-ui' + import { type Events, type Props, buttonVariants } from './index.js' + import { cn } from '$utils/ui.js' + + type $$Props = Props + type $$Events = Events + + let className: $$Props['class'] = undefined + export let variant: $$Props['variant'] = 'default' + export let size: $$Props['size'] = 'default' + export let builders: $$Props['builders'] = [] + export { className as class } +</script> + +<ButtonPrimitive.Root + {builders} + class={cn(buttonVariants({ variant, size, className }))} + type="button" + {...$$restProps} + on:click + on:keydown +> + <slot /> +</ButtonPrimitive.Root> diff --git a/code/frontend/src/components/ui/button/index.ts b/code/frontend/src/components/ui/button/index.ts new file mode 100644 index 0000000..9cfd91c --- /dev/null +++ b/code/frontend/src/components/ui/button/index.ts @@ -0,0 +1,48 @@ +import type { Button as ButtonPrimitive } from 'bits-ui' +import { type VariantProps, tv } from 'tailwind-variants' +import Root from './button.svelte' + +const buttonVariants = tv({ + base: 'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50', + variants: { + variant: { + default: 'bg-primary text-primary-foreground shadow hover:bg-primary/90', + destructive: 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90', + outline: 'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground', + secondary: 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80', + ghost: 'hover:bg-accent hover:text-accent-foreground', + link: 'text-primary underline-offset-4 hover:underline' + }, + size: { + default: 'h-9 px-4 py-2', + sm: 'h-8 rounded-md px-3 text-xs', + lg: 'h-10 rounded-md px-8', + icon: 'h-9 w-9' + } + }, + defaultVariants: { + variant: 'default', + size: 'default' + } +}) + +type Variant = VariantProps<typeof buttonVariants>['variant'] +type Size = VariantProps<typeof buttonVariants>['size'] + +type Props = ButtonPrimitive.Props & { + variant?: Variant + size?: Size +} + +type Events = ButtonPrimitive.Events + +export { + Root, + type Props, + type Events, + // + Root as Button, + type Props as ButtonProps, + type Events as ButtonEvents, + buttonVariants +} diff --git a/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte b/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte new file mode 100644 index 0000000..ea02af0 --- /dev/null +++ b/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte @@ -0,0 +1,35 @@ +<script lang="ts"> + import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui' + import Check from 'svelte-radix/Check.svelte' + import { cn } from '$utils/ui' + + type $$Props = DropdownMenuPrimitive.CheckboxItemProps + type $$Events = DropdownMenuPrimitive.CheckboxItemEvents + + let className: $$Props['class'] = undefined + export let checked: $$Props['checked'] = undefined + export { className as class } +</script> + +<DropdownMenuPrimitive.CheckboxItem + bind:checked + class={cn( + 'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50', + className + )} + {...$$restProps} + on:click + on:keydown + on:focusin + on:focusout + on:pointerdown + on:pointerleave + on:pointermove +> + <span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> + <DropdownMenuPrimitive.CheckboxIndicator> + <Check class="h-4 w-4" /> + </DropdownMenuPrimitive.CheckboxIndicator> + </span> + <slot /> +</DropdownMenuPrimitive.CheckboxItem> diff --git a/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-content.svelte b/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-content.svelte new file mode 100644 index 0000000..a2b8da7 --- /dev/null +++ b/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-content.svelte @@ -0,0 +1,26 @@ +<script lang="ts"> + import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui' + import { cn, flyAndScale } from '$utils/ui' + + type $$Props = DropdownMenuPrimitive.ContentProps + + let className: $$Props['class'] = undefined + export let sideOffset: $$Props['sideOffset'] = 4 + export let transition: $$Props['transition'] = flyAndScale + export let transitionConfig: $$Props['transitionConfig'] = undefined + export { className as class } +</script> + +<DropdownMenuPrimitive.Content + {transition} + {transitionConfig} + {sideOffset} + class={cn( + 'z-50 min-w-[8rem] rounded-md border bg-popover p-1 text-popover-foreground shadow-md focus:outline-none', + className + )} + {...$$restProps} + on:keydown +> + <slot /> +</DropdownMenuPrimitive.Content> diff --git a/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-item.svelte b/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-item.svelte new file mode 100644 index 0000000..ed45da7 --- /dev/null +++ b/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-item.svelte @@ -0,0 +1,31 @@ +<script lang="ts"> + import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui' + import { cn } from '$utils/ui' + + type $$Props = DropdownMenuPrimitive.ItemProps & { + inset?: boolean + } + type $$Events = DropdownMenuPrimitive.ItemEvents + + let className: $$Props['class'] = undefined + export let inset: $$Props['inset'] = undefined + export { className as class } +</script> + +<DropdownMenuPrimitive.Item + class={cn( + 'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50', + inset && 'pl-8', + className + )} + on:click + on:keydown + on:focusin + on:focusout + on:pointerdown + on:pointerleave + on:pointermove + {...$$restProps} +> + <slot /> +</DropdownMenuPrimitive.Item> diff --git a/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-label.svelte b/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-label.svelte new file mode 100644 index 0000000..69fddd1 --- /dev/null +++ b/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-label.svelte @@ -0,0 +1,19 @@ +<script lang="ts"> + import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui' + import { cn } from '$utils/ui' + + type $$Props = DropdownMenuPrimitive.LabelProps & { + inset?: boolean + } + + let className: $$Props['class'] = undefined + export let inset: $$Props['inset'] = undefined + export { className as class } +</script> + +<DropdownMenuPrimitive.Label + class={cn('px-2 py-1.5 text-sm font-semibold', inset && 'pl-8', className)} + {...$$restProps} +> + <slot /> +</DropdownMenuPrimitive.Label> diff --git a/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte b/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte new file mode 100644 index 0000000..c07bd1a --- /dev/null +++ b/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte @@ -0,0 +1,11 @@ +<script lang="ts"> + import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui' + + type $$Props = DropdownMenuPrimitive.RadioGroupProps + + export let value: $$Props['value'] = undefined +</script> + +<DropdownMenuPrimitive.RadioGroup {...$$restProps} bind:value> + <slot /> +</DropdownMenuPrimitive.RadioGroup> diff --git a/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte b/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte new file mode 100644 index 0000000..c754953 --- /dev/null +++ b/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte @@ -0,0 +1,35 @@ +<script lang="ts"> + import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui' + import DotFilled from 'svelte-radix/DotFilled.svelte' + import { cn } from '$utils/ui' + + type $$Props = DropdownMenuPrimitive.RadioItemProps + type $$Events = DropdownMenuPrimitive.RadioItemEvents + + let className: $$Props['class'] = undefined + export let value: DropdownMenuPrimitive.RadioItemProps['value'] + export { className as class } +</script> + +<DropdownMenuPrimitive.RadioItem + class={cn( + 'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50', + className + )} + {value} + {...$$restProps} + on:click + on:keydown + on:focusin + on:focusout + on:pointerdown + on:pointerleave + on:pointermove +> + <span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> + <DropdownMenuPrimitive.RadioIndicator> + <DotFilled class="h-4 w-4 fill-current" /> + </DropdownMenuPrimitive.RadioIndicator> + </span> + <slot /> +</DropdownMenuPrimitive.RadioItem> diff --git a/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-separator.svelte b/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-separator.svelte new file mode 100644 index 0000000..b6c5798 --- /dev/null +++ b/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-separator.svelte @@ -0,0 +1,11 @@ +<script lang="ts"> + import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui' + import { cn } from '$utils/ui' + + type $$Props = DropdownMenuPrimitive.SeparatorProps + + let className: $$Props['class'] = undefined + export { className as class } +</script> + +<DropdownMenuPrimitive.Separator class={cn('-mx-1 my-1 h-px bg-muted', className)} {...$$restProps} /> diff --git a/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte b/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte new file mode 100644 index 0000000..f9e5953 --- /dev/null +++ b/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte @@ -0,0 +1,13 @@ +<script lang="ts"> + import type { HTMLAttributes } from 'svelte/elements' + import { cn } from '$utils/ui' + + type $$Props = HTMLAttributes<HTMLSpanElement> + + let className: $$Props['class'] = undefined + export { className as class } +</script> + +<span class={cn('ml-auto text-xs tracking-widest opacity-60', className)} {...$$restProps}> + <slot /> +</span> diff --git a/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte b/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte new file mode 100644 index 0000000..7c00a1b --- /dev/null +++ b/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte @@ -0,0 +1,29 @@ +<script lang="ts"> + import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui' + import { cn, flyAndScale } from '$utils/ui' + + type $$Props = DropdownMenuPrimitive.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> + +<DropdownMenuPrimitive.SubContent + {transition} + {transitionConfig} + class={cn( + 'z-50 min-w-[8rem] rounded-md border bg-popover p-1 text-popover-foreground shadow-lg focus:outline-none', + className + )} + {...$$restProps} + on:keydown + on:focusout + on:pointermove +> + <slot /> +</DropdownMenuPrimitive.SubContent> diff --git a/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte b/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte new file mode 100644 index 0000000..4967d2b --- /dev/null +++ b/code/frontend/src/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte @@ -0,0 +1,32 @@ +<script lang="ts"> + import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui' + import ChevronRight from 'svelte-radix/ChevronRight.svelte' + import { cn } from '$utils/ui' + + type $$Props = DropdownMenuPrimitive.SubTriggerProps & { + inset?: boolean + } + type $$Events = DropdownMenuPrimitive.SubTriggerEvents + + let className: $$Props['class'] = undefined + export let inset: $$Props['inset'] = undefined + export { className as class } +</script> + +<DropdownMenuPrimitive.SubTrigger + class={cn( + 'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted]:bg-accent data-[state=open]:bg-accent data-[highlighted]:text-accent-foreground data-[state=open]:text-accent-foreground', + inset && 'pl-8', + className + )} + {...$$restProps} + on:click + on:keydown + on:focusin + on:focusout + on:pointerleave + on:pointermove +> + <slot /> + <ChevronRight class="ml-auto h-4 w-4" /> +</DropdownMenuPrimitive.SubTrigger> diff --git a/code/frontend/src/components/ui/dropdown-menu/index.ts b/code/frontend/src/components/ui/dropdown-menu/index.ts new file mode 100644 index 0000000..df959fa --- /dev/null +++ b/code/frontend/src/components/ui/dropdown-menu/index.ts @@ -0,0 +1,48 @@ +import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui' +import Item from './dropdown-menu-item.svelte' +import Label from './dropdown-menu-label.svelte' +import Content from './dropdown-menu-content.svelte' +import Shortcut from './dropdown-menu-shortcut.svelte' +import RadioItem from './dropdown-menu-radio-item.svelte' +import Separator from './dropdown-menu-separator.svelte' +import RadioGroup from './dropdown-menu-radio-group.svelte' +import SubContent from './dropdown-menu-sub-content.svelte' +import SubTrigger from './dropdown-menu-sub-trigger.svelte' +import CheckboxItem from './dropdown-menu-checkbox-item.svelte' + +const Sub = DropdownMenuPrimitive.Sub +const Root = DropdownMenuPrimitive.Root +const Trigger = DropdownMenuPrimitive.Trigger +const Group = DropdownMenuPrimitive.Group + +export { + Sub, + Root, + Item, + Label, + Group, + Trigger, + Content, + Shortcut, + Separator, + RadioItem, + SubContent, + SubTrigger, + RadioGroup, + CheckboxItem, + // + Root as DropdownMenu, + Sub as DropdownMenuSub, + Item as DropdownMenuItem, + Label as DropdownMenuLabel, + Group as DropdownMenuGroup, + Content as DropdownMenuContent, + Trigger as DropdownMenuTrigger, + Shortcut as DropdownMenuShortcut, + RadioItem as DropdownMenuRadioItem, + Separator as DropdownMenuSeparator, + RadioGroup as DropdownMenuRadioGroup, + SubContent as DropdownMenuSubContent, + SubTrigger as DropdownMenuSubTrigger, + CheckboxItem as DropdownMenuCheckboxItem +} |
