@aleph-alpha/ui-library 1.13.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/README.md +1 -1
  2. package/config.js +34 -1
  3. package/dist/system/index.d.ts +1728 -234
  4. package/dist/system/lib.js +19804 -16600
  5. package/package.json +1 -1
  6. package/src/components/UiKbd/UiKbd.stories.ts +1 -1
  7. package/src/components/UiNavigationMenu/UiNavigationMenu.stories.ts +1196 -0
  8. package/src/components/UiNavigationMenu/UiNavigationMenu.vue +39 -0
  9. package/src/components/UiNavigationMenu/UiNavigationMenuContent.vue +25 -0
  10. package/src/components/UiNavigationMenu/UiNavigationMenuIndicator.vue +14 -0
  11. package/src/components/UiNavigationMenu/UiNavigationMenuItem.vue +16 -0
  12. package/src/components/UiNavigationMenu/UiNavigationMenuLink.vue +27 -0
  13. package/src/components/UiNavigationMenu/UiNavigationMenuList.vue +16 -0
  14. package/src/components/UiNavigationMenu/UiNavigationMenuTrigger.vue +16 -0
  15. package/src/components/UiNavigationMenu/__tests__/UiNavigationMenu.test.ts +428 -0
  16. package/src/components/UiNavigationMenu/index.ts +11 -0
  17. package/src/components/UiNavigationMenu/types.ts +185 -0
  18. package/src/components/UiSheet/UiSheet.stories.ts +715 -0
  19. package/src/components/UiSheet/__tests__/UiSheet.test.ts +229 -0
  20. package/src/components/UiSheet/index.ts +12 -0
  21. package/src/components/UiSheet/types.ts +83 -0
  22. package/src/components/UiSidebar/UiSidebar.stories.ts +1010 -0
  23. package/src/components/UiSidebar/UiSidebar.vue +20 -0
  24. package/src/components/UiSidebar/UiSidebarGroupAction.vue +18 -0
  25. package/src/components/UiSidebar/UiSidebarGroupLabel.vue +18 -0
  26. package/src/components/UiSidebar/UiSidebarHeaderTrigger.vue +53 -0
  27. package/src/components/UiSidebar/UiSidebarInput.vue +14 -0
  28. package/src/components/UiSidebar/UiSidebarMenuAction.vue +19 -0
  29. package/src/components/UiSidebar/UiSidebarMenuButton.vue +27 -0
  30. package/src/components/UiSidebar/UiSidebarMenuSkeleton.vue +16 -0
  31. package/src/components/UiSidebar/UiSidebarMenuSubButton.vue +24 -0
  32. package/src/components/UiSidebar/UiSidebarProvider.vue +18 -0
  33. package/src/components/UiSidebar/UiSidebarSeparator.vue +13 -0
  34. package/src/components/UiSidebar/__tests__/UiSidebar.test.ts +221 -0
  35. package/src/components/UiSidebar/index.ts +34 -0
  36. package/src/components/UiSidebar/types.ts +168 -0
  37. package/src/components/UiStepper/UiStepper.stories.ts +425 -0
  38. package/src/components/UiStepper/UiStepper.vue +27 -0
  39. package/src/components/UiStepper/UiStepperDescription.vue +20 -0
  40. package/src/components/UiStepper/UiStepperIndicator.vue +13 -0
  41. package/src/components/UiStepper/UiStepperItem.vue +25 -0
  42. package/src/components/UiStepper/UiStepperSeparator.vue +17 -0
  43. package/src/components/UiStepper/UiStepperTitle.vue +19 -0
  44. package/src/components/UiStepper/UiStepperTrigger.vue +18 -0
  45. package/src/components/UiStepper/__tests__/UiStepper.test.ts +167 -0
  46. package/src/components/UiStepper/index.ts +9 -0
  47. package/src/components/UiStepper/types.ts +65 -0
  48. package/src/components/core/alert/index.ts +2 -2
  49. package/src/components/core/alert-dialog/AlertDialogContent.vue +1 -1
  50. package/src/components/core/card/Card.vue +1 -1
  51. package/src/components/core/drawer/DrawerContent.vue +1 -1
  52. package/src/components/core/dropdown-menu/DropdownMenuContent.vue +1 -1
  53. package/src/components/core/dropdown-menu/DropdownMenuSubContent.vue +1 -1
  54. package/src/components/core/input/Input.vue +1 -1
  55. package/src/components/core/native-select/NativeSelect.vue +1 -1
  56. package/src/components/core/native-select/NativeSelectOptGroup.vue +1 -1
  57. package/src/components/core/native-select/NativeSelectOption.vue +1 -1
  58. package/src/components/core/navigation-menu/NavigationMenu.vue +40 -0
  59. package/src/components/core/navigation-menu/NavigationMenuContent.vue +28 -0
  60. package/src/components/core/navigation-menu/NavigationMenuIndicator.vue +26 -0
  61. package/src/components/core/navigation-menu/NavigationMenuItem.vue +19 -0
  62. package/src/components/core/navigation-menu/NavigationMenuLink.vue +27 -0
  63. package/src/components/core/navigation-menu/NavigationMenuList.vue +21 -0
  64. package/src/components/core/navigation-menu/NavigationMenuTrigger.vue +27 -0
  65. package/src/components/core/navigation-menu/NavigationMenuViewport.vue +26 -0
  66. package/src/components/core/navigation-menu/index.ts +14 -0
  67. package/src/components/core/popover/PopoverContent.vue +1 -1
  68. package/src/components/core/select/SelectContent.vue +1 -1
  69. package/src/components/core/select/SelectTrigger.vue +1 -1
  70. package/src/components/core/sheet/Sheet.vue +15 -0
  71. package/src/components/core/sheet/SheetClose.vue +12 -0
  72. package/src/components/core/sheet/SheetContent.vue +56 -0
  73. package/src/components/core/sheet/SheetDescription.vue +19 -0
  74. package/src/components/core/sheet/SheetFooter.vue +9 -0
  75. package/src/components/core/sheet/SheetHeader.vue +9 -0
  76. package/src/components/core/sheet/SheetOverlay.vue +24 -0
  77. package/src/components/core/sheet/SheetTitle.vue +19 -0
  78. package/src/components/core/sheet/SheetTrigger.vue +12 -0
  79. package/src/components/core/sheet/index.ts +8 -0
  80. package/src/components/core/sidebar/Sidebar.vue +105 -0
  81. package/src/components/core/sidebar/SidebarContent.vue +21 -0
  82. package/src/components/core/sidebar/SidebarFooter.vue +16 -0
  83. package/src/components/core/sidebar/SidebarGroup.vue +16 -0
  84. package/src/components/core/sidebar/SidebarGroupAction.vue +25 -0
  85. package/src/components/core/sidebar/SidebarGroupContent.vue +16 -0
  86. package/src/components/core/sidebar/SidebarGroupLabel.vue +23 -0
  87. package/src/components/core/sidebar/SidebarHeader.vue +16 -0
  88. package/src/components/core/sidebar/SidebarInput.vue +17 -0
  89. package/src/components/core/sidebar/SidebarInset.vue +21 -0
  90. package/src/components/core/sidebar/SidebarMenu.vue +16 -0
  91. package/src/components/core/sidebar/SidebarMenuAction.vue +33 -0
  92. package/src/components/core/sidebar/SidebarMenuBadge.vue +26 -0
  93. package/src/components/core/sidebar/SidebarMenuButton.vue +49 -0
  94. package/src/components/core/sidebar/SidebarMenuButtonChild.vue +36 -0
  95. package/src/components/core/sidebar/SidebarMenuItem.vue +16 -0
  96. package/src/components/core/sidebar/SidebarMenuSkeleton.vue +32 -0
  97. package/src/components/core/sidebar/SidebarMenuSub.vue +22 -0
  98. package/src/components/core/sidebar/SidebarMenuSubButton.vue +38 -0
  99. package/src/components/core/sidebar/SidebarMenuSubItem.vue +16 -0
  100. package/src/components/core/sidebar/SidebarProvider.vue +102 -0
  101. package/src/components/core/sidebar/SidebarRail.vue +33 -0
  102. package/src/components/core/sidebar/SidebarSeparator.vue +17 -0
  103. package/src/components/core/sidebar/SidebarTrigger.vue +25 -0
  104. package/src/components/core/sidebar/index.ts +58 -0
  105. package/src/components/core/sidebar/utils.ts +19 -0
  106. package/src/components/core/stepper/Stepper.vue +20 -0
  107. package/src/components/core/stepper/StepperDescription.vue +23 -0
  108. package/src/components/core/stepper/StepperIndicator.vue +34 -0
  109. package/src/components/core/stepper/StepperItem.vue +23 -0
  110. package/src/components/core/stepper/StepperSeparator.vue +29 -0
  111. package/src/components/core/stepper/StepperTitle.vue +24 -0
  112. package/src/components/core/stepper/StepperTrigger.vue +22 -0
  113. package/src/components/core/stepper/index.ts +7 -0
  114. package/src/components/core/tabs/TabsTrigger.vue +1 -1
  115. package/src/components/core/tags-input/TagsInput.vue +1 -1
  116. package/src/components/core/textarea/Textarea.vue +1 -1
  117. package/src/components/index.ts +4 -0
  118. package/src/theme/Background.stories.ts +84 -35
  119. package/src/theme/Extended.stories.ts +4 -4
  120. package/tokens.json +145 -8
