@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,715 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite';
|
|
2
|
+
import {
|
|
3
|
+
UiSheet,
|
|
4
|
+
UiSheetClose,
|
|
5
|
+
UiSheetContent,
|
|
6
|
+
UiSheetDescription,
|
|
7
|
+
UiSheetFooter,
|
|
8
|
+
UiSheetHeader,
|
|
9
|
+
UiSheetTitle,
|
|
10
|
+
UiSheetTrigger,
|
|
11
|
+
} from '.';
|
|
12
|
+
import { UiButton } from '../UiButton';
|
|
13
|
+
import { UiInput } from '../UiInput';
|
|
14
|
+
import { UiLabel } from '../UiLabel';
|
|
15
|
+
import { ref, watch } from 'vue';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* UiSheet slides a panel in from the edge of the screen.
|
|
19
|
+
* Use it for supplementary content like forms, filters, detail views, or settings
|
|
20
|
+
* that shouldn't navigate away from the current page.
|
|
21
|
+
*/
|
|
22
|
+
const meta: Meta<typeof UiSheet> = {
|
|
23
|
+
title: 'Components/UiSheet',
|
|
24
|
+
component: UiSheet,
|
|
25
|
+
tags: ['autodocs'],
|
|
26
|
+
argTypes: {
|
|
27
|
+
open: {
|
|
28
|
+
control: 'boolean',
|
|
29
|
+
description: 'Controlled open state (use `v-model:open` for controlled mode).',
|
|
30
|
+
},
|
|
31
|
+
modal: {
|
|
32
|
+
control: 'boolean',
|
|
33
|
+
description: 'If true, traps focus and blocks interaction with the page while open.',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
args: {
|
|
37
|
+
open: false,
|
|
38
|
+
modal: true,
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default meta;
|
|
43
|
+
type Story = StoryObj<typeof UiSheet>;
|
|
44
|
+
|
|
45
|
+
const defaultTemplateSource = `<script setup lang="ts">
|
|
46
|
+
import {
|
|
47
|
+
UiSheet,
|
|
48
|
+
UiSheetTrigger,
|
|
49
|
+
UiSheetContent,
|
|
50
|
+
UiSheetHeader,
|
|
51
|
+
UiSheetTitle,
|
|
52
|
+
UiSheetDescription,
|
|
53
|
+
UiSheetFooter,
|
|
54
|
+
UiSheetClose,
|
|
55
|
+
UiButton,
|
|
56
|
+
} from '@aleph-alpha/ui-library'
|
|
57
|
+
</script>
|
|
58
|
+
|
|
59
|
+
<template>
|
|
60
|
+
<UiSheet>
|
|
61
|
+
<UiSheetTrigger as-child>
|
|
62
|
+
<UiButton variant="outline">Open Sheet</UiButton>
|
|
63
|
+
</UiSheetTrigger>
|
|
64
|
+
<UiSheetContent>
|
|
65
|
+
<UiSheetHeader>
|
|
66
|
+
<UiSheetTitle>Sheet title</UiSheetTitle>
|
|
67
|
+
<UiSheetDescription>
|
|
68
|
+
A slide-out panel for supplementary content.
|
|
69
|
+
</UiSheetDescription>
|
|
70
|
+
</UiSheetHeader>
|
|
71
|
+
<div class="flex-1 overflow-auto px-4 py-4 text-sm">
|
|
72
|
+
Put any content here.
|
|
73
|
+
</div>
|
|
74
|
+
<UiSheetFooter>
|
|
75
|
+
<UiSheetClose as-child>
|
|
76
|
+
<UiButton>Close</UiButton>
|
|
77
|
+
</UiSheetClose>
|
|
78
|
+
</UiSheetFooter>
|
|
79
|
+
</UiSheetContent>
|
|
80
|
+
</UiSheet>
|
|
81
|
+
</template>`;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Basic sheet composition showing Trigger + Content + Header/Footer.
|
|
85
|
+
* Opens from the right side by default.
|
|
86
|
+
*/
|
|
87
|
+
export const Default: Story = {
|
|
88
|
+
render: (args) => ({
|
|
89
|
+
components: {
|
|
90
|
+
UiSheet,
|
|
91
|
+
UiSheetClose,
|
|
92
|
+
UiSheetContent,
|
|
93
|
+
UiSheetDescription,
|
|
94
|
+
UiSheetFooter,
|
|
95
|
+
UiSheetHeader,
|
|
96
|
+
UiSheetTitle,
|
|
97
|
+
UiSheetTrigger,
|
|
98
|
+
UiButton,
|
|
99
|
+
},
|
|
100
|
+
setup() {
|
|
101
|
+
const open = ref(args.open);
|
|
102
|
+
const modal = ref(args.modal);
|
|
103
|
+
|
|
104
|
+
watch(
|
|
105
|
+
() => args.open,
|
|
106
|
+
(val) => {
|
|
107
|
+
open.value = val;
|
|
108
|
+
},
|
|
109
|
+
);
|
|
110
|
+
watch(
|
|
111
|
+
() => args.modal,
|
|
112
|
+
(val) => {
|
|
113
|
+
modal.value = val;
|
|
114
|
+
},
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
return { open, modal };
|
|
118
|
+
},
|
|
119
|
+
template: `
|
|
120
|
+
<UiSheet v-model:open="open" :modal="modal">
|
|
121
|
+
<UiSheetTrigger as-child>
|
|
122
|
+
<UiButton variant="outline">Open Sheet</UiButton>
|
|
123
|
+
</UiSheetTrigger>
|
|
124
|
+
<UiSheetContent>
|
|
125
|
+
<UiSheetHeader>
|
|
126
|
+
<UiSheetTitle>Sheet title</UiSheetTitle>
|
|
127
|
+
<UiSheetDescription>
|
|
128
|
+
A slide-out panel for supplementary content.
|
|
129
|
+
</UiSheetDescription>
|
|
130
|
+
</UiSheetHeader>
|
|
131
|
+
<div class="flex-1 overflow-auto px-4 py-4 text-sm">
|
|
132
|
+
Put any content here.
|
|
133
|
+
</div>
|
|
134
|
+
<UiSheetFooter>
|
|
135
|
+
<UiSheetClose as-child>
|
|
136
|
+
<UiButton>Close</UiButton>
|
|
137
|
+
</UiSheetClose>
|
|
138
|
+
</UiSheetFooter>
|
|
139
|
+
</UiSheetContent>
|
|
140
|
+
</UiSheet>
|
|
141
|
+
`,
|
|
142
|
+
}),
|
|
143
|
+
parameters: {
|
|
144
|
+
docs: { source: { code: defaultTemplateSource } },
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const controlledTemplateSource = `<script setup lang="ts">
|
|
149
|
+
import {
|
|
150
|
+
UiSheet,
|
|
151
|
+
UiSheetTrigger,
|
|
152
|
+
UiSheetContent,
|
|
153
|
+
UiSheetHeader,
|
|
154
|
+
UiSheetTitle,
|
|
155
|
+
UiSheetDescription,
|
|
156
|
+
UiSheetFooter,
|
|
157
|
+
UiSheetClose,
|
|
158
|
+
UiButton,
|
|
159
|
+
} from '@aleph-alpha/ui-library'
|
|
160
|
+
import { ref } from 'vue'
|
|
161
|
+
|
|
162
|
+
const open = ref(false)
|
|
163
|
+
</script>
|
|
164
|
+
|
|
165
|
+
<template>
|
|
166
|
+
<UiSheet v-model:open="open">
|
|
167
|
+
<UiSheetTrigger as-child>
|
|
168
|
+
<UiButton variant="outline">
|
|
169
|
+
{{ open ? 'Close' : 'Open' }} Sheet
|
|
170
|
+
</UiButton>
|
|
171
|
+
</UiSheetTrigger>
|
|
172
|
+
<UiSheetContent>
|
|
173
|
+
<UiSheetHeader>
|
|
174
|
+
<UiSheetTitle>Controlled sheet</UiSheetTitle>
|
|
175
|
+
<UiSheetDescription>
|
|
176
|
+
This sheet is controlled via v-model:open.
|
|
177
|
+
</UiSheetDescription>
|
|
178
|
+
</UiSheetHeader>
|
|
179
|
+
<div class="flex-1 overflow-auto px-4 py-4 text-sm space-y-3">
|
|
180
|
+
<p>Click the buttons below to close programmatically.</p>
|
|
181
|
+
<div class="flex gap-2 flex-wrap">
|
|
182
|
+
<UiButton size="sm" @click="open = false">Close via model</UiButton>
|
|
183
|
+
<UiSheetClose as-child>
|
|
184
|
+
<UiButton size="sm" variant="outline">Close via UiSheetClose</UiButton>
|
|
185
|
+
</UiSheetClose>
|
|
186
|
+
</div>
|
|
187
|
+
</div>
|
|
188
|
+
</UiSheetContent>
|
|
189
|
+
</UiSheet>
|
|
190
|
+
</template>`;
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Controlled sheet using `v-model:open`.
|
|
194
|
+
* Use this when visibility is driven by app state (router, async flows, programmatic close).
|
|
195
|
+
*/
|
|
196
|
+
export const Controlled: Story = {
|
|
197
|
+
render: () => ({
|
|
198
|
+
components: {
|
|
199
|
+
UiSheet,
|
|
200
|
+
UiSheetClose,
|
|
201
|
+
UiSheetContent,
|
|
202
|
+
UiSheetDescription,
|
|
203
|
+
UiSheetFooter,
|
|
204
|
+
UiSheetHeader,
|
|
205
|
+
UiSheetTitle,
|
|
206
|
+
UiSheetTrigger,
|
|
207
|
+
UiButton,
|
|
208
|
+
},
|
|
209
|
+
setup() {
|
|
210
|
+
const open = ref(false);
|
|
211
|
+
return { open };
|
|
212
|
+
},
|
|
213
|
+
template: `
|
|
214
|
+
<UiSheet v-model:open="open">
|
|
215
|
+
<UiSheetTrigger as-child>
|
|
216
|
+
<UiButton variant="outline">
|
|
217
|
+
{{ open ? 'Close' : 'Open' }} Sheet
|
|
218
|
+
</UiButton>
|
|
219
|
+
</UiSheetTrigger>
|
|
220
|
+
<UiSheetContent>
|
|
221
|
+
<UiSheetHeader>
|
|
222
|
+
<UiSheetTitle>Controlled sheet</UiSheetTitle>
|
|
223
|
+
<UiSheetDescription>
|
|
224
|
+
This sheet is controlled via v-model:open.
|
|
225
|
+
</UiSheetDescription>
|
|
226
|
+
</UiSheetHeader>
|
|
227
|
+
<div class="flex-1 overflow-auto px-4 py-4 text-sm space-y-3">
|
|
228
|
+
<p>Click the buttons below to close programmatically.</p>
|
|
229
|
+
<div class="flex gap-2 flex-wrap">
|
|
230
|
+
<UiButton size="sm" @click="open = false">Close via model</UiButton>
|
|
231
|
+
<UiSheetClose as-child>
|
|
232
|
+
<UiButton size="sm" variant="outline">Close via UiSheetClose</UiButton>
|
|
233
|
+
</UiSheetClose>
|
|
234
|
+
</div>
|
|
235
|
+
</div>
|
|
236
|
+
</UiSheetContent>
|
|
237
|
+
</UiSheet>
|
|
238
|
+
`,
|
|
239
|
+
}),
|
|
240
|
+
parameters: {
|
|
241
|
+
controls: { disable: true },
|
|
242
|
+
docs: { source: { code: controlledTemplateSource } },
|
|
243
|
+
},
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
const sideVariantsTemplateSource = `<script setup lang="ts">
|
|
247
|
+
import {
|
|
248
|
+
UiSheet,
|
|
249
|
+
UiSheetTrigger,
|
|
250
|
+
UiSheetContent,
|
|
251
|
+
UiSheetHeader,
|
|
252
|
+
UiSheetTitle,
|
|
253
|
+
UiSheetDescription,
|
|
254
|
+
UiSheetClose,
|
|
255
|
+
UiButton,
|
|
256
|
+
} from '@aleph-alpha/ui-library'
|
|
257
|
+
</script>
|
|
258
|
+
|
|
259
|
+
<template>
|
|
260
|
+
<div class="flex flex-wrap gap-2">
|
|
261
|
+
<UiSheet v-for="side in ['top', 'right', 'bottom', 'left']" :key="side">
|
|
262
|
+
<UiSheetTrigger as-child>
|
|
263
|
+
<UiButton variant="outline">{{ side }}</UiButton>
|
|
264
|
+
</UiSheetTrigger>
|
|
265
|
+
<UiSheetContent :side="side">
|
|
266
|
+
<UiSheetHeader>
|
|
267
|
+
<UiSheetTitle>{{ side }} sheet</UiSheetTitle>
|
|
268
|
+
<UiSheetDescription>
|
|
269
|
+
This sheet slides in from the {{ side }}.
|
|
270
|
+
</UiSheetDescription>
|
|
271
|
+
</UiSheetHeader>
|
|
272
|
+
<div class="flex-1 overflow-auto px-4 py-4 text-sm">
|
|
273
|
+
Content for the {{ side }} sheet.
|
|
274
|
+
</div>
|
|
275
|
+
<UiSheetClose as-child>
|
|
276
|
+
<UiButton class="mx-4 mb-4">Close</UiButton>
|
|
277
|
+
</UiSheetClose>
|
|
278
|
+
</UiSheetContent>
|
|
279
|
+
</UiSheet>
|
|
280
|
+
</div>
|
|
281
|
+
</template>`;
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* All four side variants: top, right, bottom, left.
|
|
285
|
+
* The `side` prop on `UiSheetContent` controls the slide-in direction.
|
|
286
|
+
*/
|
|
287
|
+
export const SideVariants: Story = {
|
|
288
|
+
render: () => ({
|
|
289
|
+
components: {
|
|
290
|
+
UiSheet,
|
|
291
|
+
UiSheetClose,
|
|
292
|
+
UiSheetContent,
|
|
293
|
+
UiSheetDescription,
|
|
294
|
+
UiSheetHeader,
|
|
295
|
+
UiSheetTitle,
|
|
296
|
+
UiSheetTrigger,
|
|
297
|
+
UiButton,
|
|
298
|
+
},
|
|
299
|
+
template: `
|
|
300
|
+
<div class="flex flex-wrap gap-2">
|
|
301
|
+
<UiSheet v-for="side in ['top', 'right', 'bottom', 'left']" :key="side">
|
|
302
|
+
<UiSheetTrigger as-child>
|
|
303
|
+
<UiButton variant="outline">{{ side }}</UiButton>
|
|
304
|
+
</UiSheetTrigger>
|
|
305
|
+
<UiSheetContent :side="side">
|
|
306
|
+
<UiSheetHeader>
|
|
307
|
+
<UiSheetTitle>{{ side }} sheet</UiSheetTitle>
|
|
308
|
+
<UiSheetDescription>
|
|
309
|
+
This sheet slides in from the {{ side }}.
|
|
310
|
+
</UiSheetDescription>
|
|
311
|
+
</UiSheetHeader>
|
|
312
|
+
<div class="flex-1 overflow-auto px-4 py-4 text-sm">
|
|
313
|
+
Content for the {{ side }} sheet.
|
|
314
|
+
</div>
|
|
315
|
+
<UiSheetClose as-child>
|
|
316
|
+
<UiButton class="mx-4 mb-4">Close</UiButton>
|
|
317
|
+
</UiSheetClose>
|
|
318
|
+
</UiSheetContent>
|
|
319
|
+
</UiSheet>
|
|
320
|
+
</div>
|
|
321
|
+
`,
|
|
322
|
+
}),
|
|
323
|
+
parameters: {
|
|
324
|
+
controls: { disable: true },
|
|
325
|
+
docs: { source: { code: sideVariantsTemplateSource } },
|
|
326
|
+
},
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
const nonModalTemplateSource = `<script setup lang="ts">
|
|
330
|
+
import {
|
|
331
|
+
UiSheet,
|
|
332
|
+
UiSheetTrigger,
|
|
333
|
+
UiSheetContent,
|
|
334
|
+
UiSheetHeader,
|
|
335
|
+
UiSheetTitle,
|
|
336
|
+
UiSheetDescription,
|
|
337
|
+
UiSheetFooter,
|
|
338
|
+
UiSheetClose,
|
|
339
|
+
UiButton,
|
|
340
|
+
} from '@aleph-alpha/ui-library'
|
|
341
|
+
</script>
|
|
342
|
+
|
|
343
|
+
<template>
|
|
344
|
+
<div class="space-y-4">
|
|
345
|
+
<p class="text-sm text-muted-foreground">
|
|
346
|
+
Non-modal sheet: you can still interact with the page while it is open.
|
|
347
|
+
</p>
|
|
348
|
+
<UiSheet :modal="false">
|
|
349
|
+
<UiSheetTrigger as-child>
|
|
350
|
+
<UiButton variant="outline">Open non-modal</UiButton>
|
|
351
|
+
</UiSheetTrigger>
|
|
352
|
+
<UiSheetContent>
|
|
353
|
+
<UiSheetHeader>
|
|
354
|
+
<UiSheetTitle>Non-modal sheet</UiSheetTitle>
|
|
355
|
+
<UiSheetDescription>
|
|
356
|
+
Outside interaction is allowed.
|
|
357
|
+
</UiSheetDescription>
|
|
358
|
+
</UiSheetHeader>
|
|
359
|
+
<div class="flex-1 overflow-auto px-4 py-4 text-sm">
|
|
360
|
+
Try selecting text outside the sheet.
|
|
361
|
+
</div>
|
|
362
|
+
<UiSheetFooter>
|
|
363
|
+
<UiSheetClose as-child>
|
|
364
|
+
<UiButton>Close</UiButton>
|
|
365
|
+
</UiSheetClose>
|
|
366
|
+
</UiSheetFooter>
|
|
367
|
+
</UiSheetContent>
|
|
368
|
+
</UiSheet>
|
|
369
|
+
</div>
|
|
370
|
+
</template>`;
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Non-modal sheet (`modal=false`) where outside interaction remains possible.
|
|
374
|
+
* Use this for lightweight panels that shouldn't block the rest of the UI.
|
|
375
|
+
*/
|
|
376
|
+
export const NonModal: Story = {
|
|
377
|
+
render: () => ({
|
|
378
|
+
components: {
|
|
379
|
+
UiSheet,
|
|
380
|
+
UiSheetClose,
|
|
381
|
+
UiSheetContent,
|
|
382
|
+
UiSheetDescription,
|
|
383
|
+
UiSheetFooter,
|
|
384
|
+
UiSheetHeader,
|
|
385
|
+
UiSheetTitle,
|
|
386
|
+
UiSheetTrigger,
|
|
387
|
+
UiButton,
|
|
388
|
+
},
|
|
389
|
+
template: `
|
|
390
|
+
<div class="space-y-4">
|
|
391
|
+
<p class="text-sm text-muted-foreground">
|
|
392
|
+
Non-modal sheet: you can still interact with the page while it is open.
|
|
393
|
+
</p>
|
|
394
|
+
<UiSheet :modal="false">
|
|
395
|
+
<UiSheetTrigger as-child>
|
|
396
|
+
<UiButton variant="outline">Open non-modal</UiButton>
|
|
397
|
+
</UiSheetTrigger>
|
|
398
|
+
<UiSheetContent>
|
|
399
|
+
<UiSheetHeader>
|
|
400
|
+
<UiSheetTitle>Non-modal sheet</UiSheetTitle>
|
|
401
|
+
<UiSheetDescription>
|
|
402
|
+
Outside interaction is allowed.
|
|
403
|
+
</UiSheetDescription>
|
|
404
|
+
</UiSheetHeader>
|
|
405
|
+
<div class="flex-1 overflow-auto px-4 py-4 text-sm">
|
|
406
|
+
Try selecting text outside the sheet.
|
|
407
|
+
</div>
|
|
408
|
+
<UiSheetFooter>
|
|
409
|
+
<UiSheetClose as-child>
|
|
410
|
+
<UiButton>Close</UiButton>
|
|
411
|
+
</UiSheetClose>
|
|
412
|
+
</UiSheetFooter>
|
|
413
|
+
</UiSheetContent>
|
|
414
|
+
</UiSheet>
|
|
415
|
+
</div>
|
|
416
|
+
`,
|
|
417
|
+
}),
|
|
418
|
+
parameters: {
|
|
419
|
+
controls: { disable: true },
|
|
420
|
+
docs: { source: { code: nonModalTemplateSource } },
|
|
421
|
+
},
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
const withFormTemplateSource = `<script setup lang="ts">
|
|
425
|
+
import {
|
|
426
|
+
UiSheet,
|
|
427
|
+
UiSheetTrigger,
|
|
428
|
+
UiSheetContent,
|
|
429
|
+
UiSheetHeader,
|
|
430
|
+
UiSheetTitle,
|
|
431
|
+
UiSheetDescription,
|
|
432
|
+
UiSheetFooter,
|
|
433
|
+
UiSheetClose,
|
|
434
|
+
UiButton,
|
|
435
|
+
UiInput,
|
|
436
|
+
UiLabel,
|
|
437
|
+
} from '@aleph-alpha/ui-library'
|
|
438
|
+
import { ref } from 'vue'
|
|
439
|
+
|
|
440
|
+
const open = ref(false)
|
|
441
|
+
</script>
|
|
442
|
+
|
|
443
|
+
<template>
|
|
444
|
+
<UiSheet v-model:open="open">
|
|
445
|
+
<UiSheetTrigger as-child>
|
|
446
|
+
<UiButton variant="outline">Edit Profile</UiButton>
|
|
447
|
+
</UiSheetTrigger>
|
|
448
|
+
<UiSheetContent>
|
|
449
|
+
<UiSheetHeader>
|
|
450
|
+
<UiSheetTitle>Edit profile</UiSheetTitle>
|
|
451
|
+
<UiSheetDescription>
|
|
452
|
+
Make changes to your profile here. Click save when you're done.
|
|
453
|
+
</UiSheetDescription>
|
|
454
|
+
</UiSheetHeader>
|
|
455
|
+
<div class="flex-1 overflow-auto px-4 py-4 space-y-4">
|
|
456
|
+
<div class="space-y-2">
|
|
457
|
+
<UiLabel for="name">Name</UiLabel>
|
|
458
|
+
<UiInput id="name" placeholder="Enter your name" />
|
|
459
|
+
</div>
|
|
460
|
+
<div class="space-y-2">
|
|
461
|
+
<UiLabel for="email">Email</UiLabel>
|
|
462
|
+
<UiInput id="email" placeholder="Enter your email" />
|
|
463
|
+
</div>
|
|
464
|
+
</div>
|
|
465
|
+
<UiSheetFooter>
|
|
466
|
+
<UiSheetClose as-child>
|
|
467
|
+
<UiButton variant="outline">Cancel</UiButton>
|
|
468
|
+
</UiSheetClose>
|
|
469
|
+
<UiButton @click="open = false">Save changes</UiButton>
|
|
470
|
+
</UiSheetFooter>
|
|
471
|
+
</UiSheetContent>
|
|
472
|
+
</UiSheet>
|
|
473
|
+
</template>`;
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Sheet with a form layout for editing data.
|
|
477
|
+
* A common pattern for settings panels, profile editing, or filter configuration.
|
|
478
|
+
*/
|
|
479
|
+
export const WithForm: Story = {
|
|
480
|
+
render: () => ({
|
|
481
|
+
components: {
|
|
482
|
+
UiSheet,
|
|
483
|
+
UiSheetClose,
|
|
484
|
+
UiSheetContent,
|
|
485
|
+
UiSheetDescription,
|
|
486
|
+
UiSheetFooter,
|
|
487
|
+
UiSheetHeader,
|
|
488
|
+
UiSheetTitle,
|
|
489
|
+
UiSheetTrigger,
|
|
490
|
+
UiButton,
|
|
491
|
+
UiInput,
|
|
492
|
+
UiLabel,
|
|
493
|
+
},
|
|
494
|
+
setup() {
|
|
495
|
+
const open = ref(false);
|
|
496
|
+
return { open };
|
|
497
|
+
},
|
|
498
|
+
template: `
|
|
499
|
+
<UiSheet v-model:open="open">
|
|
500
|
+
<UiSheetTrigger as-child>
|
|
501
|
+
<UiButton variant="outline">Edit Profile</UiButton>
|
|
502
|
+
</UiSheetTrigger>
|
|
503
|
+
<UiSheetContent>
|
|
504
|
+
<UiSheetHeader>
|
|
505
|
+
<UiSheetTitle>Edit profile</UiSheetTitle>
|
|
506
|
+
<UiSheetDescription>
|
|
507
|
+
Make changes to your profile here. Click save when you're done.
|
|
508
|
+
</UiSheetDescription>
|
|
509
|
+
</UiSheetHeader>
|
|
510
|
+
<div class="flex-1 overflow-auto px-4 py-4 space-y-4">
|
|
511
|
+
<div class="space-y-2">
|
|
512
|
+
<UiLabel for="name">Name</UiLabel>
|
|
513
|
+
<UiInput id="name" placeholder="Enter your name" />
|
|
514
|
+
</div>
|
|
515
|
+
<div class="space-y-2">
|
|
516
|
+
<UiLabel for="email">Email</UiLabel>
|
|
517
|
+
<UiInput id="email" placeholder="Enter your email" />
|
|
518
|
+
</div>
|
|
519
|
+
</div>
|
|
520
|
+
<UiSheetFooter>
|
|
521
|
+
<UiSheetClose as-child>
|
|
522
|
+
<UiButton variant="outline">Cancel</UiButton>
|
|
523
|
+
</UiSheetClose>
|
|
524
|
+
<UiButton @click="open = false">Save changes</UiButton>
|
|
525
|
+
</UiSheetFooter>
|
|
526
|
+
</UiSheetContent>
|
|
527
|
+
</UiSheet>
|
|
528
|
+
`,
|
|
529
|
+
}),
|
|
530
|
+
parameters: {
|
|
531
|
+
controls: { disable: true },
|
|
532
|
+
docs: { source: { code: withFormTemplateSource } },
|
|
533
|
+
},
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
const longContentTemplateSource = `<script setup lang="ts">
|
|
537
|
+
import {
|
|
538
|
+
UiSheet,
|
|
539
|
+
UiSheetTrigger,
|
|
540
|
+
UiSheetContent,
|
|
541
|
+
UiSheetHeader,
|
|
542
|
+
UiSheetTitle,
|
|
543
|
+
UiSheetDescription,
|
|
544
|
+
UiSheetFooter,
|
|
545
|
+
UiSheetClose,
|
|
546
|
+
UiButton,
|
|
547
|
+
} from '@aleph-alpha/ui-library'
|
|
548
|
+
</script>
|
|
549
|
+
|
|
550
|
+
<template>
|
|
551
|
+
<UiSheet>
|
|
552
|
+
<UiSheetTrigger as-child>
|
|
553
|
+
<UiButton variant="outline">Open long content</UiButton>
|
|
554
|
+
</UiSheetTrigger>
|
|
555
|
+
<UiSheetContent>
|
|
556
|
+
<UiSheetHeader>
|
|
557
|
+
<UiSheetTitle>Long content</UiSheetTitle>
|
|
558
|
+
<UiSheetDescription>
|
|
559
|
+
Demonstrates scrolling content inside the sheet.
|
|
560
|
+
</UiSheetDescription>
|
|
561
|
+
</UiSheetHeader>
|
|
562
|
+
<div class="flex-1 overflow-auto px-4 py-4">
|
|
563
|
+
<div class="space-y-2 text-sm">
|
|
564
|
+
<p v-for="i in 30" :key="i">Item {{ i }} — Lorem ipsum dolor sit amet.</p>
|
|
565
|
+
</div>
|
|
566
|
+
</div>
|
|
567
|
+
<UiSheetFooter>
|
|
568
|
+
<UiSheetClose as-child>
|
|
569
|
+
<UiButton>Close</UiButton>
|
|
570
|
+
</UiSheetClose>
|
|
571
|
+
</UiSheetFooter>
|
|
572
|
+
</UiSheetContent>
|
|
573
|
+
</UiSheet>
|
|
574
|
+
</template>`;
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* Sheet with scrollable content.
|
|
578
|
+
* Use this for lists or forms that exceed the viewport height.
|
|
579
|
+
*/
|
|
580
|
+
export const LongContent: Story = {
|
|
581
|
+
render: () => ({
|
|
582
|
+
components: {
|
|
583
|
+
UiSheet,
|
|
584
|
+
UiSheetClose,
|
|
585
|
+
UiSheetContent,
|
|
586
|
+
UiSheetDescription,
|
|
587
|
+
UiSheetFooter,
|
|
588
|
+
UiSheetHeader,
|
|
589
|
+
UiSheetTitle,
|
|
590
|
+
UiSheetTrigger,
|
|
591
|
+
UiButton,
|
|
592
|
+
},
|
|
593
|
+
template: `
|
|
594
|
+
<UiSheet>
|
|
595
|
+
<UiSheetTrigger as-child>
|
|
596
|
+
<UiButton variant="outline">Open long content</UiButton>
|
|
597
|
+
</UiSheetTrigger>
|
|
598
|
+
<UiSheetContent>
|
|
599
|
+
<UiSheetHeader>
|
|
600
|
+
<UiSheetTitle>Long content</UiSheetTitle>
|
|
601
|
+
<UiSheetDescription>
|
|
602
|
+
Demonstrates scrolling content inside the sheet.
|
|
603
|
+
</UiSheetDescription>
|
|
604
|
+
</UiSheetHeader>
|
|
605
|
+
<div class="flex-1 overflow-auto px-4 py-4">
|
|
606
|
+
<div class="space-y-2 text-sm">
|
|
607
|
+
<p v-for="i in 30" :key="i">Item {{ i }} — Lorem ipsum dolor sit amet.</p>
|
|
608
|
+
</div>
|
|
609
|
+
</div>
|
|
610
|
+
<UiSheetFooter>
|
|
611
|
+
<UiSheetClose as-child>
|
|
612
|
+
<UiButton>Close</UiButton>
|
|
613
|
+
</UiSheetClose>
|
|
614
|
+
</UiSheetFooter>
|
|
615
|
+
</UiSheetContent>
|
|
616
|
+
</UiSheet>
|
|
617
|
+
`,
|
|
618
|
+
}),
|
|
619
|
+
parameters: {
|
|
620
|
+
controls: { disable: true },
|
|
621
|
+
docs: { source: { code: longContentTemplateSource } },
|
|
622
|
+
},
|
|
623
|
+
};
|
|
624
|
+
|
|
625
|
+
const openByDefaultTemplateSource = `<script setup lang="ts">
|
|
626
|
+
import {
|
|
627
|
+
UiSheet,
|
|
628
|
+
UiSheetTrigger,
|
|
629
|
+
UiSheetContent,
|
|
630
|
+
UiSheetHeader,
|
|
631
|
+
UiSheetTitle,
|
|
632
|
+
UiSheetDescription,
|
|
633
|
+
UiSheetFooter,
|
|
634
|
+
UiSheetClose,
|
|
635
|
+
UiButton,
|
|
636
|
+
} from '@aleph-alpha/ui-library'
|
|
637
|
+
import { ref } from 'vue'
|
|
638
|
+
|
|
639
|
+
const open = ref(true)
|
|
640
|
+
</script>
|
|
641
|
+
|
|
642
|
+
<template>
|
|
643
|
+
<UiSheet v-model:open="open">
|
|
644
|
+
<UiSheetTrigger as-child>
|
|
645
|
+
<UiButton variant="outline">Toggle Sheet</UiButton>
|
|
646
|
+
</UiSheetTrigger>
|
|
647
|
+
<UiSheetContent>
|
|
648
|
+
<UiSheetHeader>
|
|
649
|
+
<UiSheetTitle>Open by default</UiSheetTitle>
|
|
650
|
+
<UiSheetDescription>
|
|
651
|
+
Useful for visual regression testing.
|
|
652
|
+
</UiSheetDescription>
|
|
653
|
+
</UiSheetHeader>
|
|
654
|
+
<div class="flex-1 overflow-auto px-4 py-4 text-sm">
|
|
655
|
+
This sheet starts open.
|
|
656
|
+
</div>
|
|
657
|
+
<UiSheetFooter>
|
|
658
|
+
<UiSheetClose as-child>
|
|
659
|
+
<UiButton>Close</UiButton>
|
|
660
|
+
</UiSheetClose>
|
|
661
|
+
</UiSheetFooter>
|
|
662
|
+
</UiSheetContent>
|
|
663
|
+
</UiSheet>
|
|
664
|
+
</template>`;
|
|
665
|
+
|
|
666
|
+
/**
|
|
667
|
+
* Sheet that starts open.
|
|
668
|
+
* Use this for visual regression testing to capture sheet content without user interaction.
|
|
669
|
+
*/
|
|
670
|
+
export const OpenByDefault: Story = {
|
|
671
|
+
render: () => ({
|
|
672
|
+
components: {
|
|
673
|
+
UiSheet,
|
|
674
|
+
UiSheetClose,
|
|
675
|
+
UiSheetContent,
|
|
676
|
+
UiSheetDescription,
|
|
677
|
+
UiSheetFooter,
|
|
678
|
+
UiSheetHeader,
|
|
679
|
+
UiSheetTitle,
|
|
680
|
+
UiSheetTrigger,
|
|
681
|
+
UiButton,
|
|
682
|
+
},
|
|
683
|
+
setup() {
|
|
684
|
+
const open = ref(true);
|
|
685
|
+
return { open };
|
|
686
|
+
},
|
|
687
|
+
template: `
|
|
688
|
+
<UiSheet v-model:open="open">
|
|
689
|
+
<UiSheetTrigger as-child>
|
|
690
|
+
<UiButton variant="outline">Toggle Sheet</UiButton>
|
|
691
|
+
</UiSheetTrigger>
|
|
692
|
+
<UiSheetContent>
|
|
693
|
+
<UiSheetHeader>
|
|
694
|
+
<UiSheetTitle>Open by default</UiSheetTitle>
|
|
695
|
+
<UiSheetDescription>
|
|
696
|
+
Useful for visual regression testing.
|
|
697
|
+
</UiSheetDescription>
|
|
698
|
+
</UiSheetHeader>
|
|
699
|
+
<div class="flex-1 overflow-auto px-4 py-4 text-sm">
|
|
700
|
+
This sheet starts open.
|
|
701
|
+
</div>
|
|
702
|
+
<UiSheetFooter>
|
|
703
|
+
<UiSheetClose as-child>
|
|
704
|
+
<UiButton>Close</UiButton>
|
|
705
|
+
</UiSheetClose>
|
|
706
|
+
</UiSheetFooter>
|
|
707
|
+
</UiSheetContent>
|
|
708
|
+
</UiSheet>
|
|
709
|
+
`,
|
|
710
|
+
}),
|
|
711
|
+
parameters: {
|
|
712
|
+
controls: { disable: true },
|
|
713
|
+
docs: { source: { code: openByDefaultTemplateSource } },
|
|
714
|
+
},
|
|
715
|
+
};
|