@polymarbot/nuxt-layer-shadcn-ui 0.3.10 → 0.4.1

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 (61) hide show
  1. package/app/components/ui/Accordion/index.stories.ts +43 -15
  2. package/app/components/ui/AdminLayout/index.stories.ts +6 -14
  3. package/app/components/ui/Alert/index.stories.ts +32 -2
  4. package/app/components/ui/AlertDialog/index.stories.ts +114 -5
  5. package/app/components/ui/AsyncDataTable/index.stories.ts +36 -2
  6. package/app/components/ui/Avatar/index.stories.ts +58 -4
  7. package/app/components/ui/Badge/index.stories.ts +48 -3
  8. package/app/components/ui/Breadcrumb/index.stories.ts +8 -19
  9. package/app/components/ui/Button/index.stories.ts +116 -7
  10. package/app/components/ui/ButtonGroup/index.stories.ts +63 -4
  11. package/app/components/ui/Card/index.stories.ts +40 -14
  12. package/app/components/ui/Checkbox/index.stories.ts +53 -3
  13. package/app/components/ui/CopyButton/index.stories.ts +77 -5
  14. package/app/components/ui/DataTable/index.stories.ts +184 -11
  15. package/app/components/ui/DatePicker/index.stories.ts +56 -7
  16. package/app/components/ui/DateRangePicker/index.stories.ts +40 -5
  17. package/app/components/ui/Divider/index.stories.ts +18 -15
  18. package/app/components/ui/Drawer/index.stories.ts +115 -16
  19. package/app/components/ui/Drawer/index.vue +27 -12
  20. package/app/components/ui/Dropdown/index.stories.ts +72 -54
  21. package/app/components/ui/Dropdown/index.vue +5 -8
  22. package/app/components/ui/Dropdown/types.ts +3 -8
  23. package/app/components/ui/FormItem/index.stories.ts +33 -45
  24. package/app/components/ui/Help/index.stories.ts +34 -2
  25. package/app/components/ui/Icon/index.stories.ts +41 -2
  26. package/app/components/ui/Input/index.stories.ts +73 -14
  27. package/app/components/ui/InputCurrency/index.stories.ts +20 -65
  28. package/app/components/ui/InputNumber/index.stories.ts +31 -58
  29. package/app/components/ui/InputOtp/index.stories.ts +41 -9
  30. package/app/components/ui/InputPercent/index.stories.ts +3 -7
  31. package/app/components/ui/InputRange/index.stories.ts +51 -4
  32. package/app/components/ui/Loading/index.stories.ts +16 -1
  33. package/app/components/ui/Markdown/index.stories.ts +9 -0
  34. package/app/components/ui/Modal/index.stories.ts +133 -16
  35. package/app/components/ui/Modal/index.vue +27 -12
  36. package/app/components/ui/ModalContent/index.stories.ts +35 -11
  37. package/app/components/ui/PageCard/index.stories.ts +154 -56
  38. package/app/components/ui/Pagination/index.stories.ts +79 -18
  39. package/app/components/ui/Pagination/index.vue +4 -1
  40. package/app/components/ui/Popover/index.stories.ts +73 -3
  41. package/app/components/ui/Popover/index.vue +67 -4
  42. package/app/components/ui/Popover/types.ts +5 -2
  43. package/app/components/ui/Qrcode/index.stories.ts +32 -2
  44. package/app/components/ui/RadioCardGroup/index.stories.ts +45 -6
  45. package/app/components/ui/RadioGroup/index.stories.ts +64 -35
  46. package/app/components/ui/ScrollArea/index.stories.ts +21 -23
  47. package/app/components/ui/SearchSelect/index.stories.ts +73 -24
  48. package/app/components/ui/Select/index.stories.ts +121 -6
  49. package/app/components/ui/Skeleton/index.stories.ts +34 -2
  50. package/app/components/ui/Slider/index.stories.ts +67 -4
  51. package/app/components/ui/Surface/index.stories.ts +86 -5
  52. package/app/components/ui/Surface/index.vue +115 -2
  53. package/app/components/ui/Surface/types.ts +2 -0
  54. package/app/components/ui/Switch/index.stories.ts +46 -0
  55. package/app/components/ui/Tabs/index.stories.ts +61 -47
  56. package/app/components/ui/Tag/index.stories.ts +45 -3
  57. package/app/components/ui/Textarea/index.stories.ts +61 -15
  58. package/app/components/ui/Toast/index.stories.ts +77 -3
  59. package/app/components/ui/Tooltip/index.stories.ts +60 -2
  60. package/app/components/ui/WebLink/index.stories.ts +53 -15
  61. package/package.json +2 -2