@@ -0,0 +1,12 @@
1
+ <script setup lang="ts">
2
+ import type { DialogCloseProps } from 'reka-ui';
3
+ import { DialogClose } from 'reka-ui';
4
+
5
+ const props = defineProps<DialogCloseProps>();
6
+ </script>
7
+
8
+ <template>
9
+ <DialogClose data-slot="sheet-close" v-bind="props">
10
+ <slot />
11
+ </DialogClose>
12
+ </template>
@@ -0,0 +1,56 @@
1
+ <script setup lang="ts">
2
+ import type { DialogContentEmits, DialogContentProps } from 'reka-ui';
3
+ import { X } from 'lucide-vue-next';
4
+ import { DialogClose, DialogContent, DialogPortal, useForwardPropsEmits } from 'reka-ui';
5
+ import { cn } from '@/lib/utils';
6
+ import SheetOverlay from './SheetOverlay.vue';
7
+
8
+ const props = withDefaults(
9
+ defineProps<
10
+ DialogContentProps & {
11
+ side?: 'top' | 'right' | 'bottom' | 'left';
12
+ closeLabel?: string;
13
+ }
14
+ >(),
15
+ {
16
+ side: 'right',
17
+ closeLabel: 'Close',
18
+ },
19
+ );
20
+ const emits = defineEmits<DialogContentEmits>();
21
+
22
+ const forwarded = useForwardPropsEmits(props, emits);
23
+ </script>
24
+
25
+ <template>
26
+ <DialogPortal>
27
+ <SheetOverlay />
28
+ <DialogContent
29
+ data-slot="sheet-content"
30
+ :class="
31
+ cn(
32
+ 'bg-background-surface-modal data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500',
33
+ props.side === 'right' &&
34
+ 'data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l border-border-surface-default sm:max-w-sm',
35
+ props.side === 'left' &&
36
+ 'data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r border-border-surface-default sm:max-w-sm',
37
+ props.side === 'top' &&
38
+ 'data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b border-border-surface-default',
39
+ props.side === 'bottom' &&
40
+ 'data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t border-border-surface-default',
41
+ $attrs.class ?? '',
42
+ )
43
+ "
44
+ v-bind="forwarded"
45
+ >
46
+ <slot />
47
+
48
+ <DialogClose
49
+ class="ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none"
50
+ >
51
+ <X class="size-4" />
52
+ <span class="sr-only">{{ props.closeLabel }}</span>
53
+ </DialogClose>
54
+ </DialogContent>
55
+ </DialogPortal>
56
+ </template>
@@ -0,0 +1,19 @@
1
+ <script setup lang="ts">
2
+ import type { DialogDescriptionProps } from 'reka-ui';
3
+ import { DialogDescription, useForwardProps } from 'reka-ui';
4
+ import { cn } from '@/lib/utils';
5
+
6
+ const props = defineProps<DialogDescriptionProps>();
7
+
8
+ const forwarded = useForwardProps(props);
9
+ </script>
10
+
11
+ <template>
12
+ <DialogDescription
13
+ data-slot="sheet-description"
14
+ :class="cn('text-muted-foreground text-sm', $attrs.class ?? '')"
15
+ v-bind="forwarded"
16
+ >
17
+ <slot />
18
+ </DialogDescription>
19
+ </template>
@@ -0,0 +1,9 @@
1
+ <script setup lang="ts">
2
+ import { cn } from '@/lib/utils';
3
+ </script>
4
+
5
+ <template>
6
+ <div data-slot="sheet-footer" :class="cn('mt-auto flex flex-col gap-2 p-4', $attrs.class ?? '')">
7
+ <slot />
8
+ </div>
9
+ </template>
@@ -0,0 +1,9 @@
1
+ <script setup lang="ts">
2
+ import { cn } from '@/lib/utils';
3
+ </script>
4
+
5
+ <template>
6
+ <div data-slot="sheet-header" :class="cn('flex flex-col gap-1.5 p-4', $attrs.class ?? '')">
7
+ <slot />
8
+ </div>
9
+ </template>
@@ -0,0 +1,24 @@
1
+ <script setup lang="ts">
2
+ import type { DialogOverlayProps } from 'reka-ui';
3
+ import { DialogOverlay, useForwardProps } from 'reka-ui';
4
+ import { cn } from '@/lib/utils';
5
+
6
+ const props = defineProps<DialogOverlayProps>();
7
+
8
+ const forwarded = useForwardProps(props);
9
+ </script>
10
+
11
+ <template>
12
+ <DialogOverlay
13
+ data-slot="sheet-overlay"
14
+ :class="
15
+ cn(
16
+ 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-modal-overlay',
17
+ $attrs.class ?? '',
18
+ )
19
+ "
20
+ v-bind="forwarded"
21
+ >
22
+ <slot />
23
+ </DialogOverlay>
24
+ </template>
@@ -0,0 +1,19 @@
1
+ <script setup lang="ts">
2
+ import type { DialogTitleProps } from 'reka-ui';
3
+ import { DialogTitle, useForwardProps } from 'reka-ui';
4
+ import { cn } from '@/lib/utils';
5
+
6
+ const props = defineProps<DialogTitleProps>();
7
+
8
+ const forwarded = useForwardProps(props);
9
+ </script>
10
+
11
+ <template>
12
+ <DialogTitle
13
+ data-slot="sheet-title"
14
+ :class="cn('text-foreground font-semibold', $attrs.class ?? '')"
15
+ v-bind="forwarded"
16
+ >
17
+ <slot />
18
+ </DialogTitle>
19
+ </template>
@@ -0,0 +1,12 @@
1
+ <script setup lang="ts">
2
+ import type { DialogTriggerProps } from 'reka-ui';
3
+ import { DialogTrigger } from 'reka-ui';
4
+
5
+ const props = defineProps<DialogTriggerProps>();
6
+ </script>
7
+
8
+ <template>
9
+ <DialogTrigger data-slot="sheet-trigger" v-bind="props">
10
+ <slot />
11
+ </DialogTrigger>
12
+ </template>
@@ -0,0 +1,8 @@
1
+ export { default as Sheet } from './Sheet.vue';
2
+ export { default as SheetClose } from './SheetClose.vue';
3
+ export { default as SheetContent } from './SheetContent.vue';
4
+ export { default as SheetDescription } from './SheetDescription.vue';
5
+ export { default as SheetFooter } from './SheetFooter.vue';
6
+ export { default as SheetHeader } from './SheetHeader.vue';
7
+ export { default as SheetTitle } from './SheetTitle.vue';
8
+ export { default as SheetTrigger } from './SheetTrigger.vue';
@@ -0,0 +1,105 @@
1
+ <script setup lang="ts">
2
+ import type { SidebarProps } from '.';
3
+ import { cn } from '@/lib/utils';
4
+ import { Sheet, SheetContent } from '@/components/core/sheet';
5
+ import SheetDescription from '@/components/core/sheet/SheetDescription.vue';
6
+ import SheetHeader from '@/components/core/sheet/SheetHeader.vue';
7
+ import SheetTitle from '@/components/core/sheet/SheetTitle.vue';
8
+ import { SIDEBAR_WIDTH_MOBILE, useSidebar } from './utils';
9
+
10
+ defineOptions({
11
+ inheritAttrs: false,
12
+ });
13
+
14
+ const props = withDefaults(defineProps<SidebarProps>(), {
15
+ side: 'left',
16
+ variant: 'sidebar',
17
+ collapsible: 'offcanvas',
18
+ });
19
+
20
+ const { isMobile, state, openMobile, setOpenMobile } = useSidebar();
21
+ </script>
22
+
23
+ <template>
24
+ <div
25
+ v-if="collapsible === 'none'"
26
+ data-slot="sidebar"
27
+ :class="
28
+ cn(
29
+ 'bg-sidebar text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col',
30
+ $attrs.class ?? '',
31
+ )
32
+ "
33
+ v-bind="$attrs"
34
+ >
35
+ <slot />
36
+ </div>
37
+
38
+ <Sheet v-else-if="isMobile" :open="openMobile" v-bind="$attrs" @update:open="setOpenMobile">
39
+ <SheetContent
40
+ data-sidebar="sidebar"
41
+ data-slot="sidebar"
42
+ data-mobile="true"
43
+ :side="side"
44
+ class="bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden"
45
+ :style="{
46
+ '--sidebar-width': SIDEBAR_WIDTH_MOBILE,
47
+ }"
48
+ >
49
+ <SheetHeader class="sr-only">
50
+ <SheetTitle>Sidebar</SheetTitle>
51
+ <SheetDescription>Displays the mobile sidebar.</SheetDescription>
52
+ </SheetHeader>
53
+ <div class="flex h-full w-full flex-col">
54
+ <slot />
55
+ </div>
56
+ </SheetContent>
57
+ </Sheet>
58
+
59
+ <div
60
+ v-else
61
+ class="group peer text-sidebar-foreground hidden md:block"
62
+ data-slot="sidebar"
63
+ :data-state="state"
64
+ :data-collapsible="state === 'collapsed' ? collapsible : ''"
65
+ :data-variant="variant"
66
+ :data-side="side"
67
+ >
68
+ <!-- This is what handles the sidebar gap on desktop -->
69
+ <div
70
+ :class="
71
+ cn(
72
+ 'relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear',
73
+ 'group-data-[collapsible=offcanvas]:w-0',
74
+ 'group-data-[side=right]:rotate-180',
75
+ variant === 'floating' || variant === 'inset'
76
+ ? 'group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]'
77
+ : 'group-data-[collapsible=icon]:w-(--sidebar-width-icon)',
78
+ )
79
+ "
80
+ />
81
+ <div
82
+ :class="
83
+ cn(
84
+ 'fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex',
85
+ side === 'left'
86
+ ? 'left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]'
87
+ : 'right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]',
88
+ // Adjust the padding for floating and inset variants.
89
+ variant === 'floating' || variant === 'inset'
90
+ ? 'p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]'
91
+ : 'group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l',
92
+ $attrs.class ?? '',
93
+ )
94
+ "
95
+ v-bind="$attrs"
96
+ >
97
+ <div
98
+ data-sidebar="sidebar"
99
+ class="bg-sidebar group-data-[variant=floating]:border-sidebar-border flex h-full w-full flex-col group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow-sm"
100
+ >
101
+ <slot />
102
+ </div>
103
+ </div>
104
+ </div>
105
+ </template>
@@ -0,0 +1,21 @@
1
+ <script setup lang="ts">
2
+ import { cn } from '@/lib/utils';
3
+
4
+ defineOptions({ inheritAttrs: false });
5
+ </script>
6
+
7
+ <template>
8
+ <div
9
+ v-bind="$attrs"
10
+ data-slot="sidebar-content"
11
+ data-sidebar="content"
12
+ :class="
13
+ cn(
14
+ 'flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden',
15
+ $attrs.class ?? '',
16
+ )
17
+ "
18
+ >
19
+ <slot />
20
+ </div>
21
+ </template>
@@ -0,0 +1,16 @@
1
+ <script setup lang="ts">
2
+ import { cn } from '@/lib/utils';
3
+
4
+ defineOptions({ inheritAttrs: false });
5
+ </script>
6
+
7
+ <template>
8
+ <div
9
+ v-bind="$attrs"
10
+ data-slot="sidebar-footer"
11
+ data-sidebar="footer"
12
+ :class="cn('flex flex-col gap-2 p-2', $attrs.class ?? '')"
13
+ >
14
+ <slot />
15
+ </div>
16
+ </template>
@@ -0,0 +1,16 @@
1
+ <script setup lang="ts">
2
+ import { cn } from '@/lib/utils';
3
+
4
+ defineOptions({ inheritAttrs: false });
5
+ </script>
6
+
7
+ <template>
8
+ <div
9
+ v-bind="$attrs"
10
+ data-slot="sidebar-group"
11
+ data-sidebar="group"
12
+ :class="cn('relative flex w-full min-w-0 flex-col p-2', $attrs.class ?? '')"
13
+ >
14
+ <slot />
15
+ </div>
16
+ </template>
@@ -0,0 +1,25 @@
1
+ <script setup lang="ts">
2
+ import { Primitive } from 'reka-ui';
3
+ import { cn } from '@/lib/utils';
4
+
5
+ defineOptions({ inheritAttrs: false });
6
+ </script>
7
+
8
+ <template>
9
+ <Primitive
10
+ v-bind="$attrs"
11
+ :as="($attrs as any).as ?? 'button'"
12
+ data-slot="sidebar-group-action"
13
+ data-sidebar="group-action"
14
+ :class="
15
+ cn(
16
+ 'text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
17
+ 'after:absolute after:-inset-2 md:after:hidden',
18
+ 'group-data-[collapsible=icon]:hidden',
19
+ $attrs.class ?? '',
20
+ )
21
+ "
22
+ >
23
+ <slot />
24
+ </Primitive>
25
+ </template>
@@ -0,0 +1,16 @@
1
+ <script setup lang="ts">
2
+ import { cn } from '@/lib/utils';
3
+
4
+ defineOptions({ inheritAttrs: false });
5
+ </script>
6
+
7
+ <template>
8
+ <div
9
+ v-bind="$attrs"
10
+ data-slot="sidebar-group-content"
11
+ data-sidebar="group-content"
12
+ :class="cn('w-full text-sm', $attrs.class ?? '')"
13
+ >
14
+ <slot />
15
+ </div>
16
+ </template>
@@ -0,0 +1,23 @@
1
+ <script setup lang="ts">
2
+ import { Primitive } from 'reka-ui';
3
+ import { cn } from '@/lib/utils';
4
+
5
+ defineOptions({ inheritAttrs: false });
6
+ </script>
7
+
8
+ <template>
9
+ <Primitive
10
+ v-bind="$attrs"
11
+ data-slot="sidebar-group-label"
12
+ data-sidebar="group-label"
13
+ :class="
14
+ cn(
15
+ 'text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-hidden transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
16
+ 'group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0',
17
+ $attrs.class ?? '',
18
+ )
19
+ "
20
+ >
21
+ <slot />
22
+ </Primitive>
23
+ </template>
@@ -0,0 +1,16 @@
1
+ <script setup lang="ts">
2
+ import { cn } from '@/lib/utils';
3
+
4
+ defineOptions({ inheritAttrs: false });
5
+ </script>
6
+
7
+ <template>
8
+ <div
9
+ v-bind="$attrs"
10
+ data-slot="sidebar-header"
11
+ data-sidebar="header"
12
+ :class="cn('flex flex-col gap-2 p-2', $attrs.class ?? '')"
13
+ >
14
+ <slot />
15
+ </div>
16
+ </template>
@@ -0,0 +1,17 @@
1
+ <script setup lang="ts">
2
+ import { cn } from '@/lib/utils';
3
+ import { Input } from '@/components/core/input';
4
+
5
+ defineOptions({ inheritAttrs: false });
6
+ </script>
7
+
8
+ <template>
9
+ <Input
10
+ v-bind="$attrs"
11
+ data-slot="sidebar-input"
12
+ data-sidebar="input"
13
+ :class="cn('bg-background h-8 w-full shadow-none', $attrs.class ?? '')"
14
+ >
15
+ <slot />
16
+ </Input>
17
+ </template>
@@ -0,0 +1,21 @@
1
+ <script setup lang="ts">
2
+ import { cn } from '@/lib/utils';
3
+
4
+ defineOptions({ inheritAttrs: false });
5
+ </script>
6
+
7
+ <template>
8
+ <main
9
+ v-bind="$attrs"
10
+ data-slot="sidebar-inset"
11
+ :class="
12
+ cn(
13
+ 'bg-background relative flex w-full flex-1 flex-col',
14
+ 'md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2',
15
+ $attrs.class ?? '',
16
+ )
17
+ "
18
+ >
19
+ <slot />
20
+ </main>
21
+ </template>
@@ -0,0 +1,16 @@
1
+ <script setup lang="ts">
2
+ import { cn } from '@/lib/utils';
3
+
4
+ defineOptions({ inheritAttrs: false });
5
+ </script>
6
+
7
+ <template>
8
+ <ul
9
+ v-bind="$attrs"
10
+ data-slot="sidebar-menu"
11
+ data-sidebar="menu"
12
+ :class="cn('flex w-full min-w-0 flex-col gap-1', $attrs.class ?? '')"
13
+ >
14
+ <slot />
15
+ </ul>
16
+ </template>
@@ -0,0 +1,33 @@
1
+ <script setup lang="ts">
2
+ import { Primitive } from 'reka-ui';
3
+ import { cn } from '@/lib/utils';
4
+
5
+ defineOptions({ inheritAttrs: false });
6
+
7
+ const props = defineProps<{
8
+ showOnHover?: boolean;
9
+ }>();
10
+ </script>
11
+
12
+ <template>
13
+ <Primitive
14
+ v-bind="{ as: 'button', ...$attrs }"
15
+ data-slot="sidebar-menu-action"
16
+ data-sidebar="menu-action"
17
+ :class="
18
+ cn(
19
+ 'text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground peer-hover/menu-button:text-sidebar-accent-foreground absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
20
+ 'after:absolute after:-inset-2 md:after:hidden',
21
+ 'peer-data-[size=sm]/menu-button:top-1',
22
+ 'peer-data-[size=default]/menu-button:top-1.5',
23
+ 'peer-data-[size=lg]/menu-button:top-2.5',
24
+ 'group-data-[collapsible=icon]:hidden',
25
+ showOnHover &&
26
+ 'peer-data-[active=true]/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 md:opacity-0',
27
+ $attrs.class ?? '',
28
+ )
29
+ "
30
+ >
31
+ <slot />
32
+ </Primitive>
33
+ </template>
@@ -0,0 +1,26 @@
1
+ <script setup lang="ts">
2
+ import { cn } from '@/lib/utils';
3
+
4
+ defineOptions({ inheritAttrs: false });
5
+ </script>
6
+
7
+ <template>
8
+ <div
9
+ v-bind="$attrs"
10
+ data-slot="sidebar-menu-badge"
11
+ data-sidebar="menu-badge"
12
+ :class="
13
+ cn(
14
+ 'text-sidebar-foreground pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums select-none',
15
+ 'peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground',
16
+ 'peer-data-[size=sm]/menu-button:top-1',
17
+ 'peer-data-[size=default]/menu-button:top-1.5',
18
+ 'peer-data-[size=lg]/menu-button:top-2.5',
19
+ 'group-data-[collapsible=icon]:hidden',
20
+ $attrs.class ?? '',
21
+ )
22
+ "
23
+ >
24
+ <slot />
25
+ </div>
26
+ </template>
@@ -0,0 +1,49 @@
1
+ <script setup lang="ts">
2
+ import type { Component } from 'vue';
3
+ import type { SidebarMenuButtonProps } from './SidebarMenuButtonChild.vue';
4
+ import { reactiveOmit } from '@vueuse/core';
5
+ import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/core/tooltip';
6
+ import SidebarMenuButtonChild from './SidebarMenuButtonChild.vue';
7
+ import { useSidebar } from './utils';
8
+
9
+ defineOptions({
10
+ inheritAttrs: false,
11
+ });
12
+
13
+ const props = withDefaults(
14
+ defineProps<
15
+ SidebarMenuButtonProps & {
16
+ tooltip?: string | Component;
17
+ }
18
+ >(),
19
+ {
20
+ as: 'button',
21
+ variant: 'default',
22
+ size: 'default',
23
+ },
24
+ );
25
+
26
+ const { isMobile, state } = useSidebar();
27
+
28
+ const delegatedProps = reactiveOmit(props, 'tooltip');
29
+ </script>
30
+
31
+ <template>
32
+ <SidebarMenuButtonChild v-if="!tooltip" v-bind="{ ...delegatedProps, ...$attrs }">
33
+ <slot />
34
+ </SidebarMenuButtonChild>
35
+
36
+ <Tooltip v-else>
37
+ <TooltipTrigger as-child>
38
+ <SidebarMenuButtonChild v-bind="{ ...delegatedProps, ...$attrs }">
39
+ <slot />
40
+ </SidebarMenuButtonChild>
41
+ </TooltipTrigger>
42
+ <TooltipContent side="right" align="center" :hidden="state !== 'collapsed' || isMobile">
43
+ <template v-if="typeof tooltip === 'string'">
44
+ {{ tooltip }}
45
+ </template>
46
+ <component :is="tooltip" v-else />
47
+ </TooltipContent>
48
+ </Tooltip>
49
+ </template>
@@ -0,0 +1,36 @@
1
+ <script setup lang="ts">
2
+ import type { PrimitiveProps } from 'reka-ui';
3
+ import type { SidebarMenuButtonVariants } from '.';
4
+ import { Primitive } from 'reka-ui';
5
+ import { cn } from '@/lib/utils';
6
+ import { sidebarMenuButtonVariants } from '.';
7
+
8
+ defineOptions({ inheritAttrs: false });
9
+
10
+ export interface SidebarMenuButtonProps extends PrimitiveProps {
11
+ variant?: SidebarMenuButtonVariants['variant'];
12
+ size?: SidebarMenuButtonVariants['size'];
13
+ isActive?: boolean;
14
+ }
15
+
16
+ const props = withDefaults(defineProps<SidebarMenuButtonProps>(), {
17
+ as: 'button',
18
+ variant: 'default',
19
+ size: 'default',
20
+ });
21
+ </script>
22
+
23
+ <template>
24
+ <Primitive
25
+ v-bind="$attrs"
26
+ data-slot="sidebar-menu-button"
27
+ data-sidebar="menu-button"
28
+ :data-size="size"
29
+ :data-active="isActive"
30
+ :class="cn(sidebarMenuButtonVariants({ variant, size }), $attrs.class ?? '')"
31
+ :as="as"
32
+ :as-child="asChild"
33
+ >
34
+ <slot />
35
+ </Primitive>
36
+ </template>
@@ -0,0 +1,16 @@
1
+ <script setup lang="ts">
2
+ import { cn } from '@/lib/utils';
3
+
4
+ defineOptions({ inheritAttrs: false });
5
+ </script>
6
+
7
+ <template>
8
+ <li
9
+ v-bind="$attrs"
10
+ data-slot="sidebar-menu-item"
11
+ data-sidebar="menu-item"
12
+ :class="cn('group/menu-item relative', $attrs.class ?? '')"
13
+ >
14
+ <slot />
15
+ </li>
16
+ </template>