@polymarbot/nuxt-layer-shadcn-ui 0.3.10 → 0.4.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 (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
@@ -7,6 +7,7 @@ import {
7
7
  DialogFooter,
8
8
  DialogHeader,
9
9
  DialogTitle,
10
+ DialogTrigger,
10
11
  } from '../../shadcn/dialog'
11
12
  import type { ModalProps } from './types'
12
13
 
@@ -42,28 +43,32 @@ const resolvedCancelText = computed(
42
43
  () => props.cancelText || t('common.actions.cancel'),
43
44
  )
44
45
 
45
- const dialogOpen = computed({
46
- get: () => props.visible ?? false,
47
- set: (value: boolean) => {
48
- if (!value && props.visible && !props.loading) {
49
- onCancel()
50
- }
51
- },
46
+ const dialogOpen = ref(props.visible ?? false)
47
+
48
+ watch(() => props.visible, value => {
49
+ if (value !== undefined) dialogOpen.value = value
52
50
  })
53
51
 
54
- watch(() => props.visible, visible => {
55
- if (visible) emit('open')
52
+ watch(dialogOpen, value => {
53
+ emit('update:visible', value)
54
+ if (value) emit('open')
56
55
  else emit('close')
57
56
  })
58
57
 
58
+ function onOpenUpdate (value: boolean) {
59
+ if (!value && props.loading) return
60
+ if (value) dialogOpen.value = true
61
+ else onCancel()
62
+ }
63
+
59
64
  function onConfirm () {
60
65
  emit('confirm')
61
- emit('update:visible', false)
66
+ dialogOpen.value = false
62
67
  }
63
68
 
64
69
  function onCancel () {
65
70
  emit('cancel')
66
- emit('update:visible', false)
71
+ dialogOpen.value = false
67
72
  }
68
73
 
69
74
  function onPointerDownOutside (event: Event) {
@@ -80,7 +85,17 @@ const contentClass = computed(() =>
80
85
  </script>
81
86
 
82
87
  <template>
83
- <Dialog v-model:open="dialogOpen">
88
+ <Dialog
89
+ :open="dialogOpen"
90
+ @update:open="onOpenUpdate"
91
+ >
92
+ <DialogTrigger
93
+ v-if="$slots.trigger"
94
+ asChild
95
+ >
96
+ <slot name="trigger" />
97
+ </DialogTrigger>
98
+
84
99
  <DialogContent
85
100
  :class="contentClass"
86
101
  :showCloseButton="false"
@@ -36,10 +36,26 @@ const noControls = { controls: { disable: true }} satisfies Story['parameters']
36
36
  export const Default: Story = {}
37
37
 
38
38
  export const Types: Story = {
39
- parameters: noControls,
39
+ parameters: {
40
+ ...noControls,
41
+ docs: {
42
+ source: {
43
+ code: `
44
+ <template>
45
+ <ModalContent type="default" content="This is a default message." />
46
+ <ModalContent type="success" content="Operation completed successfully." />
47
+ <ModalContent type="info" content="Your changes have been saved." />
48
+ <ModalContent type="help" content="Need help? Check the documentation." />
49
+ <ModalContent type="warn" content="This operation will affect all users." />
50
+ <ModalContent type="danger" content="Are you sure you want to delete this item? This action cannot be undone." />
51
+ <ModalContent type="error" content="An error occurred while processing your request." />
52
+ </template>
53
+ `.trim(),
54
+ },
55
+ },
56
+ },
40
57
  render: () => ({
41
58
  components: { ModalContent },
42
- setup: () => ({ types }),
43
59
  template: `
44
60
  <div class="space-y-4 max-w-md">
45
61
  <ModalContent type="default" content="This is a default message." />
@@ -55,7 +71,19 @@ export const Types: Story = {
55
71
  }
56
72
 
57
73
  export const WithCustomIcon: Story = {
58
- parameters: noControls,
74
+ parameters: {
75
+ ...noControls,
76
+ docs: {
77
+ source: {
78
+ code: `
79
+ <template>
80
+ <ModalContent icon="shield-alert" content="Your session is about to expire." />
81
+ <ModalContent type="warn" icon="shield-alert" content="Security warning: unusual login detected." />
82
+ </template>
83
+ `.trim(),
84
+ },
85
+ },
86
+ },
59
87
  render: () => ({
60
88
  components: { ModalContent },
61
89
  template: `
@@ -69,12 +97,8 @@ export const WithCustomIcon: Story = {
69
97
 
70
98
  export const MultilineText: Story = {
71
99
  parameters: noControls,
72
- render: () => ({
73
- components: { ModalContent },
74
- template: `
75
- <div class="max-w-md">
76
- <ModalContent type="warn" content="Warning: This operation will affect all users.\nPlease review the changes before proceeding." />
77
- </div>
78
- `,
79
- }),
100
+ args: {
101
+ type: 'warn',
102
+ content: 'Warning: This operation will affect all users.\nPlease review the changes before proceeding.',
103
+ },
80
104
  }
@@ -42,34 +42,34 @@ export const Default: Story = {}
42
42
 
43
43
  export const NoTitle: Story = {
44
44
  parameters: noControls,
45
- render: () => ({
46
- components: { PageCard },
47
- template: `
48
- <PageCard class="max-w-2xl">
49
- <p>A page card without a title — just content.</p>
50
- </PageCard>
51
- `,
52
- }),
45
+ args: {
46
+ title: '',
47
+ },
53
48
  }
54
49
 
55
50
  export const WithSubtitle: Story = {
56
51
  parameters: noControls,
57
- render: () => ({
58
- components: { PageCard },
59
- template: `
60
- <PageCard
61
- title="Bot Details"
62
- subtitle="View and edit your bot configuration."
63
- class="max-w-2xl"
64
- >
65
- <p>Title combined with subtitle.</p>
66
- </PageCard>
67
- `,
68
- }),
52
+ args: {
53
+ title: 'Bot Details',
54
+ subtitle: 'View and edit your bot configuration.',
55
+ },
69
56
  }
70
57
 
71
58
  export const WithBackButton: Story = {
72
- parameters: noControls,
59
+ parameters: {
60
+ ...noControls,
61
+ docs: {
62
+ source: {
63
+ code: `
64
+ <template>
65
+ <PageCard title="Edit Profile" :back="{ action: () => {} }" class="max-w-2xl">
66
+ <p>A page card with a back button in the header.</p>
67
+ </PageCard>
68
+ </template>
69
+ `.trim(),
70
+ },
71
+ },
72
+ },
73
73
  render: () => ({
74
74
  components: { PageCard },
75
75
  template: `
@@ -81,7 +81,25 @@ export const WithBackButton: Story = {
81
81
  }
82
82
 
83
83
  export const BackWithSubtitle: Story = {
84
- parameters: noControls,
84
+ parameters: {
85
+ ...noControls,
86
+ docs: {
87
+ source: {
88
+ code: `
89
+ <template>
90
+ <PageCard
91
+ title="Bot Details"
92
+ subtitle="View and edit your bot configuration."
93
+ :back="{ action: () => {} }"
94
+ class="max-w-2xl"
95
+ >
96
+ <p>Back button combined with title and subtitle.</p>
97
+ </PageCard>
98
+ </template>
99
+ `.trim(),
100
+ },
101
+ },
102
+ },
85
103
  render: () => ({
86
104
  components: { PageCard },
87
105
  template: `
@@ -98,7 +116,24 @@ export const BackWithSubtitle: Story = {
98
116
  }
99
117
 
100
118
  export const WithActions: Story = {
101
- parameters: noControls,
119
+ parameters: {
120
+ ...noControls,
121
+ docs: {
122
+ source: {
123
+ code: `
124
+ <template>
125
+ <PageCard title="API Keys" class="max-w-2xl">
126
+ <template #actions>
127
+ <Button variant="outline" size="sm">Export</Button>
128
+ <Button size="sm">Create</Button>
129
+ </template>
130
+ <p>Action buttons rendered on the right side of the title.</p>
131
+ </PageCard>
132
+ </template>
133
+ `.trim(),
134
+ },
135
+ },
136
+ },
102
137
  render: () => ({
103
138
  components: { PageCard, Button },
104
139
  template: `
@@ -114,7 +149,29 @@ export const WithActions: Story = {
114
149
  }
115
150
 
116
151
  export const ActionsSubtitleBack: Story = {
117
- parameters: noControls,
152
+ parameters: {
153
+ ...noControls,
154
+ docs: {
155
+ source: {
156
+ code: `
157
+ <template>
158
+ <PageCard
159
+ title="Developer Settings"
160
+ subtitle="Manage API keys and webhooks for your organization."
161
+ :back="{ action: () => {} }"
162
+ class="max-w-2xl"
163
+ >
164
+ <template #actions>
165
+ <WebLink href="#" target="_blank" class="text-sm">Docs</WebLink>
166
+ <WebLink href="#" target="_blank" class="text-sm">API Reference</WebLink>
167
+ </template>
168
+ <p>Back button, title, subtitle, and trailing action slot working together.</p>
169
+ </PageCard>
170
+ </template>
171
+ `.trim(),
172
+ },
173
+ },
174
+ },
118
175
  render: () => ({
119
176
  components: { PageCard, WebLink },
120
177
  template: `
@@ -135,7 +192,29 @@ export const ActionsSubtitleBack: Story = {
135
192
  }
136
193
 
137
194
  export const CustomTitleSlot: Story = {
138
- parameters: noControls,
195
+ parameters: {
196
+ ...noControls,
197
+ docs: {
198
+ source: {
199
+ code: `
200
+ <template>
201
+ <PageCard class="max-w-2xl">
202
+ <template #title>
203
+ <span class="flex items-center gap-2">
204
+ <span class="inline-block size-2 rounded-full bg-success" />
205
+ <span>Active Workspace</span>
206
+ </span>
207
+ </template>
208
+ <template #subtitle>
209
+ <span class="text-success">All systems operational</span>
210
+ </template>
211
+ <p>Title and subtitle rendered via slots.</p>
212
+ </PageCard>
213
+ </template>
214
+ `.trim(),
215
+ },
216
+ },
217
+ },
139
218
  render: () => ({
140
219
  components: { PageCard },
141
220
  template: `
@@ -156,7 +235,26 @@ export const CustomTitleSlot: Story = {
156
235
  }
157
236
 
158
237
  export const WithFooter: Story = {
159
- parameters: noControls,
238
+ parameters: {
239
+ ...noControls,
240
+ docs: {
241
+ source: {
242
+ code: `
243
+ <template>
244
+ <PageCard title="Profile" class="max-w-2xl">
245
+ <p>Edit your profile information and save the changes.</p>
246
+ <template #footer>
247
+ <div class="flex w-full justify-end gap-2">
248
+ <Button variant="outline">Cancel</Button>
249
+ <Button>Save</Button>
250
+ </div>
251
+ </template>
252
+ </PageCard>
253
+ </template>
254
+ `.trim(),
255
+ },
256
+ },
257
+ },
160
258
  render: () => ({
161
259
  components: { PageCard, Button },
162
260
  template: `
@@ -175,47 +273,47 @@ export const WithFooter: Story = {
175
273
 
176
274
  export const CardVariant: Story = {
177
275
  parameters: noControls,
178
- render: () => ({
179
- components: { PageCard },
180
- template: `
181
- <PageCard
182
- title="Profile"
183
- subtitle="Rounded corners and a visible border."
184
- variant="card"
185
- class="max-w-2xl"
186
- >
187
- <p>Use variant="card" for widget-style panels; default "paper" is edge-to-edge.</p>
188
- </PageCard>
189
- `,
190
- }),
276
+ args: {
277
+ title: 'Profile',
278
+ subtitle: 'Rounded corners and a visible border.',
279
+ variant: 'card',
280
+ },
191
281
  }
192
282
 
193
283
  export const Loading: Story = {
194
284
  parameters: noControls,
195
- render: () => ({
196
- components: { PageCard },
197
- template: `
198
- <PageCard title="Saving…" loading class="max-w-2xl">
199
- <p>Content is covered by a centered loading overlay while <code>loading</code> is true.</p>
200
- </PageCard>
201
- `,
202
- }),
285
+ args: {
286
+ title: 'Saving…',
287
+ loading: true,
288
+ },
203
289
  }
204
290
 
205
291
  export const NotReady: Story = {
206
292
  parameters: noControls,
207
- render: () => ({
208
- components: { PageCard },
209
- template: `
210
- <PageCard :ready="false" class="max-w-2xl">
211
- <p>This content would be replaced by skeleton placeholders while data is loading.</p>
212
- </PageCard>
213
- `,
214
- }),
293
+ args: {
294
+ title: '',
295
+ ready: false,
296
+ },
215
297
  }
216
298
 
217
299
  export const Disabled: Story = {
218
- parameters: noControls,
300
+ parameters: {
301
+ ...noControls,
302
+ docs: {
303
+ source: {
304
+ code: `
305
+ <template>
306
+ <PageCard title="Read-only" disabled class="max-w-2xl">
307
+ <div class="flex flex-col gap-3">
308
+ <p>When <code>disabled</code> is true, content becomes non-interactive and dimmed.</p>
309
+ <Button>Disabled action</Button>
310
+ </div>
311
+ </PageCard>
312
+ </template>
313
+ `.trim(),
314
+ },
315
+ },
316
+ },
219
317
  render: () => ({
220
318
  components: { PageCard, Button },
221
319
  template: `
@@ -1,4 +1,5 @@
1
1
  import type { Meta, StoryObj } from '@storybook/vue3'
2
+ import EventLog from '#storybook/EventLog.vue'
2
3
  import Pagination from './index.vue'
3
4
 
4
5
  const sizes = [ 'default', 'sm' ] as const
@@ -39,18 +40,27 @@ const noControls = { controls: { disable: true }} satisfies Story['parameters']
39
40
  export const Default: Story = {}
40
41
 
41
42
  export const Sizes: Story = {
42
- parameters: noControls,
43
+ parameters: {
44
+ ...noControls,
45
+ docs: {
46
+ source: {
47
+ code: `
48
+ <template>
49
+ <Pagination :page="3" :total="85" :pageSize="10" size="default" />
50
+ <Pagination :page="3" :total="85" :pageSize="10" size="sm" />
51
+ </template>
52
+ `.trim(),
53
+ },
54
+ },
55
+ },
43
56
  render: () => ({
44
57
  components: { Pagination },
58
+ setup: () => ({ sizes }),
45
59
  template: `
46
- <div class="space-y-4">
47
- <div>
48
- <span class="mb-2 block text-sm font-medium">default</span>
49
- <Pagination :page="3" :total="85" :pageSize="10" />
50
- </div>
51
- <div>
52
- <span class="mb-2 block text-sm font-medium">sm</span>
53
- <Pagination :page="3" :total="85" :pageSize="10" size="sm" />
60
+ <div class="space-y-3">
61
+ <div v-for="s in sizes" :key="s" class="flex flex-wrap items-center gap-3">
62
+ <span class="w-16 text-sm text-muted-foreground">{{ s }}</span>
63
+ <Pagination :page="3" :total="85" :pageSize="10" :size="s" />
54
64
  </div>
55
65
  </div>
56
66
  `,
@@ -58,20 +68,71 @@ export const Sizes: Story = {
58
68
  }
59
69
 
60
70
  export const Simple: Story = {
61
- parameters: noControls,
71
+ parameters: {
72
+ ...noControls,
73
+ docs: {
74
+ source: {
75
+ code: `
76
+ <template>
77
+ <Pagination :page="3" :total="85" :pageSize="10" simple size="default" />
78
+ <Pagination :page="3" :total="85" :pageSize="10" simple size="sm" />
79
+ </template>
80
+ `.trim(),
81
+ },
82
+ },
83
+ },
62
84
  render: () => ({
63
85
  components: { Pagination },
86
+ setup: () => ({ sizes }),
64
87
  template: `
65
- <div class="space-y-4">
66
- <div>
67
- <span class="mb-2 block text-sm font-medium">default</span>
68
- <Pagination :page="3" :total="85" :pageSize="10" simple />
69
- </div>
70
- <div>
71
- <span class="mb-2 block text-sm font-medium">sm</span>
72
- <Pagination :page="3" :total="85" :pageSize="10" simple size="sm" />
88
+ <div class="space-y-3">
89
+ <div v-for="s in sizes" :key="s" class="flex flex-wrap items-center gap-3">
90
+ <span class="w-16 text-sm text-muted-foreground">{{ s }}</span>
91
+ <Pagination :page="3" :total="85" :pageSize="10" simple :size="s" />
73
92
  </div>
74
93
  </div>
75
94
  `,
76
95
  }),
77
96
  }
97
+
98
+ export const EventHandling: Story = {
99
+ parameters: {
100
+ ...noControls,
101
+ docs: {
102
+ source: {
103
+ code: `
104
+ <template>
105
+ <Pagination
106
+ v-model:page="page"
107
+ v-model:pageSize="pageSize"
108
+ :total="85"
109
+ :pageSizeOptions="[10, 20, 50]"
110
+ @update:page="onPageUpdate"
111
+ @update:pageSize="onPageSizeUpdate"
112
+ />
113
+ </template>
114
+ `.trim(),
115
+ },
116
+ },
117
+ },
118
+ render: () => ({
119
+ components: { Pagination, EventLog },
120
+ setup () {
121
+ const page = ref(1)
122
+ const pageSize = ref(10)
123
+ return { page, pageSize }
124
+ },
125
+ template: `
126
+ <EventLog v-slot="{ record }">
127
+ <Pagination
128
+ v-model:page="page"
129
+ v-model:pageSize="pageSize"
130
+ :total="85"
131
+ :pageSizeOptions="[10, 20, 50]"
132
+ @update:page="(v) => record('update:page', v)"
133
+ @update:pageSize="(v) => record('update:pageSize', v)"
134
+ />
135
+ </EventLog>
136
+ `,
137
+ }),
138
+ }
@@ -125,7 +125,10 @@ const pageSizeMenuItems = computed<DropdownItem[]>(() =>
125
125
  :page="page"
126
126
  :siblingCount="siblingCount"
127
127
  showEdges
128
- class="mx-0 w-auto"
128
+ class="
129
+ mx-0 w-auto
130
+ [&_button]:cursor-pointer
131
+ "
129
132
  @update:page="emit('update:page', $event)"
130
133
  >
131
134
  <PaginationContent v-slot="{ items }">
@@ -6,10 +6,23 @@ import Popover from './index.vue'
6
6
  const meta = {
7
7
  title: 'UI/Popover',
8
8
  component: Popover,
9
- render: () => ({
9
+ argTypes: {
10
+ trigger: { control: 'inline-radio', options: [ 'click', 'hover' ]},
11
+ side: { control: 'select', options: [ 'top', 'bottom', 'left', 'right' ]},
12
+ align: { control: 'select', options: [ 'start', 'center', 'end' ]},
13
+ sideOffset: { control: 'number' },
14
+ },
15
+ args: {
16
+ trigger: 'click',
17
+ side: undefined,
18
+ align: undefined,
19
+ sideOffset: undefined,
20
+ },
21
+ render: args => ({
10
22
  components: { Popover, Button },
23
+ setup: () => ({ args }),
11
24
  template: `
12
- <Popover>
25
+ <Popover v-bind="args">
13
26
  <template #trigger>
14
27
  <Button variant="outline">Open Popover</Button>
15
28
  </template>
@@ -29,8 +42,65 @@ const noControls = { controls: { disable: true }} satisfies Story['parameters']
29
42
 
30
43
  export const Default: Story = {}
31
44
 
45
+ export const HoverTrigger: Story = {
46
+ parameters: {
47
+ ...noControls,
48
+ docs: {
49
+ source: {
50
+ code: `
51
+ <template>
52
+ <Popover trigger="hover">
53
+ <template #trigger>
54
+ <Button variant="outline">Hover me</Button>
55
+ </template>
56
+ <div class="space-y-2">
57
+ <h4 class="font-medium">Hovering opens it</h4>
58
+ <p class="text-sm text-muted-foreground">Move the cursor away to close.</p>
59
+ </div>
60
+ </Popover>
61
+ </template>
62
+ `.trim(),
63
+ },
64
+ },
65
+ },
66
+ render: () => ({
67
+ components: { Popover, Button },
68
+ template: `
69
+ <Popover trigger="hover">
70
+ <template #trigger>
71
+ <Button variant="outline">Hover me</Button>
72
+ </template>
73
+ <div class="space-y-2">
74
+ <h4 class="font-medium">Hovering opens it</h4>
75
+ <p class="text-sm text-muted-foreground">Move the cursor away to close.</p>
76
+ </div>
77
+ </Popover>
78
+ `,
79
+ }),
80
+ }
81
+
32
82
  export const WithForm: Story = {
33
- parameters: noControls,
83
+ parameters: {
84
+ ...noControls,
85
+ docs: {
86
+ source: {
87
+ code: `
88
+ <template>
89
+ <Popover>
90
+ <template #trigger>
91
+ <Button variant="outline">Edit Name</Button>
92
+ </template>
93
+ <div class="space-y-3">
94
+ <h4 class="font-medium">Update Name</h4>
95
+ <Input placeholder="Enter new name" />
96
+ <Button size="sm" class="w-full">Save</Button>
97
+ </div>
98
+ </Popover>
99
+ </template>
100
+ `.trim(),
101
+ },
102
+ },
103
+ },
34
104
  render: () => ({
35
105
  components: { Popover, Button, Input },
36
106
  template: `