@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,425 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3-vite';
2
+ import { ref, watch } from 'vue';
3
+ import {
4
+ UiStepper,
5
+ UiStepperItem,
6
+ UiStepperTrigger,
7
+ UiStepperIndicator,
8
+ UiStepperTitle,
9
+ UiStepperDescription,
10
+ UiStepperSeparator,
11
+ } from './index';
12
+ import { UiIcon } from '../UiIcon';
13
+
14
+ const meta: Meta<typeof UiStepper> = {
15
+ title: 'Primitives/UiStepper',
16
+ component: UiStepper,
17
+ tags: ['autodocs'],
18
+ argTypes: {
19
+ modelValue: {
20
+ control: 'number',
21
+ description: 'The controlled value of the active step (use with v-model)',
22
+ },
23
+ defaultValue: {
24
+ control: 'number',
25
+ },
26
+ orientation: {
27
+ control: 'select',
28
+ options: ['horizontal', 'vertical'],
29
+ },
30
+ linear: {
31
+ control: 'boolean',
32
+ description:
33
+ 'Whether navigation must be sequential (user cannot skip ahead to incomplete steps)',
34
+ },
35
+ },
36
+ args: {
37
+ orientation: 'horizontal',
38
+ linear: true,
39
+ },
40
+ };
41
+
42
+ export default meta;
43
+
44
+ type Story = StoryObj<typeof UiStepper>;
45
+
46
+ const defaultTemplateSource = `<script setup lang="ts">
47
+ import { ref } from 'vue'
48
+ import {
49
+ UiStepper,
50
+ UiStepperItem,
51
+ UiStepperTrigger,
52
+ UiStepperIndicator,
53
+ UiStepperTitle,
54
+ UiStepperDescription,
55
+ UiStepperSeparator,
56
+ UiIcon,
57
+ } from '@aleph-alpha/ui-library'
58
+
59
+ const currentStep = ref(1)
60
+
61
+ const steps = [
62
+ { step: 1, title: 'Address', description: 'Add your address', icon: 'book-user' },
63
+ { step: 2, title: 'Shipping', description: 'Set your preferred', icon: 'truck' },
64
+ { step: 3, title: 'Payment', description: 'Add any payment', icon: 'credit-card' },
65
+ { step: 4, title: 'Checkout', description: 'Confirm your order' },
66
+ ]
67
+ </script>
68
+
69
+ <template>
70
+ <UiStepper v-model="currentStep" class="flex w-full items-start gap-2">
71
+ <UiStepperItem
72
+ v-for="item in steps"
73
+ :key="item.step"
74
+ :step="item.step"
75
+ class="relative flex w-full flex-col items-center justify-center"
76
+ >
77
+ <UiStepperTrigger>
78
+ <UiStepperIndicator class="">
79
+ <UiIcon v-if="item.icon" :name="item.icon" :size="16" />
80
+ <span v-else>{{ item.step }}</span>
81
+ </UiStepperIndicator>
82
+ </UiStepperTrigger>
83
+ <UiStepperSeparator
84
+ v-if="item.step !== steps[steps.length - 1]?.step"
85
+ />
86
+ <div class="flex flex-col items-center">
87
+ <UiStepperTitle>{{ item.title }}</UiStepperTitle>
88
+ <UiStepperDescription>{{ item.description }}</UiStepperDescription>
89
+ </div>
90
+ </UiStepperItem>
91
+ </UiStepper>
92
+ </template>`;
93
+
94
+ /**
95
+ * Default stepper with icon indicators for each step. Steps without an icon
96
+ * fall back to displaying the step number. Use for multi-step workflows like
97
+ * checkout flows or onboarding sequences.
98
+ */
99
+ export const Default: Story = {
100
+ render: (args) => ({
101
+ components: {
102
+ UiStepper,
103
+ UiStepperItem,
104
+ UiStepperTrigger,
105
+ UiStepperIndicator,
106
+ UiStepperTitle,
107
+ UiStepperDescription,
108
+ UiStepperSeparator,
109
+ UiIcon,
110
+ },
111
+ setup() {
112
+ const currentStep = ref(args.modelValue ?? 1);
113
+ watch(
114
+ () => args.modelValue,
115
+ (val) => {
116
+ if (val != null) currentStep.value = val;
117
+ },
118
+ );
119
+ const steps = [
120
+ { step: 1, title: 'Address', description: 'Add your address', icon: 'book-user' },
121
+ { step: 2, title: 'Shipping', description: 'Set your preferred', icon: 'truck' },
122
+ { step: 3, title: 'Payment', description: 'Add any payment', icon: 'credit-card' },
123
+ { step: 4, title: 'Checkout', description: 'Confirm your order' },
124
+ ];
125
+ return { args, currentStep, steps };
126
+ },
127
+ template: `
128
+ <UiStepper
129
+ v-model="currentStep"
130
+ :orientation="args.orientation"
131
+ :linear="args.linear"
132
+ :class="args.orientation === 'vertical'
133
+ ? 'mx-auto flex w-full max-w-md flex-col justify-start gap-10'
134
+ : 'flex w-full items-start gap-2'"
135
+ >
136
+ <UiStepperItem
137
+ v-for="item in steps"
138
+ :key="item.step"
139
+ :step="item.step"
140
+ :class="args.orientation === 'vertical'
141
+ ? 'relative flex w-full items-start justify-start gap-6'
142
+ : 'relative flex w-full flex-col items-center justify-center'"
143
+ >
144
+ <UiStepperTrigger>
145
+ <UiStepperIndicator>
146
+ <UiIcon v-if="item.icon" :name="item.icon" :size="16" />
147
+ <span v-else>{{ item.step }}</span>
148
+ </UiStepperIndicator>
149
+ </UiStepperTrigger>
150
+ <UiStepperSeparator
151
+ v-if="item.step !== steps[steps.length - 1]?.step"
152
+ />
153
+ <div :class="args.orientation === 'vertical' ? 'flex flex-col gap-1' : 'flex flex-col items-center'">
154
+ <UiStepperTitle>{{ item.title }}</UiStepperTitle>
155
+ <UiStepperDescription>{{ item.description }}</UiStepperDescription>
156
+ </div>
157
+ </UiStepperItem>
158
+ </UiStepper>
159
+ `,
160
+ }),
161
+ parameters: {
162
+ docs: {
163
+ source: {
164
+ code: defaultTemplateSource,
165
+ },
166
+ },
167
+ },
168
+ };
169
+
170
+ const horizontalTemplateSource = `<script setup lang="ts">
171
+ import { ref } from 'vue'
172
+ import {
173
+ UiStepper,
174
+ UiStepperItem,
175
+ UiStepperTrigger,
176
+ UiStepperIndicator,
177
+ UiStepperTitle,
178
+ UiStepperDescription,
179
+ UiStepperSeparator,
180
+ UiIcon,
181
+ } from '@aleph-alpha/ui-library'
182
+
183
+ const currentStep = ref(1)
184
+
185
+ const steps = [
186
+ { step: 1, title: 'Your details', description: 'Provide your name and email' },
187
+ { step: 2, title: 'Company details', description: 'A few details about your company' },
188
+ { step: 3, title: 'Invite your team', description: 'Start collaborating with your team' },
189
+ ]
190
+ </script>
191
+
192
+ <template>
193
+ <UiStepper v-model="currentStep" :linear="true" class="flex w-full items-start gap-2">
194
+ <UiStepperItem
195
+ v-for="step in steps"
196
+ :key="step.step"
197
+ v-slot="{ state }"
198
+ :step="step.step"
199
+ class="relative flex w-full flex-col items-center justify-center"
200
+ >
201
+ <UiStepperTrigger>
202
+ <UiStepperIndicator
203
+ :class="[
204
+ state === 'completed' && 'bg-[oklch(var(--background-accent-default))] group-data-[state=completed]:text-content-on-accent-default',
205
+ state === 'inactive' && 'bg-transparent border-2 border-content-on-surface-muted/30',
206
+ ]"
207
+ >
208
+ <UiIcon v-if="state === 'completed'" name="check" class="size-5" />
209
+ <UiIcon v-if="state === 'active'" name="circle" class="size-4" />
210
+ <UiIcon v-if="state === 'inactive'" name="dot" class="size-4" />
211
+ </UiStepperIndicator>
212
+ </UiStepperTrigger>
213
+ <UiStepperSeparator
214
+ v-if="step.step !== steps[steps.length - 1]?.step"
215
+ />
216
+ <div class="flex flex-col items-center text-center">
217
+ <UiStepperTitle>{{ step.title }}</UiStepperTitle>
218
+ <UiStepperDescription>{{ step.description }}</UiStepperDescription>
219
+ </div>
220
+ </UiStepperItem>
221
+ </UiStepper>
222
+ </template>`;
223
+
224
+ /**
225
+ * Horizontal stepper with check/circle/dot icons. Completed and active steps
226
+ * show a filled blue indicator, inactive steps show an outlined circle.
227
+ */
228
+ export const Horizontal: Story = {
229
+ render: () => ({
230
+ components: {
231
+ UiStepper,
232
+ UiStepperItem,
233
+ UiStepperTrigger,
234
+ UiStepperIndicator,
235
+ UiStepperTitle,
236
+ UiStepperDescription,
237
+ UiStepperSeparator,
238
+ UiIcon,
239
+ },
240
+ setup() {
241
+ const currentStep = ref(1);
242
+ const steps = [
243
+ { step: 1, title: 'Your details', description: 'Provide your name and email' },
244
+ {
245
+ step: 2,
246
+ title: 'Company details',
247
+ description: 'A few details about your company',
248
+ },
249
+ {
250
+ step: 3,
251
+ title: 'Invite your team',
252
+ description: 'Start collaborating with your team',
253
+ },
254
+ ];
255
+ return { currentStep, steps };
256
+ },
257
+ template: `
258
+ <UiStepper v-model="currentStep" :linear="true" class="flex w-full items-start gap-2">
259
+ <UiStepperItem
260
+ v-for="step in steps"
261
+ :key="step.step"
262
+ v-slot="{ state }"
263
+ :step="step.step"
264
+ class="relative flex w-full flex-col items-center justify-center"
265
+ >
266
+ <UiStepperTrigger>
267
+ <UiStepperIndicator
268
+ :class="[
269
+ state === 'completed' && 'bg-[oklch(var(--background-accent-default))] group-data-[state=completed]:text-content-on-accent-default',
270
+ state === 'inactive' && 'bg-transparent border-2 border-content-on-surface-muted/30',
271
+ ]"
272
+ >
273
+ <UiIcon v-if="state === 'completed'" name="check" class="size-5" />
274
+ <UiIcon v-if="state === 'active'" name="circle" class="size-4" />
275
+ <UiIcon v-if="state === 'inactive'" name="dot" class="size-4" />
276
+ </UiStepperIndicator>
277
+ </UiStepperTrigger>
278
+ <UiStepperSeparator
279
+ v-if="step.step !== steps[steps.length - 1]?.step"
280
+ />
281
+ <div class="flex flex-col items-center text-center">
282
+ <UiStepperTitle>{{ step.title }}</UiStepperTitle>
283
+ <UiStepperDescription>{{ step.description }}</UiStepperDescription>
284
+ </div>
285
+ </UiStepperItem>
286
+ </UiStepper>
287
+ `,
288
+ }),
289
+ parameters: {
290
+ docs: {
291
+ source: {
292
+ code: horizontalTemplateSource,
293
+ },
294
+ },
295
+ },
296
+ };
297
+
298
+ const verticalTemplateSource = `<script setup lang="ts">
299
+ import { ref } from 'vue'
300
+ import {
301
+ UiStepper,
302
+ UiStepperItem,
303
+ UiStepperTrigger,
304
+ UiStepperIndicator,
305
+ UiStepperTitle,
306
+ UiStepperDescription,
307
+ UiStepperSeparator,
308
+ UiIcon,
309
+ } from '@aleph-alpha/ui-library'
310
+
311
+ const currentStep = ref(1)
312
+
313
+ const steps = [
314
+ { step: 1, title: 'Your details', description: 'Provide your name and email' },
315
+ { step: 2, title: 'Company details', description: 'A few details about your company' },
316
+ { step: 3, title: 'Invite your team', description: 'Start collaborating with your team' },
317
+ ]
318
+ </script>
319
+
320
+ <template>
321
+ <UiStepper v-model="currentStep" orientation="vertical" :linear="true" class="mx-auto flex w-full max-w-md flex-col justify-start gap-10">
322
+ <UiStepperItem
323
+ v-for="step in steps"
324
+ :key="step.step"
325
+ v-slot="{ state }"
326
+ :step="step.step"
327
+ class="relative flex w-full items-start justify-start gap-6"
328
+ >
329
+ <UiStepperTrigger>
330
+ <UiStepperIndicator
331
+ :class="[
332
+ state === 'completed' && 'bg-[oklch(var(--background-accent-default))] group-data-[state=completed]:text-content-on-accent-default',
333
+ state === 'inactive' && 'bg-transparent border-2 border-content-on-surface-muted/30',
334
+ ]"
335
+ >
336
+ <UiIcon v-if="state === 'completed'" name="check" class="size-5" />
337
+ <UiIcon v-if="state === 'active'" name="circle" class="size-4" />
338
+ <UiIcon v-if="state === 'inactive'" name="dot" class="size-4" />
339
+ </UiStepperIndicator>
340
+ </UiStepperTrigger>
341
+ <UiStepperSeparator
342
+ v-if="step.step !== steps[steps.length - 1]?.step"
343
+ />
344
+ <div class="flex flex-col gap-1">
345
+ <UiStepperTitle>{{ step.title }}</UiStepperTitle>
346
+ <UiStepperDescription>{{ step.description }}</UiStepperDescription>
347
+ </div>
348
+ </UiStepperItem>
349
+ </UiStepper>
350
+ </template>`;
351
+
352
+ /**
353
+ * Vertical stepper with check/circle/dot icons. Uses the same indicator
354
+ * pattern as Horizontal but with vertical layout and connecting lines
355
+ * running top-to-bottom.
356
+ */
357
+ export const Vertical: Story = {
358
+ render: () => ({
359
+ components: {
360
+ UiStepper,
361
+ UiStepperItem,
362
+ UiStepperTrigger,
363
+ UiStepperIndicator,
364
+ UiStepperTitle,
365
+ UiStepperDescription,
366
+ UiStepperSeparator,
367
+ UiIcon,
368
+ },
369
+ setup() {
370
+ const currentStep = ref(1);
371
+ const steps = [
372
+ { step: 1, title: 'Your details', description: 'Provide your name and email' },
373
+ {
374
+ step: 2,
375
+ title: 'Company details',
376
+ description: 'A few details about your company',
377
+ },
378
+ {
379
+ step: 3,
380
+ title: 'Invite your team',
381
+ description: 'Start collaborating with your team',
382
+ },
383
+ ];
384
+ return { currentStep, steps };
385
+ },
386
+ template: `
387
+ <UiStepper v-model="currentStep" orientation="vertical" :linear="true" class="mx-auto flex w-full max-w-md flex-col justify-start gap-10">
388
+ <UiStepperItem
389
+ v-for="step in steps"
390
+ :key="step.step"
391
+ v-slot="{ state }"
392
+ :step="step.step"
393
+ class="relative flex w-full items-start justify-start gap-6"
394
+ >
395
+ <UiStepperTrigger>
396
+ <UiStepperIndicator
397
+ :class="[
398
+ state === 'completed' && 'bg-[oklch(var(--background-accent-default))] group-data-[state=completed]:text-content-on-accent-default',
399
+ state === 'inactive' && 'bg-transparent border-2 border-content-on-surface-muted/30',
400
+ ]"
401
+ >
402
+ <UiIcon v-if="state === 'completed'" name="check" class="size-5" />
403
+ <UiIcon v-if="state === 'active'" name="circle" class="size-4" />
404
+ <UiIcon v-if="state === 'inactive'" name="dot" class="size-4" />
405
+ </UiStepperIndicator>
406
+ </UiStepperTrigger>
407
+ <UiStepperSeparator
408
+ v-if="step.step !== steps[steps.length - 1]?.step"
409
+ />
410
+ <div class="flex flex-col gap-1">
411
+ <UiStepperTitle>{{ step.title }}</UiStepperTitle>
412
+ <UiStepperDescription>{{ step.description }}</UiStepperDescription>
413
+ </div>
414
+ </UiStepperItem>
415
+ </UiStepper>
416
+ `,
417
+ }),
418
+ parameters: {
419
+ docs: {
420
+ source: {
421
+ code: verticalTemplateSource,
422
+ },
423
+ },
424
+ },
425
+ };
@@ -0,0 +1,27 @@
1
+ <script setup lang="ts">
2
+ import { Stepper as ShadcnStepper } from '@/components/core/stepper';
3
+ import type { UiStepperProps } from './types';
4
+
5
+ defineOptions({
6
+ name: 'UiStepper',
7
+ });
8
+
9
+ defineProps<UiStepperProps>();
10
+ const model = defineModel<number>();
11
+ </script>
12
+
13
+ <template>
14
+ <ShadcnStepper
15
+ #default="slotProps"
16
+ v-model="model"
17
+ :default-value="$props.defaultValue"
18
+ :orientation="$props.orientation"
19
+ :linear="$props.linear"
20
+ :class="[
21
+ 'w-full items-start',
22
+ 'data-[orientation=vertical]:flex-col data-[orientation=vertical]:gap-10',
23
+ ]"
24
+ >
25
+ <slot v-bind="slotProps" />
26
+ </ShadcnStepper>
27
+ </template>
@@ -0,0 +1,20 @@
1
+ <script setup lang="ts">
2
+ import { StepperDescription as ShadcnStepperDescription } from '@/components/core/stepper';
3
+
4
+ defineOptions({
5
+ name: 'UiStepperDescription',
6
+ });
7
+ </script>
8
+
9
+ <template>
10
+ <ShadcnStepperDescription
11
+ #default="slotProps"
12
+ :class="[
13
+ 'transition-colors',
14
+ 'group-data-[state=active]:text-content-on-surface-primary',
15
+ 'group-data-[state=completed]:text-content-on-surface-primary',
16
+ ]"
17
+ >
18
+ <slot v-bind="slotProps" />
19
+ </ShadcnStepperDescription>
20
+ </template>
@@ -0,0 +1,13 @@
1
+ <script setup lang="ts">
2
+ import { StepperIndicator as ShadcnStepperIndicator } from '@/components/core/stepper';
3
+
4
+ defineOptions({
5
+ name: 'UiStepperIndicator',
6
+ });
7
+ </script>
8
+
9
+ <template>
10
+ <ShadcnStepperIndicator #default="slotProps" :class="['transition-colors']">
11
+ <slot v-bind="slotProps" />
12
+ </ShadcnStepperIndicator>
13
+ </template>
@@ -0,0 +1,25 @@
1
+ <script setup lang="ts">
2
+ import { StepperItem as ShadcnStepperItem } from '@/components/core/stepper';
3
+ import type { UiStepperItemProps } from './types';
4
+
5
+ defineOptions({
6
+ name: 'UiStepperItem',
7
+ });
8
+
9
+ const props = defineProps<UiStepperItemProps>();
10
+ </script>
11
+
12
+ <template>
13
+ <ShadcnStepperItem
14
+ #default="slotProps"
15
+ :step="props.step"
16
+ :disabled="props.disabled"
17
+ :completed="props.completed"
18
+ :class="[
19
+ 'relative w-full flex-col justify-center',
20
+ 'data-[orientation=vertical]:flex-row data-[orientation=vertical]:items-start data-[orientation=vertical]:gap-6',
21
+ ]"
22
+ >
23
+ <slot v-bind="slotProps" />
24
+ </ShadcnStepperItem>
25
+ </template>
@@ -0,0 +1,17 @@
1
+ <script setup lang="ts">
2
+ import { StepperSeparator as ShadcnStepperSeparator } from '@/components/core/stepper';
3
+
4
+ defineOptions({
5
+ name: 'UiStepperSeparator',
6
+ });
7
+ </script>
8
+
9
+ <template>
10
+ <ShadcnStepperSeparator
11
+ :class="[
12
+ 'absolute block shrink-0 rounded-full transition-colors',
13
+ 'left-[calc(50%+24px)] right-[calc(-50%+16px)] top-[23px] h-0.5',
14
+ 'group-data-[orientation=vertical]:left-[23px] group-data-[orientation=vertical]:top-[48px] group-data-[orientation=vertical]:bottom-[-40px] group-data-[orientation=vertical]:h-auto group-data-[orientation=vertical]:w-0.5 group-data-[orientation=vertical]:right-auto',
15
+ ]"
16
+ />
17
+ </template>
@@ -0,0 +1,19 @@
1
+ <script setup lang="ts">
2
+ import { StepperTitle as ShadcnStepperTitle } from '@/components/core/stepper';
3
+
4
+ defineOptions({
5
+ name: 'UiStepperTitle',
6
+ });
7
+ </script>
8
+
9
+ <template>
10
+ <ShadcnStepperTitle
11
+ :class="[
12
+ 'transition-colors',
13
+ 'group-data-[state=active]:text-content-on-surface-primary',
14
+ 'group-data-[state=completed]:text-content-on-surface-primary',
15
+ ]"
16
+ >
17
+ <slot />
18
+ </ShadcnStepperTitle>
19
+ </template>
@@ -0,0 +1,18 @@
1
+ <script setup lang="ts">
2
+ import { StepperTrigger as ShadcnStepperTrigger } from '@/components/core/stepper';
3
+ import type { UiStepperTriggerProps } from './types';
4
+
5
+ defineOptions({
6
+ name: 'UiStepperTrigger',
7
+ });
8
+
9
+ const props = withDefaults(defineProps<UiStepperTriggerProps>(), {
10
+ asChild: false,
11
+ });
12
+ </script>
13
+
14
+ <template>
15
+ <ShadcnStepperTrigger :as-child="props.asChild">
16
+ <slot />
17
+ </ShadcnStepperTrigger>
18
+ </template>