@aleph-alpha/ui-library 1.13.0 → 1.15.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.
- package/README.md +1 -1
- package/config.d.ts +18 -5
- package/config.js +95 -5
- package/dist/system/index.d.ts +1718 -236
- package/dist/system/lib.js +19726 -16529
- package/docs/public-docs/component-directory.md +13 -0
- package/docs/public-docs/contributing.md +11 -0
- package/docs/public-docs/external-links.md +16 -0
- package/docs/public-docs/foundations.md +25 -0
- package/docs/public-docs/getting-started-designers.md +17 -0
- package/docs/public-docs/index.md +5 -0
- package/docs/public-docs/quick-start.md +230 -0
- package/docs/public-docs/standards-guidelines.md +15 -0
- package/package.json +3 -2
- package/src/components/UiCalendar/UiCalendar.stories.ts +1 -4
- package/src/components/UiCalendar/types.ts +1 -1
- package/src/components/UiKbd/UiKbd.stories.ts +1 -1
- package/src/components/UiNavigationMenu/UiNavigationMenu.stories.ts +1196 -0
- package/src/components/UiNavigationMenu/UiNavigationMenu.vue +39 -0
- package/src/components/UiNavigationMenu/UiNavigationMenuContent.vue +25 -0
- package/src/components/UiNavigationMenu/UiNavigationMenuIndicator.vue +14 -0
- package/src/components/UiNavigationMenu/UiNavigationMenuItem.vue +16 -0
- package/src/components/UiNavigationMenu/UiNavigationMenuLink.vue +27 -0
- package/src/components/UiNavigationMenu/UiNavigationMenuList.vue +16 -0
- package/src/components/UiNavigationMenu/UiNavigationMenuTrigger.vue +16 -0
- package/src/components/UiNavigationMenu/__tests__/UiNavigationMenu.test.ts +428 -0
- package/src/components/UiNavigationMenu/index.ts +11 -0
- package/src/components/UiNavigationMenu/types.ts +185 -0
- package/src/components/UiRangeCalendar/UiRangeCalendar.stories.ts +2 -4
- package/src/components/UiRangeCalendar/types.ts +1 -1
- package/src/components/UiSheet/UiSheet.stories.ts +715 -0
- package/src/components/UiSheet/__tests__/UiSheet.test.ts +229 -0
- package/src/components/UiSheet/index.ts +12 -0
- package/src/components/UiSheet/types.ts +83 -0
- package/src/components/UiSidebar/UiSidebar.stories.ts +1188 -0
- package/src/components/UiSidebar/UiSidebar.vue +20 -0
- package/src/components/UiSidebar/UiSidebarGroupAction.vue +18 -0
- package/src/components/UiSidebar/UiSidebarGroupLabel.vue +18 -0
- package/src/components/UiSidebar/UiSidebarHeaderTrigger.vue +53 -0
- package/src/components/UiSidebar/UiSidebarInput.vue +14 -0
- package/src/components/UiSidebar/UiSidebarMenuAction.vue +19 -0
- package/src/components/UiSidebar/UiSidebarMenuButton.vue +27 -0
- package/src/components/UiSidebar/UiSidebarMenuSkeleton.vue +16 -0
- package/src/components/UiSidebar/UiSidebarMenuSubButton.vue +24 -0
- package/src/components/UiSidebar/UiSidebarProvider.vue +16 -0
- package/src/components/UiSidebar/UiSidebarSeparator.vue +13 -0
- package/src/components/UiSidebar/__tests__/UiSidebar.test.ts +221 -0
- package/src/components/UiSidebar/index.ts +34 -0
- package/src/components/UiSidebar/types.ts +165 -0
- package/src/components/UiStepper/UiStepper.stories.ts +425 -0
- package/src/components/UiStepper/UiStepper.vue +27 -0
- package/src/components/UiStepper/UiStepperDescription.vue +20 -0
- package/src/components/UiStepper/UiStepperIndicator.vue +13 -0
- package/src/components/UiStepper/UiStepperItem.vue +25 -0
- package/src/components/UiStepper/UiStepperSeparator.vue +17 -0
- package/src/components/UiStepper/UiStepperTitle.vue +19 -0
- package/src/components/UiStepper/UiStepperTrigger.vue +18 -0
- package/src/components/UiStepper/__tests__/UiStepper.test.ts +167 -0
- package/src/components/UiStepper/index.ts +9 -0
- package/src/components/UiStepper/types.ts +65 -0
- package/src/components/core/alert/index.ts +2 -2
- package/src/components/core/alert-dialog/AlertDialogContent.vue +1 -1
- package/src/components/core/calendar/Calendar.vue +1 -1
- package/src/components/core/card/Card.vue +1 -1
- package/src/components/core/drawer/DrawerContent.vue +1 -1
- package/src/components/core/dropdown-menu/DropdownMenuContent.vue +1 -1
- package/src/components/core/dropdown-menu/DropdownMenuSubContent.vue +1 -1
- package/src/components/core/input/Input.vue +1 -1
- package/src/components/core/native-select/NativeSelect.vue +1 -1
- package/src/components/core/native-select/NativeSelectOptGroup.vue +1 -1
- package/src/components/core/native-select/NativeSelectOption.vue +1 -1
- package/src/components/core/navigation-menu/NavigationMenu.vue +40 -0
- package/src/components/core/navigation-menu/NavigationMenuContent.vue +28 -0
- package/src/components/core/navigation-menu/NavigationMenuIndicator.vue +26 -0
- package/src/components/core/navigation-menu/NavigationMenuItem.vue +19 -0
- package/src/components/core/navigation-menu/NavigationMenuLink.vue +27 -0
- package/src/components/core/navigation-menu/NavigationMenuList.vue +21 -0
- package/src/components/core/navigation-menu/NavigationMenuTrigger.vue +27 -0
- package/src/components/core/navigation-menu/NavigationMenuViewport.vue +26 -0
- package/src/components/core/navigation-menu/index.ts +14 -0
- package/src/components/core/popover/PopoverContent.vue +1 -1
- package/src/components/core/range-calendar/RangeCalendar.vue +1 -1
- package/src/components/core/select/SelectContent.vue +1 -1
- package/src/components/core/select/SelectTrigger.vue +1 -1
- package/src/components/core/sheet/Sheet.vue +15 -0
- package/src/components/core/sheet/SheetClose.vue +12 -0
- package/src/components/core/sheet/SheetContent.vue +56 -0
- package/src/components/core/sheet/SheetDescription.vue +19 -0
- package/src/components/core/sheet/SheetFooter.vue +9 -0
- package/src/components/core/sheet/SheetHeader.vue +9 -0
- package/src/components/core/sheet/SheetOverlay.vue +24 -0
- package/src/components/core/sheet/SheetTitle.vue +19 -0
- package/src/components/core/sheet/SheetTrigger.vue +12 -0
- package/src/components/core/sheet/index.ts +8 -0
- package/src/components/core/sidebar/Sidebar.vue +105 -0
- package/src/components/core/sidebar/SidebarContent.vue +21 -0
- package/src/components/core/sidebar/SidebarFooter.vue +16 -0
- package/src/components/core/sidebar/SidebarGroup.vue +16 -0
- package/src/components/core/sidebar/SidebarGroupAction.vue +25 -0
- package/src/components/core/sidebar/SidebarGroupContent.vue +16 -0
- package/src/components/core/sidebar/SidebarGroupLabel.vue +23 -0
- package/src/components/core/sidebar/SidebarHeader.vue +16 -0
- package/src/components/core/sidebar/SidebarInput.vue +17 -0
- package/src/components/core/sidebar/SidebarInset.vue +21 -0
- package/src/components/core/sidebar/SidebarMenu.vue +16 -0
- package/src/components/core/sidebar/SidebarMenuAction.vue +33 -0
- package/src/components/core/sidebar/SidebarMenuBadge.vue +26 -0
- package/src/components/core/sidebar/SidebarMenuButton.vue +49 -0
- package/src/components/core/sidebar/SidebarMenuButtonChild.vue +36 -0
- package/src/components/core/sidebar/SidebarMenuItem.vue +16 -0
- package/src/components/core/sidebar/SidebarMenuSkeleton.vue +32 -0
- package/src/components/core/sidebar/SidebarMenuSub.vue +22 -0
- package/src/components/core/sidebar/SidebarMenuSubButton.vue +38 -0
- package/src/components/core/sidebar/SidebarMenuSubItem.vue +16 -0
- package/src/components/core/sidebar/SidebarProvider.vue +102 -0
- package/src/components/core/sidebar/SidebarRail.vue +33 -0
- package/src/components/core/sidebar/SidebarSeparator.vue +17 -0
- package/src/components/core/sidebar/SidebarTrigger.vue +25 -0
- package/src/components/core/sidebar/index.ts +58 -0
- package/src/components/core/sidebar/utils.ts +19 -0
- package/src/components/core/stepper/Stepper.vue +20 -0
- package/src/components/core/stepper/StepperDescription.vue +23 -0
- package/src/components/core/stepper/StepperIndicator.vue +34 -0
- package/src/components/core/stepper/StepperItem.vue +23 -0
- package/src/components/core/stepper/StepperSeparator.vue +29 -0
- package/src/components/core/stepper/StepperTitle.vue +24 -0
- package/src/components/core/stepper/StepperTrigger.vue +22 -0
- package/src/components/core/stepper/index.ts +7 -0
- package/src/components/core/tabs/TabsTrigger.vue +1 -1
- package/src/components/core/tags-input/TagsInput.vue +1 -1
- package/src/components/core/textarea/Textarea.vue +1 -1
- package/src/components/index.ts +4 -0
- package/src/patterns/UiDatePicker/UiDatePicker.stories.ts +1 -4
- package/src/patterns/UiDatePicker/types.ts +1 -1
- package/src/theme/Background.stories.ts +84 -35
- package/src/theme/Extended.stories.ts +4 -4
- package/tokens.json +145 -8
|
@@ -0,0 +1,1188 @@
|
|
|
1
|
+
import { ref, computed, defineComponent } from 'vue';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite';
|
|
3
|
+
import {
|
|
4
|
+
UiSidebar,
|
|
5
|
+
UiSidebarContent,
|
|
6
|
+
UiSidebarFooter,
|
|
7
|
+
UiSidebarGroup,
|
|
8
|
+
UiSidebarGroupAction,
|
|
9
|
+
UiSidebarGroupContent,
|
|
10
|
+
UiSidebarGroupLabel,
|
|
11
|
+
UiSidebarHeader,
|
|
12
|
+
UiSidebarHeaderTrigger,
|
|
13
|
+
UiSidebarInput,
|
|
14
|
+
UiSidebarInset,
|
|
15
|
+
UiSidebarMenu,
|
|
16
|
+
UiSidebarMenuAction,
|
|
17
|
+
UiSidebarMenuBadge,
|
|
18
|
+
UiSidebarMenuButton,
|
|
19
|
+
UiSidebarMenuItem,
|
|
20
|
+
UiSidebarMenuSkeleton,
|
|
21
|
+
UiSidebarMenuSub,
|
|
22
|
+
UiSidebarMenuSubButton,
|
|
23
|
+
UiSidebarMenuSubItem,
|
|
24
|
+
UiSidebarProvider,
|
|
25
|
+
UiSidebarRail,
|
|
26
|
+
UiSidebarSeparator,
|
|
27
|
+
UiSidebarTrigger,
|
|
28
|
+
useSidebar,
|
|
29
|
+
} from '.';
|
|
30
|
+
import { CollapsibleRoot, CollapsibleContent, CollapsibleTrigger } from 'reka-ui';
|
|
31
|
+
import {
|
|
32
|
+
Bot,
|
|
33
|
+
Database,
|
|
34
|
+
BarChart3,
|
|
35
|
+
MessageSquare,
|
|
36
|
+
Settings,
|
|
37
|
+
Command,
|
|
38
|
+
Plus,
|
|
39
|
+
MoreHorizontal,
|
|
40
|
+
FlaskConical,
|
|
41
|
+
Key,
|
|
42
|
+
Activity,
|
|
43
|
+
ChevronRight,
|
|
44
|
+
} from 'lucide-vue-next';
|
|
45
|
+
|
|
46
|
+
const meta: Meta<typeof UiSidebar> = {
|
|
47
|
+
title: 'Components/UiSidebar',
|
|
48
|
+
component: UiSidebar,
|
|
49
|
+
tags: ['autodocs'],
|
|
50
|
+
argTypes: {
|
|
51
|
+
side: {
|
|
52
|
+
control: 'select',
|
|
53
|
+
options: ['left', 'right'],
|
|
54
|
+
},
|
|
55
|
+
variant: {
|
|
56
|
+
control: 'select',
|
|
57
|
+
options: ['sidebar', 'floating', 'inset'],
|
|
58
|
+
description:
|
|
59
|
+
'`sidebar`: fixed with border. `floating`: shadow and rounded corners. `inset`: shares background with content.',
|
|
60
|
+
},
|
|
61
|
+
collapsible: {
|
|
62
|
+
control: 'select',
|
|
63
|
+
options: ['offcanvas', 'icon', 'none'],
|
|
64
|
+
description:
|
|
65
|
+
'`offcanvas`: slides completely off screen. `icon`: collapses to icon-only width. `none`: always expanded.',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
args: {
|
|
69
|
+
side: 'left',
|
|
70
|
+
variant: 'sidebar',
|
|
71
|
+
collapsible: 'icon',
|
|
72
|
+
},
|
|
73
|
+
parameters: {
|
|
74
|
+
layout: 'fullscreen',
|
|
75
|
+
},
|
|
76
|
+
decorators: [
|
|
77
|
+
() => ({
|
|
78
|
+
template: '<div class="-m-4"><story /></div>',
|
|
79
|
+
}),
|
|
80
|
+
],
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export default meta;
|
|
84
|
+
type Story = StoryObj<typeof UiSidebar>;
|
|
85
|
+
|
|
86
|
+
const defaultTemplateSource = `<script setup lang="ts">
|
|
87
|
+
import {
|
|
88
|
+
UiSidebar,
|
|
89
|
+
UiSidebarContent,
|
|
90
|
+
UiSidebarFooter,
|
|
91
|
+
UiSidebarGroup,
|
|
92
|
+
UiSidebarGroupContent,
|
|
93
|
+
UiSidebarGroupLabel,
|
|
94
|
+
UiSidebarHeaderTrigger,
|
|
95
|
+
UiSidebarInset,
|
|
96
|
+
UiSidebarMenu,
|
|
97
|
+
UiSidebarMenuBadge,
|
|
98
|
+
UiSidebarMenuButton,
|
|
99
|
+
UiSidebarMenuItem,
|
|
100
|
+
UiSidebarProvider,
|
|
101
|
+
UiSidebarRail,
|
|
102
|
+
} from '@aleph-alpha/ui-library'
|
|
103
|
+
import { Bot, Database, BarChart3, MessageSquare, Settings, Command } from 'lucide-vue-next'
|
|
104
|
+
|
|
105
|
+
const items = [
|
|
106
|
+
{ title: 'Playground', url: '#', icon: Bot, badge: null },
|
|
107
|
+
{ title: 'Models', url: '#', icon: Database, badge: '5' },
|
|
108
|
+
{ title: 'Evaluations', url: '#', icon: BarChart3, badge: '3' },
|
|
109
|
+
{ title: 'Conversations', url: '#', icon: MessageSquare, badge: null },
|
|
110
|
+
]
|
|
111
|
+
</script>
|
|
112
|
+
|
|
113
|
+
<template>
|
|
114
|
+
<UiSidebarProvider :default-open="false">
|
|
115
|
+
<UiSidebar>
|
|
116
|
+
<UiSidebarHeaderTrigger>
|
|
117
|
+
<template #logo>
|
|
118
|
+
<div class="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
|
|
119
|
+
<Command class="size-4" />
|
|
120
|
+
</div>
|
|
121
|
+
</template>
|
|
122
|
+
<span class="truncate font-semibold">Acme AI</span>
|
|
123
|
+
<span class="truncate text-xs">Enterprise</span>
|
|
124
|
+
</UiSidebarHeaderTrigger>
|
|
125
|
+
<UiSidebarContent>
|
|
126
|
+
<UiSidebarGroup>
|
|
127
|
+
<UiSidebarGroupLabel>Platform</UiSidebarGroupLabel>
|
|
128
|
+
<UiSidebarGroupContent>
|
|
129
|
+
<UiSidebarMenu>
|
|
130
|
+
<UiSidebarMenuItem v-for="item in items" :key="item.title">
|
|
131
|
+
<UiSidebarMenuButton :tooltip="item.title">
|
|
132
|
+
<component :is="item.icon" />
|
|
133
|
+
<span>{{ item.title }}</span>
|
|
134
|
+
</UiSidebarMenuButton>
|
|
135
|
+
<UiSidebarMenuBadge v-if="item.badge">
|
|
136
|
+
{{ item.badge }}
|
|
137
|
+
</UiSidebarMenuBadge>
|
|
138
|
+
</UiSidebarMenuItem>
|
|
139
|
+
</UiSidebarMenu>
|
|
140
|
+
</UiSidebarGroupContent>
|
|
141
|
+
</UiSidebarGroup>
|
|
142
|
+
</UiSidebarContent>
|
|
143
|
+
<UiSidebarFooter>
|
|
144
|
+
<UiSidebarMenu>
|
|
145
|
+
<UiSidebarMenuItem>
|
|
146
|
+
<UiSidebarMenuButton>
|
|
147
|
+
<Settings />
|
|
148
|
+
<span>Settings</span>
|
|
149
|
+
</UiSidebarMenuButton>
|
|
150
|
+
</UiSidebarMenuItem>
|
|
151
|
+
</UiSidebarMenu>
|
|
152
|
+
</UiSidebarFooter>
|
|
153
|
+
<UiSidebarRail />
|
|
154
|
+
</UiSidebar>
|
|
155
|
+
<UiSidebarInset>
|
|
156
|
+
<header class="flex h-16 shrink-0 items-center gap-2 border-b px-4">
|
|
157
|
+
<div class="flex items-center gap-1.5 text-sm">
|
|
158
|
+
<span class="text-muted-foreground">Platform</span>
|
|
159
|
+
<span class="text-muted-foreground">/</span>
|
|
160
|
+
<span class="font-medium">Playground</span>
|
|
161
|
+
</div>
|
|
162
|
+
</header>
|
|
163
|
+
<div class="flex flex-1 flex-col gap-4 p-4">
|
|
164
|
+
<div class="grid auto-rows-min gap-4 md:grid-cols-3">
|
|
165
|
+
<div class="aspect-video rounded-xl bg-muted" />
|
|
166
|
+
<div class="aspect-video rounded-xl bg-muted" />
|
|
167
|
+
<div class="aspect-video rounded-xl bg-muted" />
|
|
168
|
+
</div>
|
|
169
|
+
<div class="min-h-[50vh] flex-1 rounded-xl bg-muted" />
|
|
170
|
+
</div>
|
|
171
|
+
</UiSidebarInset>
|
|
172
|
+
</UiSidebarProvider>
|
|
173
|
+
</template>`;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* AI platform sidebar with a company header, icon-based navigation group with `UiSidebarMenuBadge` counters, footer, and inset content area with breadcrumb header.
|
|
177
|
+
* Uses `collapsible="icon"` — the sidebar collapses to a narrow icon-only rail. Menu items show only their icon with a tooltip on hover. Badges auto-hide in collapsed mode.
|
|
178
|
+
*/
|
|
179
|
+
export const Default: Story = {
|
|
180
|
+
render: (args) => ({
|
|
181
|
+
components: {
|
|
182
|
+
UiSidebar,
|
|
183
|
+
UiSidebarContent,
|
|
184
|
+
UiSidebarFooter,
|
|
185
|
+
UiSidebarGroup,
|
|
186
|
+
UiSidebarGroupContent,
|
|
187
|
+
UiSidebarGroupLabel,
|
|
188
|
+
UiSidebarHeaderTrigger,
|
|
189
|
+
UiSidebarInset,
|
|
190
|
+
UiSidebarMenu,
|
|
191
|
+
UiSidebarMenuBadge,
|
|
192
|
+
UiSidebarMenuButton,
|
|
193
|
+
UiSidebarMenuItem,
|
|
194
|
+
UiSidebarProvider,
|
|
195
|
+
UiSidebarRail,
|
|
196
|
+
Bot,
|
|
197
|
+
Database,
|
|
198
|
+
BarChart3,
|
|
199
|
+
MessageSquare,
|
|
200
|
+
Settings,
|
|
201
|
+
Command,
|
|
202
|
+
},
|
|
203
|
+
setup() {
|
|
204
|
+
const items = [
|
|
205
|
+
{ title: 'Playground', url: '#', icon: Bot, badge: null },
|
|
206
|
+
{ title: 'Models', url: '#', icon: Database, badge: '5' },
|
|
207
|
+
{ title: 'Evaluations', url: '#', icon: BarChart3, badge: '3' },
|
|
208
|
+
{ title: 'Conversations', url: '#', icon: MessageSquare, badge: null },
|
|
209
|
+
];
|
|
210
|
+
return { args, items };
|
|
211
|
+
},
|
|
212
|
+
template: `
|
|
213
|
+
<UiSidebarProvider :default-open="false">
|
|
214
|
+
<UiSidebar :side="args.side" :variant="args.variant" :collapsible="args.collapsible">
|
|
215
|
+
<UiSidebarHeaderTrigger>
|
|
216
|
+
<template #logo>
|
|
217
|
+
<div class="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
|
|
218
|
+
<Command class="size-4" />
|
|
219
|
+
</div>
|
|
220
|
+
</template>
|
|
221
|
+
<span class="truncate font-semibold">Acme AI</span>
|
|
222
|
+
<span class="truncate text-xs">Enterprise</span>
|
|
223
|
+
</UiSidebarHeaderTrigger>
|
|
224
|
+
<UiSidebarContent>
|
|
225
|
+
<UiSidebarGroup>
|
|
226
|
+
<UiSidebarGroupLabel>Platform</UiSidebarGroupLabel>
|
|
227
|
+
<UiSidebarGroupContent>
|
|
228
|
+
<UiSidebarMenu>
|
|
229
|
+
<UiSidebarMenuItem v-for="item in items" :key="item.title">
|
|
230
|
+
<UiSidebarMenuButton :tooltip="item.title">
|
|
231
|
+
<component :is="item.icon" />
|
|
232
|
+
<span>{{ item.title }}</span>
|
|
233
|
+
</UiSidebarMenuButton>
|
|
234
|
+
<UiSidebarMenuBadge v-if="item.badge">
|
|
235
|
+
{{ item.badge }}
|
|
236
|
+
</UiSidebarMenuBadge>
|
|
237
|
+
</UiSidebarMenuItem>
|
|
238
|
+
</UiSidebarMenu>
|
|
239
|
+
</UiSidebarGroupContent>
|
|
240
|
+
</UiSidebarGroup>
|
|
241
|
+
</UiSidebarContent>
|
|
242
|
+
<UiSidebarFooter>
|
|
243
|
+
<UiSidebarMenu>
|
|
244
|
+
<UiSidebarMenuItem>
|
|
245
|
+
<UiSidebarMenuButton>
|
|
246
|
+
<Settings />
|
|
247
|
+
<span>Settings</span>
|
|
248
|
+
</UiSidebarMenuButton>
|
|
249
|
+
</UiSidebarMenuItem>
|
|
250
|
+
</UiSidebarMenu>
|
|
251
|
+
</UiSidebarFooter>
|
|
252
|
+
<UiSidebarRail />
|
|
253
|
+
</UiSidebar>
|
|
254
|
+
<UiSidebarInset>
|
|
255
|
+
<header class="flex h-16 shrink-0 items-center gap-2 border-b px-4">
|
|
256
|
+
<div class="flex items-center gap-1.5 text-sm">
|
|
257
|
+
<span class="text-muted-foreground">Platform</span>
|
|
258
|
+
<span class="text-muted-foreground">/</span>
|
|
259
|
+
<span class="font-medium">Playground</span>
|
|
260
|
+
</div>
|
|
261
|
+
</header>
|
|
262
|
+
<div class="flex flex-1 flex-col gap-4 p-4">
|
|
263
|
+
<div class="grid auto-rows-min gap-4 md:grid-cols-3">
|
|
264
|
+
<div class="aspect-video rounded-xl bg-muted" />
|
|
265
|
+
<div class="aspect-video rounded-xl bg-muted" />
|
|
266
|
+
<div class="aspect-video rounded-xl bg-muted" />
|
|
267
|
+
</div>
|
|
268
|
+
<div class="min-h-[50vh] flex-1 rounded-xl bg-muted" />
|
|
269
|
+
</div>
|
|
270
|
+
</UiSidebarInset>
|
|
271
|
+
</UiSidebarProvider>
|
|
272
|
+
`,
|
|
273
|
+
}),
|
|
274
|
+
parameters: {
|
|
275
|
+
docs: {
|
|
276
|
+
source: {
|
|
277
|
+
code: defaultTemplateSource,
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
const withSearchTemplateSource = `<script setup lang="ts">
|
|
284
|
+
import { ref, computed } from 'vue'
|
|
285
|
+
import {
|
|
286
|
+
UiSidebar,
|
|
287
|
+
UiSidebarContent,
|
|
288
|
+
UiSidebarGroup,
|
|
289
|
+
UiSidebarGroupContent,
|
|
290
|
+
UiSidebarGroupLabel,
|
|
291
|
+
UiSidebarHeader,
|
|
292
|
+
UiSidebarInput,
|
|
293
|
+
UiSidebarInset,
|
|
294
|
+
UiSidebarMenu,
|
|
295
|
+
UiSidebarMenuButton,
|
|
296
|
+
UiSidebarMenuItem,
|
|
297
|
+
UiSidebarProvider,
|
|
298
|
+
UiSidebarTrigger,
|
|
299
|
+
} from '@aleph-alpha/ui-library'
|
|
300
|
+
import { Command } from 'lucide-vue-next'
|
|
301
|
+
|
|
302
|
+
const groups = [
|
|
303
|
+
{
|
|
304
|
+
label: 'Getting Started',
|
|
305
|
+
items: ['Quick Start', 'Authentication', 'API Keys'],
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
label: 'Models',
|
|
309
|
+
items: ['Completions', 'Embeddings', 'Chat', 'Multimodal'],
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
label: 'Advanced',
|
|
313
|
+
items: ['Fine-tuning', 'Prompt Engineering', 'Evaluation', 'RAG'],
|
|
314
|
+
},
|
|
315
|
+
]
|
|
316
|
+
|
|
317
|
+
const query = ref('')
|
|
318
|
+
const filteredGroups = computed(() =>
|
|
319
|
+
groups
|
|
320
|
+
.map(group => ({
|
|
321
|
+
...group,
|
|
322
|
+
items: group.items.filter(item =>
|
|
323
|
+
item.toLowerCase().includes(query.value.toLowerCase())
|
|
324
|
+
),
|
|
325
|
+
}))
|
|
326
|
+
.filter(group => group.items.length > 0)
|
|
327
|
+
)
|
|
328
|
+
</script>
|
|
329
|
+
|
|
330
|
+
<template>
|
|
331
|
+
<UiSidebarProvider :default-open="true">
|
|
332
|
+
<UiSidebar>
|
|
333
|
+
<UiSidebarHeader>
|
|
334
|
+
<UiSidebarMenu>
|
|
335
|
+
<UiSidebarMenuItem>
|
|
336
|
+
<UiSidebarMenuButton size="lg">
|
|
337
|
+
<div class="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
|
|
338
|
+
<Command class="size-4" />
|
|
339
|
+
</div>
|
|
340
|
+
<div class="grid flex-1 text-left text-sm leading-tight">
|
|
341
|
+
<span class="truncate font-semibold">API Docs</span>
|
|
342
|
+
<span class="truncate text-xs">v2.0.0</span>
|
|
343
|
+
</div>
|
|
344
|
+
</UiSidebarMenuButton>
|
|
345
|
+
</UiSidebarMenuItem>
|
|
346
|
+
</UiSidebarMenu>
|
|
347
|
+
<UiSidebarInput v-model="query" placeholder="Search the docs..." />
|
|
348
|
+
</UiSidebarHeader>
|
|
349
|
+
<UiSidebarContent>
|
|
350
|
+
<UiSidebarGroup v-for="group in filteredGroups" :key="group.label">
|
|
351
|
+
<UiSidebarGroupLabel>{{ group.label }}</UiSidebarGroupLabel>
|
|
352
|
+
<UiSidebarGroupContent>
|
|
353
|
+
<UiSidebarMenu>
|
|
354
|
+
<UiSidebarMenuItem v-for="item in group.items" :key="item">
|
|
355
|
+
<UiSidebarMenuButton>{{ item }}</UiSidebarMenuButton>
|
|
356
|
+
</UiSidebarMenuItem>
|
|
357
|
+
</UiSidebarMenu>
|
|
358
|
+
</UiSidebarGroupContent>
|
|
359
|
+
</UiSidebarGroup>
|
|
360
|
+
</UiSidebarContent>
|
|
361
|
+
</UiSidebar>
|
|
362
|
+
<UiSidebarInset>
|
|
363
|
+
<header class="flex h-16 shrink-0 items-center gap-2 border-b px-4">
|
|
364
|
+
<UiSidebarTrigger class="-ml-1" />
|
|
365
|
+
<span class="text-sm font-medium">API Documentation</span>
|
|
366
|
+
</header>
|
|
367
|
+
</UiSidebarInset>
|
|
368
|
+
</UiSidebarProvider>
|
|
369
|
+
</template>`;
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Documentation-style sidebar with `UiSidebarInput` that filters navigation items across multiple groups (Models, Advanced, etc.).
|
|
373
|
+
* Uses `collapsible="offcanvas"` — the sidebar slides completely off screen when closed, since text-only items have no icon representation for icon-collapse mode.
|
|
374
|
+
*/
|
|
375
|
+
export const WithSearch: Story = {
|
|
376
|
+
render: (args) => ({
|
|
377
|
+
components: {
|
|
378
|
+
UiSidebar,
|
|
379
|
+
UiSidebarContent,
|
|
380
|
+
UiSidebarGroup,
|
|
381
|
+
UiSidebarGroupContent,
|
|
382
|
+
UiSidebarGroupLabel,
|
|
383
|
+
UiSidebarHeader,
|
|
384
|
+
UiSidebarInput,
|
|
385
|
+
UiSidebarInset,
|
|
386
|
+
UiSidebarMenu,
|
|
387
|
+
UiSidebarMenuButton,
|
|
388
|
+
UiSidebarMenuItem,
|
|
389
|
+
UiSidebarProvider,
|
|
390
|
+
UiSidebarTrigger,
|
|
391
|
+
Command,
|
|
392
|
+
},
|
|
393
|
+
setup() {
|
|
394
|
+
const groups = [
|
|
395
|
+
{
|
|
396
|
+
label: 'Getting Started',
|
|
397
|
+
items: ['Quick Start', 'Authentication', 'API Keys'],
|
|
398
|
+
},
|
|
399
|
+
{
|
|
400
|
+
label: 'Models',
|
|
401
|
+
items: ['Completions', 'Embeddings', 'Chat', 'Multimodal'],
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
label: 'Advanced',
|
|
405
|
+
items: ['Fine-tuning', 'Prompt Engineering', 'Evaluation', 'RAG'],
|
|
406
|
+
},
|
|
407
|
+
];
|
|
408
|
+
const query = ref('');
|
|
409
|
+
const matchesQuery = (item: string) => item.toLowerCase().includes(query.value.toLowerCase());
|
|
410
|
+
const filteredGroups = computed(() =>
|
|
411
|
+
groups
|
|
412
|
+
.map((group) => ({ ...group, items: group.items.filter(matchesQuery) }))
|
|
413
|
+
.filter((group) => group.items.length > 0),
|
|
414
|
+
);
|
|
415
|
+
return { args, query, filteredGroups };
|
|
416
|
+
},
|
|
417
|
+
template: `
|
|
418
|
+
<UiSidebarProvider :default-open="true">
|
|
419
|
+
<UiSidebar :side="args.side" :variant="args.variant" :collapsible="args.collapsible">
|
|
420
|
+
<UiSidebarHeader>
|
|
421
|
+
<UiSidebarMenu>
|
|
422
|
+
<UiSidebarMenuItem>
|
|
423
|
+
<UiSidebarMenuButton size="lg">
|
|
424
|
+
<div class="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
|
|
425
|
+
<Command class="size-4" />
|
|
426
|
+
</div>
|
|
427
|
+
<div class="grid flex-1 text-left text-sm leading-tight">
|
|
428
|
+
<span class="truncate font-semibold">API Docs</span>
|
|
429
|
+
<span class="truncate text-xs">v2.0.0</span>
|
|
430
|
+
</div>
|
|
431
|
+
</UiSidebarMenuButton>
|
|
432
|
+
</UiSidebarMenuItem>
|
|
433
|
+
</UiSidebarMenu>
|
|
434
|
+
<UiSidebarInput v-model="query" placeholder="Search the docs..." class="group-data-[collapsible=icon]:hidden" />
|
|
435
|
+
</UiSidebarHeader>
|
|
436
|
+
<UiSidebarContent>
|
|
437
|
+
<UiSidebarGroup v-for="group in filteredGroups" :key="group.label">
|
|
438
|
+
<UiSidebarGroupLabel>{{ group.label }}</UiSidebarGroupLabel>
|
|
439
|
+
<UiSidebarGroupContent>
|
|
440
|
+
<UiSidebarMenu>
|
|
441
|
+
<UiSidebarMenuItem v-for="item in group.items" :key="item">
|
|
442
|
+
<UiSidebarMenuButton>{{ item }}</UiSidebarMenuButton>
|
|
443
|
+
</UiSidebarMenuItem>
|
|
444
|
+
</UiSidebarMenu>
|
|
445
|
+
</UiSidebarGroupContent>
|
|
446
|
+
</UiSidebarGroup>
|
|
447
|
+
</UiSidebarContent>
|
|
448
|
+
</UiSidebar>
|
|
449
|
+
<UiSidebarInset>
|
|
450
|
+
<header class="flex h-16 shrink-0 items-center gap-2 border-b px-4">
|
|
451
|
+
<UiSidebarTrigger class="-ml-1" />
|
|
452
|
+
<span class="text-sm font-medium">API Documentation</span>
|
|
453
|
+
</header>
|
|
454
|
+
</UiSidebarInset>
|
|
455
|
+
</UiSidebarProvider>
|
|
456
|
+
`,
|
|
457
|
+
}),
|
|
458
|
+
args: {
|
|
459
|
+
collapsible: 'offcanvas',
|
|
460
|
+
},
|
|
461
|
+
parameters: {
|
|
462
|
+
docs: {
|
|
463
|
+
source: {
|
|
464
|
+
code: withSearchTemplateSource,
|
|
465
|
+
},
|
|
466
|
+
},
|
|
467
|
+
},
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
const withActionsTemplateSource = `<script setup lang="ts">
|
|
471
|
+
import { ref } from 'vue'
|
|
472
|
+
import {
|
|
473
|
+
UiSidebar,
|
|
474
|
+
UiSidebarContent,
|
|
475
|
+
UiSidebarGroup,
|
|
476
|
+
UiSidebarGroupAction,
|
|
477
|
+
UiSidebarGroupContent,
|
|
478
|
+
UiSidebarGroupLabel,
|
|
479
|
+
UiSidebarHeaderTrigger,
|
|
480
|
+
UiSidebarInset,
|
|
481
|
+
UiSidebarMenu,
|
|
482
|
+
UiSidebarMenuAction,
|
|
483
|
+
UiSidebarMenuButton,
|
|
484
|
+
UiSidebarMenuItem,
|
|
485
|
+
UiSidebarProvider,
|
|
486
|
+
UiSidebarRail,
|
|
487
|
+
UiSidebarSeparator,
|
|
488
|
+
} from '@aleph-alpha/ui-library'
|
|
489
|
+
import { FlaskConical, MessageSquare, BarChart3, Database, Key, Activity, Settings, Command, Plus, MoreHorizontal } from 'lucide-vue-next'
|
|
490
|
+
|
|
491
|
+
const pipelineItems = ref([
|
|
492
|
+
{ title: 'Summarization', icon: FlaskConical },
|
|
493
|
+
{ title: 'RAG Chatbot', icon: MessageSquare },
|
|
494
|
+
{ title: 'Sentiment Analysis', icon: BarChart3 },
|
|
495
|
+
{ title: 'Data Extraction', icon: Database },
|
|
496
|
+
])
|
|
497
|
+
|
|
498
|
+
let counter = 0
|
|
499
|
+
function addPipeline() {
|
|
500
|
+
counter++
|
|
501
|
+
pipelineItems.value.push({ title: \\\`New Pipeline \\\${counter}\\\`, icon: FlaskConical })
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
const adminItems = [
|
|
505
|
+
{ title: 'API Keys', icon: Key },
|
|
506
|
+
{ title: 'Usage', icon: Activity },
|
|
507
|
+
{ title: 'Settings', icon: Settings },
|
|
508
|
+
]
|
|
509
|
+
</script>
|
|
510
|
+
|
|
511
|
+
<template>
|
|
512
|
+
<UiSidebarProvider :default-open="true">
|
|
513
|
+
<UiSidebar>
|
|
514
|
+
<UiSidebarHeaderTrigger>
|
|
515
|
+
<template #logo>
|
|
516
|
+
<div class="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
|
|
517
|
+
<Command class="size-4" />
|
|
518
|
+
</div>
|
|
519
|
+
</template>
|
|
520
|
+
<span class="truncate font-semibold">Acme AI</span>
|
|
521
|
+
<span class="truncate text-xs">Enterprise</span>
|
|
522
|
+
</UiSidebarHeaderTrigger>
|
|
523
|
+
<UiSidebarContent>
|
|
524
|
+
<UiSidebarGroup>
|
|
525
|
+
<UiSidebarGroupLabel>Pipelines</UiSidebarGroupLabel>
|
|
526
|
+
<UiSidebarGroupAction title="New Pipeline" @click="addPipeline">
|
|
527
|
+
<Plus />
|
|
528
|
+
</UiSidebarGroupAction>
|
|
529
|
+
<UiSidebarGroupContent>
|
|
530
|
+
<UiSidebarMenu>
|
|
531
|
+
<UiSidebarMenuItem v-for="item in pipelineItems" :key="item.title">
|
|
532
|
+
<UiSidebarMenuButton :tooltip="item.title">
|
|
533
|
+
<component :is="item.icon" />
|
|
534
|
+
<span>{{ item.title }}</span>
|
|
535
|
+
</UiSidebarMenuButton>
|
|
536
|
+
<UiSidebarMenuAction :show-on-hover="true" title="More options">
|
|
537
|
+
<MoreHorizontal />
|
|
538
|
+
</UiSidebarMenuAction>
|
|
539
|
+
</UiSidebarMenuItem>
|
|
540
|
+
</UiSidebarMenu>
|
|
541
|
+
</UiSidebarGroupContent>
|
|
542
|
+
</UiSidebarGroup>
|
|
543
|
+
<UiSidebarSeparator />
|
|
544
|
+
<UiSidebarGroup>
|
|
545
|
+
<UiSidebarGroupLabel>Administration</UiSidebarGroupLabel>
|
|
546
|
+
<UiSidebarGroupContent>
|
|
547
|
+
<UiSidebarMenu>
|
|
548
|
+
<UiSidebarMenuItem v-for="item in adminItems" :key="item.title">
|
|
549
|
+
<UiSidebarMenuButton :tooltip="item.title">
|
|
550
|
+
<component :is="item.icon" />
|
|
551
|
+
<span>{{ item.title }}</span>
|
|
552
|
+
</UiSidebarMenuButton>
|
|
553
|
+
</UiSidebarMenuItem>
|
|
554
|
+
</UiSidebarMenu>
|
|
555
|
+
</UiSidebarGroupContent>
|
|
556
|
+
</UiSidebarGroup>
|
|
557
|
+
</UiSidebarContent>
|
|
558
|
+
<UiSidebarRail />
|
|
559
|
+
</UiSidebar>
|
|
560
|
+
<UiSidebarInset>
|
|
561
|
+
<header class="flex h-16 shrink-0 items-center gap-2 border-b px-4">
|
|
562
|
+
<span class="text-sm font-medium">Pipelines</span>
|
|
563
|
+
</header>
|
|
564
|
+
</UiSidebarInset>
|
|
565
|
+
</UiSidebarProvider>
|
|
566
|
+
</template>`;
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Sidebar with `UiSidebarGroupAction` (a "+" button on the "Pipelines" group label), `UiSidebarMenuAction` (a "..." button on each pipeline item),
|
|
570
|
+
* and a `UiSidebarSeparator` dividing the "Pipelines" group from an "Administration" group.
|
|
571
|
+
* Menu actions use `show-on-hover` so they only appear when hovering the item. Both action types auto-hide in icon-collapse mode.
|
|
572
|
+
*/
|
|
573
|
+
export const WithActions: Story = {
|
|
574
|
+
render: (args) => ({
|
|
575
|
+
components: {
|
|
576
|
+
UiSidebar,
|
|
577
|
+
UiSidebarContent,
|
|
578
|
+
UiSidebarGroup,
|
|
579
|
+
UiSidebarGroupAction,
|
|
580
|
+
UiSidebarGroupContent,
|
|
581
|
+
UiSidebarGroupLabel,
|
|
582
|
+
UiSidebarHeaderTrigger,
|
|
583
|
+
UiSidebarInset,
|
|
584
|
+
UiSidebarMenu,
|
|
585
|
+
UiSidebarMenuAction,
|
|
586
|
+
UiSidebarMenuButton,
|
|
587
|
+
UiSidebarMenuItem,
|
|
588
|
+
UiSidebarProvider,
|
|
589
|
+
UiSidebarRail,
|
|
590
|
+
UiSidebarSeparator,
|
|
591
|
+
FlaskConical,
|
|
592
|
+
MessageSquare,
|
|
593
|
+
BarChart3,
|
|
594
|
+
Database,
|
|
595
|
+
Key,
|
|
596
|
+
Activity,
|
|
597
|
+
Settings,
|
|
598
|
+
Command,
|
|
599
|
+
Plus,
|
|
600
|
+
MoreHorizontal,
|
|
601
|
+
},
|
|
602
|
+
setup() {
|
|
603
|
+
const pipelineItems = ref([
|
|
604
|
+
{ title: 'Summarization', icon: FlaskConical },
|
|
605
|
+
{ title: 'RAG Chatbot', icon: MessageSquare },
|
|
606
|
+
{ title: 'Sentiment Analysis', icon: BarChart3 },
|
|
607
|
+
{ title: 'Data Extraction', icon: Database },
|
|
608
|
+
]);
|
|
609
|
+
let counter = 0;
|
|
610
|
+
const addPipeline = () => {
|
|
611
|
+
counter++;
|
|
612
|
+
pipelineItems.value.push({ title: `New Pipeline ${counter}`, icon: FlaskConical });
|
|
613
|
+
};
|
|
614
|
+
const adminItems = [
|
|
615
|
+
{ title: 'API Keys', icon: Key },
|
|
616
|
+
{ title: 'Usage', icon: Activity },
|
|
617
|
+
{ title: 'Settings', icon: Settings },
|
|
618
|
+
];
|
|
619
|
+
return { args, pipelineItems, addPipeline, adminItems };
|
|
620
|
+
},
|
|
621
|
+
template: `
|
|
622
|
+
<UiSidebarProvider :default-open="true">
|
|
623
|
+
<UiSidebar :side="args.side" :variant="args.variant" :collapsible="args.collapsible">
|
|
624
|
+
<UiSidebarHeaderTrigger>
|
|
625
|
+
<template #logo>
|
|
626
|
+
<div class="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
|
|
627
|
+
<Command class="size-4" />
|
|
628
|
+
</div>
|
|
629
|
+
</template>
|
|
630
|
+
<span class="truncate font-semibold">Acme AI</span>
|
|
631
|
+
<span class="truncate text-xs">Enterprise</span>
|
|
632
|
+
</UiSidebarHeaderTrigger>
|
|
633
|
+
<UiSidebarContent>
|
|
634
|
+
<UiSidebarGroup>
|
|
635
|
+
<UiSidebarGroupLabel>Pipelines</UiSidebarGroupLabel>
|
|
636
|
+
<UiSidebarGroupAction title="New Pipeline" @click="addPipeline">
|
|
637
|
+
<Plus />
|
|
638
|
+
</UiSidebarGroupAction>
|
|
639
|
+
<UiSidebarGroupContent>
|
|
640
|
+
<UiSidebarMenu>
|
|
641
|
+
<UiSidebarMenuItem v-for="item in pipelineItems" :key="item.title">
|
|
642
|
+
<UiSidebarMenuButton :tooltip="item.title">
|
|
643
|
+
<component :is="item.icon" />
|
|
644
|
+
<span>{{ item.title }}</span>
|
|
645
|
+
</UiSidebarMenuButton>
|
|
646
|
+
<UiSidebarMenuAction :show-on-hover="true" title="More options">
|
|
647
|
+
<MoreHorizontal />
|
|
648
|
+
</UiSidebarMenuAction>
|
|
649
|
+
</UiSidebarMenuItem>
|
|
650
|
+
</UiSidebarMenu>
|
|
651
|
+
</UiSidebarGroupContent>
|
|
652
|
+
</UiSidebarGroup>
|
|
653
|
+
<UiSidebarSeparator />
|
|
654
|
+
<UiSidebarGroup>
|
|
655
|
+
<UiSidebarGroupLabel>Administration</UiSidebarGroupLabel>
|
|
656
|
+
<UiSidebarGroupContent>
|
|
657
|
+
<UiSidebarMenu>
|
|
658
|
+
<UiSidebarMenuItem v-for="item in adminItems" :key="item.title">
|
|
659
|
+
<UiSidebarMenuButton :tooltip="item.title">
|
|
660
|
+
<component :is="item.icon" />
|
|
661
|
+
<span>{{ item.title }}</span>
|
|
662
|
+
</UiSidebarMenuButton>
|
|
663
|
+
</UiSidebarMenuItem>
|
|
664
|
+
</UiSidebarMenu>
|
|
665
|
+
</UiSidebarGroupContent>
|
|
666
|
+
</UiSidebarGroup>
|
|
667
|
+
</UiSidebarContent>
|
|
668
|
+
<UiSidebarRail />
|
|
669
|
+
</UiSidebar>
|
|
670
|
+
<UiSidebarInset>
|
|
671
|
+
<header class="flex h-16 shrink-0 items-center gap-2 border-b px-4">
|
|
672
|
+
<span class="text-sm font-medium">Pipelines</span>
|
|
673
|
+
</header>
|
|
674
|
+
</UiSidebarInset>
|
|
675
|
+
</UiSidebarProvider>
|
|
676
|
+
`,
|
|
677
|
+
}),
|
|
678
|
+
parameters: {
|
|
679
|
+
docs: {
|
|
680
|
+
source: {
|
|
681
|
+
code: withActionsTemplateSource,
|
|
682
|
+
},
|
|
683
|
+
},
|
|
684
|
+
},
|
|
685
|
+
};
|
|
686
|
+
|
|
687
|
+
const withSubmenuTemplateSource = `<script setup lang="ts">
|
|
688
|
+
import {
|
|
689
|
+
UiSidebar,
|
|
690
|
+
UiSidebarContent,
|
|
691
|
+
UiSidebarGroup,
|
|
692
|
+
UiSidebarGroupContent,
|
|
693
|
+
UiSidebarGroupLabel,
|
|
694
|
+
UiSidebarHeaderTrigger,
|
|
695
|
+
UiSidebarInset,
|
|
696
|
+
UiSidebarMenu,
|
|
697
|
+
UiSidebarMenuButton,
|
|
698
|
+
UiSidebarMenuItem,
|
|
699
|
+
UiSidebarMenuSub,
|
|
700
|
+
UiSidebarMenuSubButton,
|
|
701
|
+
UiSidebarMenuSubItem,
|
|
702
|
+
UiSidebarProvider,
|
|
703
|
+
UiSidebarRail,
|
|
704
|
+
} from '@aleph-alpha/ui-library'
|
|
705
|
+
import { CollapsibleRoot, CollapsibleContent, CollapsibleTrigger } from 'reka-ui'
|
|
706
|
+
import { Bot, Database, BarChart3, MessageSquare, Command, ChevronRight } from 'lucide-vue-next'
|
|
707
|
+
|
|
708
|
+
const navItems = [
|
|
709
|
+
{
|
|
710
|
+
title: 'Models',
|
|
711
|
+
icon: Database,
|
|
712
|
+
children: ['Completions', 'Embeddings', 'Chat', 'Multimodal'],
|
|
713
|
+
},
|
|
714
|
+
{
|
|
715
|
+
title: 'Evaluations',
|
|
716
|
+
icon: BarChart3,
|
|
717
|
+
children: ['Benchmarks', 'Custom Tests', 'Reports'],
|
|
718
|
+
},
|
|
719
|
+
{
|
|
720
|
+
title: 'Playground',
|
|
721
|
+
icon: Bot,
|
|
722
|
+
children: [],
|
|
723
|
+
},
|
|
724
|
+
{
|
|
725
|
+
title: 'Conversations',
|
|
726
|
+
icon: MessageSquare,
|
|
727
|
+
children: [],
|
|
728
|
+
},
|
|
729
|
+
]
|
|
730
|
+
</script>
|
|
731
|
+
|
|
732
|
+
<template>
|
|
733
|
+
<UiSidebarProvider :default-open="true">
|
|
734
|
+
<UiSidebar>
|
|
735
|
+
<UiSidebarHeaderTrigger>
|
|
736
|
+
<template #logo>
|
|
737
|
+
<div class="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
|
|
738
|
+
<Command class="size-4" />
|
|
739
|
+
</div>
|
|
740
|
+
</template>
|
|
741
|
+
<span class="truncate font-semibold">Acme AI</span>
|
|
742
|
+
<span class="truncate text-xs">Enterprise</span>
|
|
743
|
+
</UiSidebarHeaderTrigger>
|
|
744
|
+
<UiSidebarContent>
|
|
745
|
+
<UiSidebarGroup>
|
|
746
|
+
<UiSidebarGroupLabel>Platform</UiSidebarGroupLabel>
|
|
747
|
+
<UiSidebarGroupContent>
|
|
748
|
+
<UiSidebarMenu>
|
|
749
|
+
<template v-for="item in navItems" :key="item.title">
|
|
750
|
+
<CollapsibleRoot v-if="item.children.length" as-child class="group/collapsible">
|
|
751
|
+
<UiSidebarMenuItem>
|
|
752
|
+
<CollapsibleTrigger as-child>
|
|
753
|
+
<UiSidebarMenuButton :tooltip="item.title">
|
|
754
|
+
<component :is="item.icon" />
|
|
755
|
+
<span>{{ item.title }}</span>
|
|
756
|
+
<ChevronRight class="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-90" />
|
|
757
|
+
</UiSidebarMenuButton>
|
|
758
|
+
</CollapsibleTrigger>
|
|
759
|
+
<CollapsibleContent>
|
|
760
|
+
<UiSidebarMenuSub>
|
|
761
|
+
<UiSidebarMenuSubItem v-for="child in item.children" :key="child">
|
|
762
|
+
<UiSidebarMenuSubButton>{{ child }}</UiSidebarMenuSubButton>
|
|
763
|
+
</UiSidebarMenuSubItem>
|
|
764
|
+
</UiSidebarMenuSub>
|
|
765
|
+
</CollapsibleContent>
|
|
766
|
+
</UiSidebarMenuItem>
|
|
767
|
+
</CollapsibleRoot>
|
|
768
|
+
<UiSidebarMenuItem v-else>
|
|
769
|
+
<UiSidebarMenuButton :tooltip="item.title">
|
|
770
|
+
<component :is="item.icon" />
|
|
771
|
+
<span>{{ item.title }}</span>
|
|
772
|
+
</UiSidebarMenuButton>
|
|
773
|
+
</UiSidebarMenuItem>
|
|
774
|
+
</template>
|
|
775
|
+
</UiSidebarMenu>
|
|
776
|
+
</UiSidebarGroupContent>
|
|
777
|
+
</UiSidebarGroup>
|
|
778
|
+
</UiSidebarContent>
|
|
779
|
+
<UiSidebarRail />
|
|
780
|
+
</UiSidebar>
|
|
781
|
+
<UiSidebarInset>
|
|
782
|
+
<header class="flex h-16 shrink-0 items-center gap-2 border-b px-4">
|
|
783
|
+
<span class="text-sm font-medium">Platform</span>
|
|
784
|
+
</header>
|
|
785
|
+
</UiSidebarInset>
|
|
786
|
+
</UiSidebarProvider>
|
|
787
|
+
</template>`;
|
|
788
|
+
|
|
789
|
+
/**
|
|
790
|
+
* Sidebar with collapsible `UiSidebarMenuSub` submenus using `Collapsible` from reka-ui. "Models" and "Evaluations" expand to reveal nested items via `UiSidebarMenuSubButton`.
|
|
791
|
+
* Submenu items are hidden in icon-collapse mode. A chevron icon rotates to indicate the open/closed state.
|
|
792
|
+
*/
|
|
793
|
+
export const WithSubmenu: Story = {
|
|
794
|
+
render: (args) => ({
|
|
795
|
+
components: {
|
|
796
|
+
UiSidebar,
|
|
797
|
+
UiSidebarContent,
|
|
798
|
+
UiSidebarGroup,
|
|
799
|
+
UiSidebarGroupContent,
|
|
800
|
+
UiSidebarGroupLabel,
|
|
801
|
+
UiSidebarHeaderTrigger,
|
|
802
|
+
UiSidebarInset,
|
|
803
|
+
UiSidebarMenu,
|
|
804
|
+
UiSidebarMenuButton,
|
|
805
|
+
UiSidebarMenuItem,
|
|
806
|
+
UiSidebarMenuSub,
|
|
807
|
+
UiSidebarMenuSubButton,
|
|
808
|
+
UiSidebarMenuSubItem,
|
|
809
|
+
UiSidebarProvider,
|
|
810
|
+
UiSidebarRail,
|
|
811
|
+
CollapsibleRoot,
|
|
812
|
+
CollapsibleContent,
|
|
813
|
+
CollapsibleTrigger,
|
|
814
|
+
Bot,
|
|
815
|
+
Database,
|
|
816
|
+
BarChart3,
|
|
817
|
+
MessageSquare,
|
|
818
|
+
Command,
|
|
819
|
+
ChevronRight,
|
|
820
|
+
},
|
|
821
|
+
setup() {
|
|
822
|
+
const navItems = [
|
|
823
|
+
{
|
|
824
|
+
title: 'Models',
|
|
825
|
+
icon: Database,
|
|
826
|
+
children: ['Completions', 'Embeddings', 'Chat', 'Multimodal'],
|
|
827
|
+
},
|
|
828
|
+
{
|
|
829
|
+
title: 'Evaluations',
|
|
830
|
+
icon: BarChart3,
|
|
831
|
+
children: ['Benchmarks', 'Custom Tests', 'Reports'],
|
|
832
|
+
},
|
|
833
|
+
{
|
|
834
|
+
title: 'Playground',
|
|
835
|
+
icon: Bot,
|
|
836
|
+
children: [],
|
|
837
|
+
},
|
|
838
|
+
{
|
|
839
|
+
title: 'Conversations',
|
|
840
|
+
icon: MessageSquare,
|
|
841
|
+
children: [],
|
|
842
|
+
},
|
|
843
|
+
];
|
|
844
|
+
return { args, navItems };
|
|
845
|
+
},
|
|
846
|
+
template: `
|
|
847
|
+
<UiSidebarProvider :default-open="true">
|
|
848
|
+
<UiSidebar :side="args.side" :variant="args.variant" :collapsible="args.collapsible">
|
|
849
|
+
<UiSidebarHeaderTrigger>
|
|
850
|
+
<template #logo>
|
|
851
|
+
<div class="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
|
|
852
|
+
<Command class="size-4" />
|
|
853
|
+
</div>
|
|
854
|
+
</template>
|
|
855
|
+
<span class="truncate font-semibold">Acme AI</span>
|
|
856
|
+
<span class="truncate text-xs">Enterprise</span>
|
|
857
|
+
</UiSidebarHeaderTrigger>
|
|
858
|
+
<UiSidebarContent>
|
|
859
|
+
<UiSidebarGroup>
|
|
860
|
+
<UiSidebarGroupLabel>Platform</UiSidebarGroupLabel>
|
|
861
|
+
<UiSidebarGroupContent>
|
|
862
|
+
<UiSidebarMenu>
|
|
863
|
+
<template v-for="item in navItems" :key="item.title">
|
|
864
|
+
<CollapsibleRoot v-if="item.children.length" as-child class="group/collapsible">
|
|
865
|
+
<UiSidebarMenuItem>
|
|
866
|
+
<CollapsibleTrigger as-child>
|
|
867
|
+
<UiSidebarMenuButton :tooltip="item.title">
|
|
868
|
+
<component :is="item.icon" />
|
|
869
|
+
<span>{{ item.title }}</span>
|
|
870
|
+
<ChevronRight class="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-90" />
|
|
871
|
+
</UiSidebarMenuButton>
|
|
872
|
+
</CollapsibleTrigger>
|
|
873
|
+
<CollapsibleContent>
|
|
874
|
+
<UiSidebarMenuSub>
|
|
875
|
+
<UiSidebarMenuSubItem v-for="child in item.children" :key="child">
|
|
876
|
+
<UiSidebarMenuSubButton>{{ child }}</UiSidebarMenuSubButton>
|
|
877
|
+
</UiSidebarMenuSubItem>
|
|
878
|
+
</UiSidebarMenuSub>
|
|
879
|
+
</CollapsibleContent>
|
|
880
|
+
</UiSidebarMenuItem>
|
|
881
|
+
</CollapsibleRoot>
|
|
882
|
+
<UiSidebarMenuItem v-else>
|
|
883
|
+
<UiSidebarMenuButton :tooltip="item.title">
|
|
884
|
+
<component :is="item.icon" />
|
|
885
|
+
<span>{{ item.title }}</span>
|
|
886
|
+
</UiSidebarMenuButton>
|
|
887
|
+
</UiSidebarMenuItem>
|
|
888
|
+
</template>
|
|
889
|
+
</UiSidebarMenu>
|
|
890
|
+
</UiSidebarGroupContent>
|
|
891
|
+
</UiSidebarGroup>
|
|
892
|
+
</UiSidebarContent>
|
|
893
|
+
<UiSidebarRail />
|
|
894
|
+
</UiSidebar>
|
|
895
|
+
<UiSidebarInset>
|
|
896
|
+
<header class="flex h-16 shrink-0 items-center gap-2 border-b px-4">
|
|
897
|
+
<span class="text-sm font-medium">Platform</span>
|
|
898
|
+
</header>
|
|
899
|
+
</UiSidebarInset>
|
|
900
|
+
</UiSidebarProvider>
|
|
901
|
+
`,
|
|
902
|
+
}),
|
|
903
|
+
parameters: {
|
|
904
|
+
docs: {
|
|
905
|
+
source: {
|
|
906
|
+
code: withSubmenuTemplateSource,
|
|
907
|
+
},
|
|
908
|
+
},
|
|
909
|
+
},
|
|
910
|
+
};
|
|
911
|
+
|
|
912
|
+
const withSkeletonTemplateSource = `<script setup lang="ts">
|
|
913
|
+
import {
|
|
914
|
+
UiSidebar,
|
|
915
|
+
UiSidebarContent,
|
|
916
|
+
UiSidebarGroup,
|
|
917
|
+
UiSidebarGroupContent,
|
|
918
|
+
UiSidebarGroupLabel,
|
|
919
|
+
UiSidebarInset,
|
|
920
|
+
UiSidebarMenu,
|
|
921
|
+
UiSidebarMenuItem,
|
|
922
|
+
UiSidebarMenuSkeleton,
|
|
923
|
+
UiSidebarProvider,
|
|
924
|
+
UiSidebarRail,
|
|
925
|
+
UiSidebarTrigger,
|
|
926
|
+
} from '@aleph-alpha/ui-library'
|
|
927
|
+
</script>
|
|
928
|
+
|
|
929
|
+
<template>
|
|
930
|
+
<UiSidebarProvider :default-open="true">
|
|
931
|
+
<UiSidebar>
|
|
932
|
+
<UiSidebarContent>
|
|
933
|
+
<UiSidebarGroup>
|
|
934
|
+
<UiSidebarGroupLabel>Platform</UiSidebarGroupLabel>
|
|
935
|
+
<UiSidebarGroupContent>
|
|
936
|
+
<UiSidebarMenu>
|
|
937
|
+
<UiSidebarMenuItem v-for="i in 4" :key="i">
|
|
938
|
+
<UiSidebarMenuSkeleton :show-icon="true" />
|
|
939
|
+
</UiSidebarMenuItem>
|
|
940
|
+
</UiSidebarMenu>
|
|
941
|
+
</UiSidebarGroupContent>
|
|
942
|
+
</UiSidebarGroup>
|
|
943
|
+
</UiSidebarContent>
|
|
944
|
+
<UiSidebarRail />
|
|
945
|
+
</UiSidebar>
|
|
946
|
+
<UiSidebarInset>
|
|
947
|
+
<header class="flex h-16 shrink-0 items-center gap-2 border-b px-4">
|
|
948
|
+
<UiSidebarTrigger class="-ml-1" />
|
|
949
|
+
<span class="text-sm font-medium">Platform</span>
|
|
950
|
+
</header>
|
|
951
|
+
</UiSidebarInset>
|
|
952
|
+
</UiSidebarProvider>
|
|
953
|
+
</template>`;
|
|
954
|
+
|
|
955
|
+
/**
|
|
956
|
+
* Sidebar with `UiSidebarMenuSkeleton` placeholders showing a loading state.
|
|
957
|
+
* Use `show-icon` to include an icon-sized skeleton circle alongside the text bar. Each skeleton renders a random width for a natural staggered look.
|
|
958
|
+
*/
|
|
959
|
+
export const WithSkeleton: Story = {
|
|
960
|
+
render: (args) => ({
|
|
961
|
+
components: {
|
|
962
|
+
UiSidebar,
|
|
963
|
+
UiSidebarContent,
|
|
964
|
+
UiSidebarGroup,
|
|
965
|
+
UiSidebarGroupContent,
|
|
966
|
+
UiSidebarGroupLabel,
|
|
967
|
+
UiSidebarInset,
|
|
968
|
+
UiSidebarMenu,
|
|
969
|
+
UiSidebarMenuItem,
|
|
970
|
+
UiSidebarMenuSkeleton,
|
|
971
|
+
UiSidebarProvider,
|
|
972
|
+
UiSidebarRail,
|
|
973
|
+
UiSidebarTrigger,
|
|
974
|
+
},
|
|
975
|
+
setup() {
|
|
976
|
+
return { args };
|
|
977
|
+
},
|
|
978
|
+
template: `
|
|
979
|
+
<UiSidebarProvider :default-open="true">
|
|
980
|
+
<UiSidebar :side="args.side" :variant="args.variant" :collapsible="args.collapsible">
|
|
981
|
+
<UiSidebarContent>
|
|
982
|
+
<UiSidebarGroup>
|
|
983
|
+
<UiSidebarGroupLabel>Platform</UiSidebarGroupLabel>
|
|
984
|
+
<UiSidebarGroupContent>
|
|
985
|
+
<UiSidebarMenu>
|
|
986
|
+
<UiSidebarMenuItem v-for="i in 4" :key="i">
|
|
987
|
+
<UiSidebarMenuSkeleton :show-icon="true" />
|
|
988
|
+
</UiSidebarMenuItem>
|
|
989
|
+
</UiSidebarMenu>
|
|
990
|
+
</UiSidebarGroupContent>
|
|
991
|
+
</UiSidebarGroup>
|
|
992
|
+
</UiSidebarContent>
|
|
993
|
+
<UiSidebarRail />
|
|
994
|
+
</UiSidebar>
|
|
995
|
+
<UiSidebarInset>
|
|
996
|
+
<header class="flex h-16 shrink-0 items-center gap-2 border-b px-4">
|
|
997
|
+
<UiSidebarTrigger class="-ml-1" />
|
|
998
|
+
<span class="text-sm font-medium">Platform</span>
|
|
999
|
+
</header>
|
|
1000
|
+
</UiSidebarInset>
|
|
1001
|
+
</UiSidebarProvider>
|
|
1002
|
+
`,
|
|
1003
|
+
}),
|
|
1004
|
+
parameters: {
|
|
1005
|
+
docs: {
|
|
1006
|
+
source: {
|
|
1007
|
+
code: withSkeletonTemplateSource,
|
|
1008
|
+
},
|
|
1009
|
+
},
|
|
1010
|
+
},
|
|
1011
|
+
};
|
|
1012
|
+
|
|
1013
|
+
const programmaticControlTemplateSource = `<script setup lang="ts">
|
|
1014
|
+
import {
|
|
1015
|
+
UiSidebar,
|
|
1016
|
+
UiSidebarContent,
|
|
1017
|
+
UiSidebarGroup,
|
|
1018
|
+
UiSidebarGroupContent,
|
|
1019
|
+
UiSidebarGroupLabel,
|
|
1020
|
+
UiSidebarHeaderTrigger,
|
|
1021
|
+
UiSidebarInset,
|
|
1022
|
+
UiSidebarMenu,
|
|
1023
|
+
UiSidebarMenuButton,
|
|
1024
|
+
UiSidebarMenuItem,
|
|
1025
|
+
UiSidebarProvider,
|
|
1026
|
+
UiSidebarRail,
|
|
1027
|
+
useSidebar,
|
|
1028
|
+
} from '@aleph-alpha/ui-library'
|
|
1029
|
+
import { Bot, Database, BarChart3, MessageSquare, Command } from 'lucide-vue-next'
|
|
1030
|
+
|
|
1031
|
+
const items = [
|
|
1032
|
+
{ title: 'Playground', icon: Bot },
|
|
1033
|
+
{ title: 'Models', icon: Database },
|
|
1034
|
+
{ title: 'Evaluations', icon: BarChart3 },
|
|
1035
|
+
{ title: 'Conversations', icon: MessageSquare },
|
|
1036
|
+
]
|
|
1037
|
+
|
|
1038
|
+
// useSidebar() must be called inside <UiSidebarProvider>.
|
|
1039
|
+
// Use a child component or <script setup> in a component nested within the provider.
|
|
1040
|
+
</script>
|
|
1041
|
+
|
|
1042
|
+
<template>
|
|
1043
|
+
<UiSidebarProvider>
|
|
1044
|
+
<!-- Wrap content in a child component that calls useSidebar() -->
|
|
1045
|
+
<SidebarLayout :items="items" />
|
|
1046
|
+
</UiSidebarProvider>
|
|
1047
|
+
</template>
|
|
1048
|
+
|
|
1049
|
+
<!-- Child component (e.g. SidebarLayout.vue) -->
|
|
1050
|
+
<script setup lang="ts">
|
|
1051
|
+
import { useSidebar } from '@aleph-alpha/ui-library'
|
|
1052
|
+
|
|
1053
|
+
const { state, open, setOpen, toggleSidebar } = useSidebar()
|
|
1054
|
+
</script>
|
|
1055
|
+
|
|
1056
|
+
<template>
|
|
1057
|
+
<UiSidebar><!-- ... --></UiSidebar>
|
|
1058
|
+
<UiSidebarInset>
|
|
1059
|
+
<div class="p-6 space-y-4">
|
|
1060
|
+
<p>Sidebar is <strong>{{ state }}</strong></p>
|
|
1061
|
+
<button @click="toggleSidebar()">Toggle</button>
|
|
1062
|
+
<button @click="setOpen(true)">Open</button>
|
|
1063
|
+
<button @click="setOpen(false)">Close</button>
|
|
1064
|
+
</div>
|
|
1065
|
+
</UiSidebarInset>
|
|
1066
|
+
</template>`;
|
|
1067
|
+
|
|
1068
|
+
/**
|
|
1069
|
+
* Programmatic sidebar control via the `useSidebar()` composable. The composable must be called
|
|
1070
|
+
* inside a component rendered within `<UiSidebarProvider>`. It returns reactive state (`state`, `open`)
|
|
1071
|
+
* and methods (`toggleSidebar`, `setOpen`) to control the sidebar from anywhere in the provider tree.
|
|
1072
|
+
*
|
|
1073
|
+
* This is the recommended pattern for controlling the sidebar from outside — e.g. opening it
|
|
1074
|
+
* from a toolbar button, closing it after navigation, or syncing state with a store.
|
|
1075
|
+
*/
|
|
1076
|
+
export const ProgrammaticControl: Story = {
|
|
1077
|
+
render: (args) => ({
|
|
1078
|
+
components: {
|
|
1079
|
+
UiSidebar,
|
|
1080
|
+
UiSidebarContent,
|
|
1081
|
+
UiSidebarGroup,
|
|
1082
|
+
UiSidebarGroupContent,
|
|
1083
|
+
UiSidebarGroupLabel,
|
|
1084
|
+
UiSidebarHeaderTrigger,
|
|
1085
|
+
UiSidebarInset,
|
|
1086
|
+
UiSidebarMenu,
|
|
1087
|
+
UiSidebarMenuButton,
|
|
1088
|
+
UiSidebarMenuItem,
|
|
1089
|
+
UiSidebarProvider,
|
|
1090
|
+
UiSidebarRail,
|
|
1091
|
+
Bot,
|
|
1092
|
+
Database,
|
|
1093
|
+
BarChart3,
|
|
1094
|
+
MessageSquare,
|
|
1095
|
+
Command,
|
|
1096
|
+
// Inline child component that uses useSidebar() — in real apps this would be a separate .vue file
|
|
1097
|
+
SidebarContent: defineComponent({
|
|
1098
|
+
setup() {
|
|
1099
|
+
const { state, toggleSidebar, setOpen } = useSidebar();
|
|
1100
|
+
return { state, toggleSidebar, setOpen };
|
|
1101
|
+
},
|
|
1102
|
+
template: `<slot :state="state" :toggleSidebar="toggleSidebar" :setOpen="setOpen" />`,
|
|
1103
|
+
}),
|
|
1104
|
+
},
|
|
1105
|
+
setup() {
|
|
1106
|
+
const items = [
|
|
1107
|
+
{ title: 'Playground', icon: Bot },
|
|
1108
|
+
{ title: 'Models', icon: Database },
|
|
1109
|
+
{ title: 'Evaluations', icon: BarChart3 },
|
|
1110
|
+
{ title: 'Conversations', icon: MessageSquare },
|
|
1111
|
+
];
|
|
1112
|
+
return { args, items };
|
|
1113
|
+
},
|
|
1114
|
+
template: `
|
|
1115
|
+
<UiSidebarProvider>
|
|
1116
|
+
<UiSidebar :side="args.side" :variant="args.variant" :collapsible="args.collapsible">
|
|
1117
|
+
<UiSidebarHeaderTrigger>
|
|
1118
|
+
<template #logo>
|
|
1119
|
+
<div class="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
|
|
1120
|
+
<Command class="size-4" />
|
|
1121
|
+
</div>
|
|
1122
|
+
</template>
|
|
1123
|
+
<span class="truncate font-semibold">Acme AI</span>
|
|
1124
|
+
<span class="truncate text-xs">Enterprise</span>
|
|
1125
|
+
</UiSidebarHeaderTrigger>
|
|
1126
|
+
<UiSidebarContent>
|
|
1127
|
+
<UiSidebarGroup>
|
|
1128
|
+
<UiSidebarGroupLabel>Platform</UiSidebarGroupLabel>
|
|
1129
|
+
<UiSidebarGroupContent>
|
|
1130
|
+
<UiSidebarMenu>
|
|
1131
|
+
<UiSidebarMenuItem v-for="item in items" :key="item.title">
|
|
1132
|
+
<UiSidebarMenuButton :tooltip="item.title">
|
|
1133
|
+
<component :is="item.icon" />
|
|
1134
|
+
<span>{{ item.title }}</span>
|
|
1135
|
+
</UiSidebarMenuButton>
|
|
1136
|
+
</UiSidebarMenuItem>
|
|
1137
|
+
</UiSidebarMenu>
|
|
1138
|
+
</UiSidebarGroupContent>
|
|
1139
|
+
</UiSidebarGroup>
|
|
1140
|
+
</UiSidebarContent>
|
|
1141
|
+
<UiSidebarRail />
|
|
1142
|
+
</UiSidebar>
|
|
1143
|
+
<UiSidebarInset>
|
|
1144
|
+
<SidebarContent v-slot="{ state, toggleSidebar, setOpen }">
|
|
1145
|
+
<div class="p-6">
|
|
1146
|
+
<div class="mb-6">
|
|
1147
|
+
<h2 class="text-lg font-semibold mb-1">Programmatic Control</h2>
|
|
1148
|
+
<p class="text-sm text-muted-foreground">
|
|
1149
|
+
Use <code class="rounded bg-muted px-1.5 py-0.5 text-xs">useSidebar()</code> inside the provider tree to control the sidebar from any component.
|
|
1150
|
+
</p>
|
|
1151
|
+
</div>
|
|
1152
|
+
<div class="flex items-center gap-3 mb-6">
|
|
1153
|
+
<span class="text-sm">State: <strong>{{ state }}</strong></span>
|
|
1154
|
+
</div>
|
|
1155
|
+
<div class="flex flex-wrap gap-2">
|
|
1156
|
+
<button
|
|
1157
|
+
class="inline-flex items-center justify-center rounded-md text-sm font-medium h-9 px-4 border border-input bg-background hover:bg-accent hover:text-accent-foreground"
|
|
1158
|
+
@click="toggleSidebar()"
|
|
1159
|
+
>
|
|
1160
|
+
Toggle sidebar
|
|
1161
|
+
</button>
|
|
1162
|
+
<button
|
|
1163
|
+
class="inline-flex items-center justify-center rounded-md text-sm font-medium h-9 px-4 border border-input bg-background hover:bg-accent hover:text-accent-foreground"
|
|
1164
|
+
@click="setOpen(true)"
|
|
1165
|
+
>
|
|
1166
|
+
Open
|
|
1167
|
+
</button>
|
|
1168
|
+
<button
|
|
1169
|
+
class="inline-flex items-center justify-center rounded-md text-sm font-medium h-9 px-4 border border-input bg-background hover:bg-accent hover:text-accent-foreground"
|
|
1170
|
+
@click="setOpen(false)"
|
|
1171
|
+
>
|
|
1172
|
+
Close
|
|
1173
|
+
</button>
|
|
1174
|
+
</div>
|
|
1175
|
+
</div>
|
|
1176
|
+
</SidebarContent>
|
|
1177
|
+
</UiSidebarInset>
|
|
1178
|
+
</UiSidebarProvider>
|
|
1179
|
+
`,
|
|
1180
|
+
}),
|
|
1181
|
+
parameters: {
|
|
1182
|
+
docs: {
|
|
1183
|
+
source: {
|
|
1184
|
+
code: programmaticControlTemplateSource,
|
|
1185
|
+
},
|
|
1186
|
+
},
|
|
1187
|
+
},
|
|
1188
|
+
};
|