@@ -27,7 +27,22 @@ const noControls = { controls: { disable: true }} satisfies Story['parameters']
27
27
  export const Default: Story = {}
28
28
 
29
29
  export const VariousSizes: Story = {
30
- parameters: noControls,
30
+ parameters: {
31
+ ...noControls,
32
+ docs: {
33
+ source: {
34
+ code: `
35
+ <template>
36
+ <div class="space-y-3">
37
+ <Skeleton width="100%" height="12px" />
38
+ <Skeleton width="80%" height="12px" />
39
+ <Skeleton width="60%" height="12px" />
40
+ </div>
41
+ </template>
42
+ `.trim(),
43
+ },
44
+ },
45
+ },
31
46
  render: () => ({
32
47
  components: { Skeleton },
33
48
  template: `
@@ -41,7 +56,24 @@ export const VariousSizes: Story = {
41
56
  }
42
57
 
43
58
  export const CardSkeleton: Story = {
44
- parameters: noControls,
59
+ parameters: {
60
+ ...noControls,
61
+ docs: {
62
+ source: {
63
+ code: `
64
+ <template>
65
+ <div class="flex items-center gap-4">
66
+ <Skeleton width="48px" height="48px" class="rounded-full" />
67
+ <div class="space-y-2">
68
+ <Skeleton width="160px" height="16px" />
69
+ <Skeleton width="120px" height="12px" />
70
+ </div>
71
+ </div>
72
+ </template>
73
+ `.trim(),
74
+ },
75
+ },
76
+ },
45
77
  render: () => ({
46
78
  components: { Skeleton },
47
79
  template: `
@@ -1,4 +1,5 @@
1
1
  import type { Meta, StoryObj } from '@storybook/vue3'
2
+ import EventLog from '#storybook/EventLog.vue'
2
3
  import Slider from './index.vue'
3
4
 
4
5
  const meta = {
@@ -41,7 +42,18 @@ const noControls = { controls: { disable: true }} satisfies Story['parameters']
41
42
  export const Default: Story = {}
42
43
 
43
44
  export const Range: Story = {
44
- parameters: noControls,
45
+ parameters: {
46
+ ...noControls,
47
+ docs: {
48
+ source: {
49
+ code: `
50
+ <template>
51
+ <Slider v-model="range" />
52
+ </template>
53
+ `.trim(),
54
+ },
55
+ },
56
+ },
45
57
  render: () => ({
46
58
  components: { Slider },
47
59
  setup () {
@@ -58,7 +70,18 @@ export const Range: Story = {
58
70
  }
59
71
 
60
72
  export const WithStep: Story = {
61
- parameters: noControls,
73
+ parameters: {
74
+ ...noControls,
75
+ docs: {
76
+ source: {
77
+ code: `
78
+ <template>
79
+ <Slider v-model="value" :step="25" />
80
+ </template>
81
+ `.trim(),
82
+ },
83
+ },
84
+ },
62
85
  render: () => ({
63
86
  components: { Slider },
64
87
  setup () {
@@ -75,7 +98,18 @@ export const WithStep: Story = {
75
98
  }
76
99
 
77
100
  export const CustomMinMax: Story = {
78
- parameters: noControls,
101
+ parameters: {
102
+ ...noControls,
103
+ docs: {
104
+ source: {
105
+ code: `
106
+ <template>
107
+ <Slider v-model="value" :min="0" :max="1000" />
108
+ </template>
109
+ `.trim(),
110
+ },
111
+ },
112
+ },
79
113
  render: () => ({
80
114
  components: { Slider },
81
115
  setup () {
@@ -92,7 +126,18 @@ export const CustomMinMax: Story = {
92
126
  }
93
127
 
94
128
  export const Disabled: Story = {
95
- parameters: noControls,
129
+ parameters: {
130
+ ...noControls,
131
+ docs: {
132
+ source: {
133
+ code: `
134
+ <template>
135
+ <Slider v-model="value" disabled />
136
+ </template>
137
+ `.trim(),
138
+ },
139
+ },
140
+ },
96
141
  render: () => ({
97
142
  components: { Slider },
98
143
  setup () {
@@ -106,3 +151,21 @@ export const Disabled: Story = {
106
151
  `,
107
152
  }),
108
153
  }
154
+
155
+ export const EventHandling: Story = {
156
+ parameters: noControls,
157
+ render: () => ({
158
+ components: { Slider, EventLog },
159
+ setup: () => ({ value: ref(50) }),
160
+ template: `
161
+ <EventLog v-slot="{ record }">
162
+ <div class="max-w-sm">
163
+ <Slider
164
+ v-model="value"
165
+ @update:modelValue="(v) => record('update:modelValue', v)"
166
+ />
167
+ </div>
168
+ </EventLog>
169
+ `,
170
+ }),
171
+ }
@@ -11,10 +11,14 @@ const meta = {
11
11
  argTypes: {
12
12
  color: { control: 'select', options: colors },
13
13
  variant: { control: 'select', options: variants },
14
+ active: { control: 'boolean' },
15
+ selectable: { control: 'boolean' },
14
16
  },
15
17
  args: {
16
18
  color: 'default',
17
19
  variant: 'soft',
20
+ active: false,
21
+ selectable: false,
18
22
  },
19
23
  render: args => ({
20
24
  components: { Surface },
@@ -31,7 +35,22 @@ const noControls = { controls: { disable: true }} satisfies Story['parameters']
31
35
  export const Default: Story = {}
32
36
 
33
37
  export const Colors: Story = {
34
- parameters: noControls,
38
+ parameters: {
39
+ ...noControls,
40
+ docs: {
41
+ source: {
42
+ code: `
43
+ <template>
44
+ <div class="grid grid-cols-2 gap-3 md:grid-cols-3">
45
+ <Surface v-for="c in colors" :key="c" :color="c" class="p-4">
46
+ <strong>{{ c }}</strong> surface
47
+ </Surface>
48
+ </div>
49
+ </template>
50
+ `.trim(),
51
+ },
52
+ },
53
+ },
35
54
  render: () => ({
36
55
  components: { Surface },
37
56
  setup: () => ({ colors }),
@@ -46,7 +65,22 @@ export const Colors: Story = {
46
65
  }
47
66
 
48
67
  export const Variants: Story = {
49
- parameters: noControls,
68
+ parameters: {
69
+ ...noControls,
70
+ docs: {
71
+ source: {
72
+ code: `
73
+ <template>
74
+ <div class="grid grid-cols-2 gap-3 md:grid-cols-4">
75
+ <Surface v-for="v in variants" :key="v" :variant="v" class="p-4">
76
+ <strong>{{ v }}</strong> surface
77
+ </Surface>
78
+ </div>
79
+ </template>
80
+ `.trim(),
81
+ },
82
+ },
83
+ },
50
84
  render: () => ({
51
85
  components: { Surface },
52
86
  setup: () => ({ variants }),
@@ -61,16 +95,63 @@ export const Variants: Story = {
61
95
  }
62
96
 
63
97
  export const VariantColorMatrix: Story = {
64
- parameters: noControls,
98
+ parameters: {
99
+ ...noControls,
100
+ docs: {
101
+ source: {
102
+ code: `
103
+ <template>
104
+ <div class="space-y-6">
105
+ <div v-for="v in variants" :key="v">
106
+ <div class="mb-2 text-sm text-muted-foreground">{{ v }}</div>
107
+ <div class="grid grid-cols-2 gap-3 md:grid-cols-3">
108
+ <Surface
109
+ v-for="c in colors"
110
+ :key="c"
111
+ :variant="v"
112
+ :color="c"
113
+ selectable
114
+ :active="selected === keyFor(v, c)"
115
+ class="p-4"
116
+ @click="selected = keyFor(v, c)"
117
+ >
118
+ <strong>{{ c }}</strong> surface
119
+ </Surface>
120
+ </div>
121
+ </div>
122
+ </div>
123
+ </template>
124
+
125
+ <script setup lang="ts">
126
+ const selected = ref('')
127
+ const keyFor = (v: string, c: string) => \`\${v}:\${c}\`
128
+ </script>
129
+ `.trim(),
130
+ },
131
+ },
132
+ },
65
133
  render: () => ({
66
134
  components: { Surface },
67
- setup: () => ({ colors, variants }),
135
+ setup () {
136
+ const selected = ref('')
137
+ const keyFor = (v: string, c: string) => `${v}:${c}`
138
+ return { colors, variants, selected, keyFor }
139
+ },
68
140
  template: `
69
141
  <div class="space-y-6">
70
142
  <div v-for="v in variants" :key="v">
71
143
  <div class="mb-2 text-sm text-muted-foreground">{{ v }}</div>
72
144
  <div class="grid grid-cols-2 gap-3 md:grid-cols-3">
73
- <Surface v-for="c in colors" :key="c" :variant="v" :color="c" class="p-4">
145
+ <Surface
146
+ v-for="c in colors"
147
+ :key="c"
148
+ :variant="v"
149
+ :color="c"
150
+ selectable
151
+ :active="selected === keyFor(v, c)"
152
+ class="p-4"
153
+ @click="selected = keyFor(v, c)"
154
+ >
74
155
  <strong>{{ c }}</strong> surface
75
156
  </Surface>
76
157
  </div>
@@ -21,11 +21,19 @@ const surfaceVariants = cva(
21
21
  warn: '',
22
22
  danger: '',
23
23
  },
24
+ active: {
25
+ true: 'ring-[3px]',
26
+ false: '',
27
+ },
28
+ selectable: {
29
+ true: 'cursor-pointer transition-colors',
30
+ false: '',
31
+ },
24
32
  },
25
33
  compoundVariants: [
26
34
  // solid — full color background
27
35
  { variant: 'solid', color: 'default', class: `
28
- border-transparent bg-accent text-accent-foreground
36
+ bg-accent text-accent-foreground border-transparent
29
37
  ` },
30
38
  { variant: 'solid', color: 'primary', class: `
31
39
  border-primary bg-primary text-primary-foreground
@@ -93,10 +101,105 @@ const surfaceVariants = cva(
93
101
  { variant: 'flat', color: 'help', class: 'bg-help/10 text-help' },
94
102
  { variant: 'flat', color: 'warn', class: 'bg-warn/10 text-warn' },
95
103
  { variant: 'flat', color: 'danger', class: 'bg-danger/10 text-danger' },
104
+ // active — color-matched border + soft ring (mirrors Input focus)
105
+ { active: true, color: 'default', class: 'border-ring ring-ring/50' },
106
+ { active: true, color: 'primary', class: 'border-primary ring-primary/50' },
107
+ { active: true, color: 'success', class: 'border-success ring-success/50' },
108
+ { active: true, color: 'info', class: 'border-info ring-info/50' },
109
+ { active: true, color: 'help', class: 'border-help ring-help/50' },
110
+ { active: true, color: 'warn', class: 'border-warn ring-warn/50' },
111
+ { active: true, color: 'danger', class: 'border-danger ring-danger/50' },
112
+ // selectable — hover bg, one step up the variant's intensity ladder
113
+ { selectable: true, variant: 'solid', color: 'default', class: `
114
+ hover:bg-accent/80
115
+ ` },
116
+ { selectable: true, variant: 'solid', color: 'primary', class: `
117
+ hover:bg-primary/90
118
+ ` },
119
+ { selectable: true, variant: 'solid', color: 'success', class: `
120
+ hover:bg-success/90
121
+ ` },
122
+ { selectable: true, variant: 'solid', color: 'info', class: `
123
+ hover:bg-info/90
124
+ ` },
125
+ { selectable: true, variant: 'solid', color: 'help', class: `
126
+ hover:bg-help/90
127
+ ` },
128
+ { selectable: true, variant: 'solid', color: 'warn', class: `
129
+ hover:bg-warn/90
130
+ ` },
131
+ { selectable: true, variant: 'solid', color: 'danger', class: `
132
+ hover:bg-danger/90
133
+ ` },
134
+ { selectable: true, variant: 'soft', color: 'default', class: `
135
+ hover:bg-secondary/70
136
+ ` },
137
+ { selectable: true, variant: 'soft', color: 'primary', class: `
138
+ hover:bg-primary/20
139
+ ` },
140
+ { selectable: true, variant: 'soft', color: 'success', class: `
141
+ hover:bg-success/20
142
+ ` },
143
+ { selectable: true, variant: 'soft', color: 'info', class: `
144
+ hover:bg-info/20
145
+ ` },
146
+ { selectable: true, variant: 'soft', color: 'help', class: `
147
+ hover:bg-help/20
148
+ ` },
149
+ { selectable: true, variant: 'soft', color: 'warn', class: `
150
+ hover:bg-warn/20
151
+ ` },
152
+ { selectable: true, variant: 'soft', color: 'danger', class: `
153
+ hover:bg-danger/20
154
+ ` },
155
+ { selectable: true, variant: 'bordered', color: 'default', class: `
156
+ hover:bg-accent/50
157
+ ` },
158
+ { selectable: true, variant: 'bordered', color: 'primary', class: `
159
+ hover:bg-primary/10
160
+ ` },
161
+ { selectable: true, variant: 'bordered', color: 'success', class: `
162
+ hover:bg-success/10
163
+ ` },
164
+ { selectable: true, variant: 'bordered', color: 'info', class: `
165
+ hover:bg-info/10
166
+ ` },
167
+ { selectable: true, variant: 'bordered', color: 'help', class: `
168
+ hover:bg-help/10
169
+ ` },
170
+ { selectable: true, variant: 'bordered', color: 'warn', class: `
171
+ hover:bg-warn/10
172
+ ` },
173
+ { selectable: true, variant: 'bordered', color: 'danger', class: `
174
+ hover:bg-danger/10
175
+ ` },
176
+ { selectable: true, variant: 'flat', color: 'default', class: `
177
+ hover:bg-secondary/70
178
+ ` },
179
+ { selectable: true, variant: 'flat', color: 'primary', class: `
180
+ hover:bg-primary/20
181
+ ` },
182
+ { selectable: true, variant: 'flat', color: 'success', class: `
183
+ hover:bg-success/20
184
+ ` },
185
+ { selectable: true, variant: 'flat', color: 'info', class: `
186
+ hover:bg-info/20
187
+ ` },
188
+ { selectable: true, variant: 'flat', color: 'help', class: `
189
+ hover:bg-help/20
190
+ ` },
191
+ { selectable: true, variant: 'flat', color: 'warn', class: `
192
+ hover:bg-warn/20
193
+ ` },
194
+ { selectable: true, variant: 'flat', color: 'danger', class: `
195
+ hover:bg-danger/20
196
+ ` },
96
197
  ],
97
198
  defaultVariants: {
98
199
  variant: 'soft',
99
200
  color: 'default',
201
+ active: false,
202
+ selectable: false,
100
203
  },
101
204
  },
102
205
  )
@@ -104,11 +207,21 @@ const surfaceVariants = cva(
104
207
  const props = withDefaults(defineProps<SurfaceProps>(), {
105
208
  color: 'default',
106
209
  variant: 'soft',
210
+ active: false,
211
+ selectable: false,
107
212
  class: undefined,
108
213
  })
109
214
 
110
215
  const mergedClass = computed(() =>
111
- cn(surfaceVariants({ color: props.color, variant: props.variant }), props.class),
216
+ cn(
217
+ surfaceVariants({
218
+ color: props.color,
219
+ variant: props.variant,
220
+ active: props.active,
221
+ selectable: props.selectable,
222
+ }),
223
+ props.class,
224
+ ),
112
225
  )
113
226
  </script>
114
227
 
@@ -4,5 +4,7 @@ export type SurfaceVariant = 'solid' | 'soft' | 'bordered' | 'flat'
4
4
  export interface SurfaceProps {
5
5
  color?: SurfaceColor
6
6
  variant?: SurfaceVariant
7
+ selectable?: boolean
8
+ active?: boolean
7
9
  class?: ClassValue
8
10
  }
@@ -1,4 +1,5 @@
1
1
  import type { Meta, StoryObj } from '@storybook/vue3'
2
+ import EventLog from '#storybook/EventLog.vue'
2
3
  import Switch from './index.vue'
3
4
 
4
5
  const meta = {
@@ -28,4 +29,49 @@ const meta = {
28
29
  export default meta
29
30
  type Story = StoryObj<typeof meta>
30
31
 
32
+ const noControls = { controls: { disable: true }} satisfies Story['parameters']
33
+
31
34
  export const Default: Story = {}
35
+
36
+ export const Disabled: Story = {
37
+ parameters: {
38
+ ...noControls,
39
+ docs: {
40
+ source: {
41
+ code: `
42
+ <template>
43
+ <div class="flex items-center gap-4">
44
+ <Switch :modelValue="false" disabled />
45
+ <Switch :modelValue="true" disabled />
46
+ </div>
47
+ </template>
48
+ `.trim(),
49
+ },
50
+ },
51
+ },
52
+ render: () => ({
53
+ components: { Switch },
54
+ template: `
55
+ <div class="flex items-center gap-4">
56
+ <Switch :modelValue="false" disabled />
57
+ <Switch :modelValue="true" disabled />
58
+ </div>
59
+ `,
60
+ }),
61
+ }
62
+
63
+ export const EventHandling: Story = {
64
+ parameters: noControls,
65
+ render: () => ({
66
+ components: { Switch, EventLog },
67
+ setup: () => ({ on: ref(false) }),
68
+ template: `
69
+ <EventLog v-slot="{ record }">
70
+ <Switch
71
+ v-model="on"
72
+ @update:modelValue="(v) => record('update:modelValue', v)"
73
+ />
74
+ </EventLog>
75
+ `,
76
+ }),
77
+ }
@@ -1,4 +1,5 @@
1
1
  import type { Meta, StoryObj } from '@storybook/vue3'
2
+ import EventLog from '#storybook/EventLog.vue'
2
3
  import Card from '../Card/index.vue'
3
4
  import type { TabsItem } from './types'
4
5
  import Tabs from './index.vue'
@@ -39,6 +40,8 @@ const meta = {
39
40
  defaultValue: { control: 'text' },
40
41
  rounded: { control: 'boolean' },
41
42
  iconOnly: { control: 'boolean' },
43
+ listClass: { control: 'text' },
44
+ triggerClass: { control: 'text' },
42
45
  },
43
46
  args: {
44
47
  items,
@@ -46,6 +49,8 @@ const meta = {
46
49
  defaultValue: 'account',
47
50
  rounded: false,
48
51
  iconOnly: false,
52
+ listClass: '',
53
+ triggerClass: '',
49
54
  },
50
55
  render: args => ({
51
56
  components: { Tabs },
@@ -63,68 +68,59 @@ export const Default: Story = {}
63
68
 
64
69
  export const IconOnly: Story = {
65
70
  parameters: noControls,
66
- render: () => ({
67
- components: { Tabs },
68
- setup: () => ({ items }),
69
- template: `
70
- <Tabs
71
- icon-only
72
- :items="items"
73
- default-value="account"
74
- class="max-w-md"
75
- />
76
- `,
77
- }),
71
+ args: {
72
+ iconOnly: true,
73
+ },
78
74
  }
79
75
 
80
76
  export const Rounded: Story = {
81
77
  parameters: noControls,
82
- render: () => ({
83
- components: { Tabs },
84
- setup: () => ({ items }),
85
- template: `
86
- <Tabs
87
- rounded
88
- :items="items"
89
- default-value="account"
90
- class="max-w-md"
91
- />
92
- `,
93
- }),
78
+ args: {
79
+ rounded: true,
80
+ },
94
81
  }
95
82
 
96
83
  export const DisabledItem: Story = {
97
84
  parameters: noControls,
98
- render: () => ({
99
- components: { Tabs },
100
- setup: () => ({ disabledItems }),
101
- template: `
102
- <Tabs
103
- :items="disabledItems"
104
- default-value="account"
105
- class="max-w-md"
106
- />
107
- `,
108
- }),
85
+ args: {
86
+ items: disabledItems,
87
+ },
109
88
  }
110
89
 
111
90
  export const NoContent: Story = {
112
91
  parameters: noControls,
113
- render: () => ({
114
- components: { Tabs },
115
- setup: () => ({ navItems }),
116
- template: `
117
- <Tabs
118
- :items="navItems"
119
- default-value="account"
120
- class="max-w-md"
121
- />
122
- `,
123
- }),
92
+ args: {
93
+ items: navItems,
94
+ },
124
95
  }
125
96
 
126
97
  export const CustomSlots: Story = {
127
- parameters: noControls,
98
+ parameters: {
99
+ ...noControls,
100
+ docs: {
101
+ source: {
102
+ code: `
103
+ <template>
104
+ <Tabs
105
+ :items="items"
106
+ default-value="account"
107
+ list-class="w-full"
108
+ class="max-w-md"
109
+ >
110
+ <template #title="{ item, active }">
111
+ <span :class="active ? 'font-semibold' : ''">{{ item.title }}</span>
112
+ </template>
113
+ <template #content="{ item }">
114
+ <Card>
115
+ <p class="text-sm text-muted-foreground">{{ item.content }}</p>
116
+ </Card>
117
+ </template>
118
+ </Tabs>
119
+ </template>
120
+ `.trim(),
121
+ },
122
+ },
123
+ },
128
124
  render: () => ({
129
125
  components: { Tabs, Card },
130
126
  setup: () => ({ items }),
@@ -147,3 +143,21 @@ export const CustomSlots: Story = {
147
143
  `,
148
144
  }),
149
145
  }
146
+
147
+ export const EventHandling: Story = {
148
+ parameters: noControls,
149
+ render: () => ({
150
+ components: { Tabs, EventLog },
151
+ setup: () => ({ items, value: ref('account') }),
152
+ template: `
153
+ <EventLog v-slot="{ record }">
154
+ <Tabs
155
+ v-model="value"
156
+ :items="items"
157
+ class="max-w-md"
158
+ @update:modelValue="(v) => record('update:modelValue', v)"
159
+ />
160
+ </EventLog>
161
+ `,
162
+ }),
163
+ }