@polymarbot/nuxt-layer-shadcn-ui 0.1.9 → 0.2.0-w
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/app/assets/styles/colors.css +10 -10
- package/app/assets/styles/globals.css +1 -0
- package/app/assets/styles/z-index.css +27 -0
- package/app/components/ui/Accordion/index.stories.ts +60 -56
- package/app/components/ui/Accordion/index.vue +1 -1
- package/app/components/ui/AdminLayout/SidebarMenus.vue +0 -2
- package/app/components/ui/AdminLayout/index.stories.ts +9 -8
- package/app/components/ui/Alert/index.stories.ts +28 -26
- package/app/components/ui/Alert/index.vue +6 -6
- package/app/components/ui/Alert/types.ts +2 -1
- package/app/components/ui/AlertDialog/index.stories.ts +85 -50
- package/app/components/ui/AsyncDataTable/index.stories.ts +53 -36
- package/app/components/ui/Avatar/index.stories.ts +56 -51
- package/app/components/ui/Avatar/index.vue +1 -1
- package/app/components/ui/Avatar/types.ts +5 -2
- package/app/components/ui/Badge/index.stories.ts +41 -41
- package/app/components/ui/Badge/index.vue +1 -1
- package/app/components/ui/Badge/types.ts +3 -1
- package/app/components/ui/Breadcrumb/index.stories.ts +48 -37
- package/app/components/ui/Breadcrumb/index.vue +1 -1
- package/app/components/ui/Button/index.stories.ts +94 -90
- package/app/components/ui/Button/index.vue +1 -1
- package/app/components/ui/Button/types.ts +4 -1
- package/app/components/ui/ButtonGroup/index.stories.ts +61 -49
- package/app/components/ui/Card/index.stories.ts +55 -47
- package/app/components/ui/Card/index.vue +1 -1
- package/app/components/ui/Checkbox/index.stories.ts +69 -46
- package/app/components/ui/Checkbox/index.vue +1 -1
- package/app/components/ui/CopyButton/index.stories.ts +89 -31
- package/app/components/ui/DataTable/index.stories.ts +218 -168
- package/app/components/ui/DataTable/index.vue +1 -1
- package/app/components/ui/DatePicker/index.stories.ts +131 -37
- package/app/components/ui/DateRangePicker/index.stories.ts +107 -33
- package/app/components/ui/Divider/index.stories.ts +46 -24
- package/app/components/ui/Divider/index.vue +1 -1
- package/app/components/ui/Drawer/index.stories.ts +131 -81
- package/app/components/ui/Drawer/index.vue +1 -7
- package/app/components/ui/Drawer/types.ts +1 -1
- package/app/components/ui/Dropdown/index.stories.ts +134 -89
- package/app/components/ui/Dropdown/index.vue +5 -1
- package/app/components/ui/Dropdown/types.ts +1 -1
- package/app/components/ui/FormItem/index.stories.ts +87 -43
- package/app/components/ui/FormItem/index.vue +1 -1
- package/app/components/ui/Help/index.stories.ts +46 -35
- package/app/components/ui/Icon/index.stories.ts +41 -43
- package/app/components/ui/Input/index.stories.ts +95 -41
- package/app/components/ui/Input/index.vue +1 -1
- package/app/components/ui/InputCurrency/index.stories.ts +89 -49
- package/app/components/ui/InputNumber/index.stories.ts +93 -29
- package/app/components/ui/InputNumber/index.vue +1 -1
- package/app/components/ui/InputOtp/index.stories.ts +6 -7
- package/app/components/ui/InputOtp/index.vue +1 -1
- package/app/components/ui/InputPercent/index.stories.ts +6 -7
- package/app/components/ui/InputRange/index.stories.ts +6 -7
- package/app/components/ui/Loading/index.stories.ts +19 -19
- package/app/components/ui/Markdown/index.stories.ts +7 -10
- package/app/components/ui/Modal/index.stories.ts +135 -80
- package/app/components/ui/Modal/index.vue +1 -6
- package/app/components/ui/Modal/types.ts +1 -1
- package/app/components/ui/ModalContent/index.stories.ts +54 -26
- package/app/components/ui/ModalContent/index.vue +2 -2
- package/app/components/ui/PageCard/index.stories.ts +177 -67
- package/app/components/ui/Pagination/index.stories.ts +68 -51
- package/app/components/ui/Pagination/index.vue +2 -2
- package/app/components/ui/Popover/index.stories.ts +47 -45
- package/app/components/ui/Popover/index.vue +1 -1
- package/app/components/ui/Qrcode/index.stories.ts +42 -34
- package/app/components/ui/RadioCardGroup/index.stories.ts +23 -32
- package/app/components/ui/RadioCardGroup/index.vue +1 -1
- package/app/components/ui/RadioGroup/index.stories.ts +123 -0
- package/app/components/ui/RadioGroup/index.vue +73 -0
- package/app/components/ui/RadioGroup/types.ts +13 -0
- package/app/components/ui/ScrollArea/index.stories.ts +69 -37
- package/app/components/ui/ScrollArea/index.vue +1 -1
- package/app/components/ui/SearchSelect/index.stories.ts +104 -66
- package/app/components/ui/Select/index.stories.ts +152 -98
- package/app/components/ui/Select/index.vue +3 -3
- package/app/components/ui/Skeleton/index.stories.ts +27 -30
- package/app/components/ui/Skeleton/index.vue +1 -1
- package/app/components/ui/Slider/index.stories.ts +73 -31
- package/app/components/ui/Slider/index.vue +1 -1
- package/app/components/ui/Surface/index.stories.ts +47 -21
- package/app/components/ui/Surface/index.vue +39 -28
- package/app/components/ui/Surface/types.ts +2 -2
- package/app/components/ui/Switch/index.stories.ts +6 -7
- package/app/components/ui/Switch/index.vue +1 -1
- package/app/components/ui/Tabs/index.stories.ts +103 -61
- package/app/components/ui/Tabs/index.vue +1 -1
- package/app/components/ui/Tag/index.stories.ts +42 -25
- package/app/components/ui/Tag/index.vue +39 -28
- package/app/components/ui/Tag/types.ts +2 -2
- package/app/components/ui/Textarea/index.stories.ts +73 -9
- package/app/components/ui/Textarea/index.vue +1 -1
- package/app/components/ui/Toast/index.stories.ts +71 -18
- package/app/components/ui/Toast/index.vue +1 -1
- package/app/components/ui/Tooltip/index.stories.ts +45 -38
- package/app/components/ui/Tooltip/index.vue +1 -1
- package/app/components/ui/WebLink/index.stories.ts +76 -41
- package/app/components/ui/WebLink/index.vue +1 -1
- package/package.json +2 -2
- package/app/components/ui/Radio/index.stories.ts +0 -71
- package/app/components/ui/Radio/index.vue +0 -10
- package/app/components/ui/Radio/types.ts +0 -3
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
2
|
import Button from '../Button/index.vue'
|
|
3
3
|
import Input from '../Input/index.vue'
|
|
4
|
+
import type { DrawerSide } from './types'
|
|
4
5
|
import Drawer from './index.vue'
|
|
5
6
|
|
|
7
|
+
const sides: DrawerSide[] = [ 'top', 'right', 'bottom', 'left' ]
|
|
8
|
+
|
|
6
9
|
const meta = {
|
|
7
10
|
title: 'UI/Drawer',
|
|
8
11
|
component: Drawer,
|
|
@@ -14,110 +17,157 @@ const meta = {
|
|
|
14
17
|
showClose: { control: 'boolean' },
|
|
15
18
|
hideHeader: { control: 'boolean' },
|
|
16
19
|
hideFooter: { control: 'boolean' },
|
|
17
|
-
side: {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
},
|
|
20
|
+
side: { control: 'select', options: sides },
|
|
21
|
+
title: { control: 'text' },
|
|
22
|
+
description: { control: 'text' },
|
|
23
|
+
confirmText: { control: 'text' },
|
|
24
|
+
cancelText: { control: 'text' },
|
|
21
25
|
},
|
|
22
26
|
args: {
|
|
23
27
|
loading: false,
|
|
24
28
|
disabled: false,
|
|
25
29
|
confirmDisabled: false,
|
|
26
|
-
showCancel:
|
|
30
|
+
showCancel: true,
|
|
27
31
|
showClose: true,
|
|
28
32
|
hideHeader: false,
|
|
29
33
|
hideFooter: false,
|
|
30
34
|
side: 'right',
|
|
35
|
+
title: 'Drawer Title',
|
|
36
|
+
description: '',
|
|
37
|
+
confirmText: 'OK',
|
|
38
|
+
cancelText: 'Cancel',
|
|
31
39
|
},
|
|
32
|
-
|
|
40
|
+
render: args => ({
|
|
41
|
+
components: { Drawer, Button, Input },
|
|
42
|
+
setup () {
|
|
43
|
+
const visible = ref(false)
|
|
44
|
+
return { args, visible }
|
|
45
|
+
},
|
|
46
|
+
template: `
|
|
47
|
+
<div>
|
|
48
|
+
<Button @click="visible = true">Open Drawer</Button>
|
|
49
|
+
<Drawer v-model:visible="visible" v-bind="args">
|
|
50
|
+
<p>This is the drawer content.</p>
|
|
51
|
+
<Input class="mt-4" placeholder="Try interacting with this input" />
|
|
52
|
+
</Drawer>
|
|
53
|
+
</div>
|
|
54
|
+
`,
|
|
55
|
+
}),
|
|
56
|
+
} satisfies Meta<typeof Drawer>
|
|
33
57
|
|
|
34
58
|
export default meta
|
|
35
59
|
type Story = StoryObj<typeof meta>
|
|
36
60
|
|
|
37
|
-
export const Default: Story = {
|
|
38
|
-
|
|
61
|
+
export const Default: Story = {}
|
|
62
|
+
|
|
63
|
+
export const WithDescription: Story = {
|
|
64
|
+
render: () => ({
|
|
39
65
|
components: { Drawer, Button, Input },
|
|
40
66
|
setup () {
|
|
41
|
-
const
|
|
42
|
-
|
|
67
|
+
const visible = ref(false)
|
|
68
|
+
return { visible }
|
|
69
|
+
},
|
|
70
|
+
template: `
|
|
71
|
+
<div>
|
|
72
|
+
<Button @click="visible = true">Open Drawer</Button>
|
|
73
|
+
<Drawer
|
|
74
|
+
v-model:visible="visible"
|
|
75
|
+
title="Edit Profile"
|
|
76
|
+
description="Update your personal information. Changes will be visible to other users immediately."
|
|
77
|
+
showCancel
|
|
78
|
+
confirmText="Save"
|
|
79
|
+
>
|
|
80
|
+
<div class="space-y-3">
|
|
81
|
+
<Input placeholder="Name" />
|
|
82
|
+
<Input placeholder="Email" />
|
|
83
|
+
</div>
|
|
84
|
+
</Drawer>
|
|
85
|
+
</div>
|
|
86
|
+
`,
|
|
87
|
+
}),
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export const ScrollableContent: Story = {
|
|
91
|
+
render: () => ({
|
|
92
|
+
components: { Drawer, Button },
|
|
93
|
+
setup () {
|
|
94
|
+
const visible = ref(false)
|
|
95
|
+
return { visible }
|
|
96
|
+
},
|
|
97
|
+
template: `
|
|
98
|
+
<div>
|
|
99
|
+
<Button @click="visible = true">Open Drawer</Button>
|
|
100
|
+
<Drawer v-model:visible="visible" title="Terms of Service" showCancel confirmText="Accept">
|
|
101
|
+
<div class="space-y-4">
|
|
102
|
+
<p v-for="i in 20" :key="i">
|
|
103
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.
|
|
104
|
+
</p>
|
|
105
|
+
</div>
|
|
106
|
+
</Drawer>
|
|
107
|
+
</div>
|
|
108
|
+
`,
|
|
109
|
+
}),
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export const Sides: Story = {
|
|
113
|
+
render: () => ({
|
|
114
|
+
components: { Drawer, Button },
|
|
115
|
+
setup () {
|
|
43
116
|
const sideTop = ref(false)
|
|
44
117
|
const sideRight = ref(false)
|
|
45
118
|
const sideBottom = ref(false)
|
|
46
119
|
const sideLeft = ref(false)
|
|
47
|
-
|
|
48
|
-
return { args, controlled, withDescription, sideTop, sideRight, sideBottom, sideLeft, scrollable }
|
|
120
|
+
return { sideTop, sideRight, sideBottom, sideLeft }
|
|
49
121
|
},
|
|
50
122
|
template: `
|
|
51
|
-
<div
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
<
|
|
55
|
-
<Button @click="
|
|
56
|
-
<
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
>
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
</
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
title="Edit Profile"
|
|
75
|
-
description="Update your personal information. Changes will be visible to other users immediately."
|
|
76
|
-
showCancel
|
|
77
|
-
confirmText="Save"
|
|
78
|
-
>
|
|
79
|
-
<div class="space-y-3">
|
|
80
|
-
<Input placeholder="Name" />
|
|
81
|
-
<Input placeholder="Email" />
|
|
82
|
-
</div>
|
|
83
|
-
</Drawer>
|
|
84
|
-
</section>
|
|
85
|
-
|
|
86
|
-
<!-- Scrollable Content -->
|
|
87
|
-
<section>
|
|
88
|
-
<h3 class="mb-4 text-lg font-medium">Scrollable Content</h3>
|
|
89
|
-
<Button @click="scrollable = true">Open Drawer</Button>
|
|
90
|
-
<Drawer v-model:visible="scrollable" title="Terms of Service" showCancel confirmText="Accept">
|
|
91
|
-
<div class="space-y-4">
|
|
92
|
-
<p v-for="i in 20" :key="i">
|
|
93
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.
|
|
94
|
-
</p>
|
|
95
|
-
</div>
|
|
96
|
-
</Drawer>
|
|
97
|
-
</section>
|
|
123
|
+
<div>
|
|
124
|
+
<div class="flex gap-2">
|
|
125
|
+
<Button variant="outline" @click="sideTop = true">Top</Button>
|
|
126
|
+
<Button variant="outline" @click="sideRight = true">Right</Button>
|
|
127
|
+
<Button variant="outline" @click="sideBottom = true">Bottom</Button>
|
|
128
|
+
<Button variant="outline" @click="sideLeft = true">Left</Button>
|
|
129
|
+
</div>
|
|
130
|
+
<Drawer v-model:visible="sideTop" side="top" title="Top Drawer">
|
|
131
|
+
<p>Slides in from the top.</p>
|
|
132
|
+
</Drawer>
|
|
133
|
+
<Drawer v-model:visible="sideRight" side="right" title="Right Drawer">
|
|
134
|
+
<p>Slides in from the right.</p>
|
|
135
|
+
</Drawer>
|
|
136
|
+
<Drawer v-model:visible="sideBottom" side="bottom" title="Bottom Drawer">
|
|
137
|
+
<p>Slides in from the bottom.</p>
|
|
138
|
+
</Drawer>
|
|
139
|
+
<Drawer v-model:visible="sideLeft" side="left" title="Left Drawer">
|
|
140
|
+
<p>Slides in from the left.</p>
|
|
141
|
+
</Drawer>
|
|
142
|
+
</div>
|
|
143
|
+
`,
|
|
144
|
+
}),
|
|
145
|
+
}
|
|
98
146
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
147
|
+
export const EventHandling: Story = {
|
|
148
|
+
render: () => ({
|
|
149
|
+
components: { Drawer, Button },
|
|
150
|
+
setup () {
|
|
151
|
+
const visible = ref(false)
|
|
152
|
+
return { visible }
|
|
153
|
+
},
|
|
154
|
+
template: `
|
|
155
|
+
<div>
|
|
156
|
+
<Button @click="visible = true">Open Drawer</Button>
|
|
157
|
+
<Drawer
|
|
158
|
+
v-model:visible="visible"
|
|
159
|
+
title="Event Demo"
|
|
160
|
+
description="Open the Actions panel to see emitted events."
|
|
161
|
+
showCancel
|
|
162
|
+
confirmText="Confirm"
|
|
163
|
+
@open="() => {}"
|
|
164
|
+
@close="() => {}"
|
|
165
|
+
@closed="() => {}"
|
|
166
|
+
@confirm="() => {}"
|
|
167
|
+
@cancel="() => {}"
|
|
168
|
+
>
|
|
169
|
+
<p>Click Confirm, Cancel, or the close button to see events fire.</p>
|
|
170
|
+
</Drawer>
|
|
121
171
|
</div>
|
|
122
172
|
`,
|
|
123
173
|
}),
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
SheetFooter,
|
|
8
8
|
SheetHeader,
|
|
9
9
|
SheetTitle,
|
|
10
|
-
} from '
|
|
10
|
+
} from '../../shadcn/sheet'
|
|
11
11
|
import type { DrawerProps } from './types'
|
|
12
12
|
|
|
13
13
|
const props = withDefaults(defineProps<DrawerProps>(), {
|
|
@@ -175,7 +175,6 @@ const contentClass = computed(() =>
|
|
|
175
175
|
/* Translucent blur backdrop. SheetOverlay is rendered inside DialogPortal
|
|
176
176
|
(outside component scope), so use a non-scoped style. */
|
|
177
177
|
[data-slot='sheet-overlay'] {
|
|
178
|
-
z-index: 200;
|
|
179
178
|
background-color: rgba(252, 252, 252, 0.3);
|
|
180
179
|
backdrop-filter: blur(2px);
|
|
181
180
|
-webkit-backdrop-filter: blur(2px);
|
|
@@ -184,11 +183,6 @@ const contentClass = computed(() =>
|
|
|
184
183
|
background-color: rgba(25, 25, 25, 0.3);
|
|
185
184
|
}
|
|
186
185
|
|
|
187
|
-
/* Raise above layout header (z-100) so the drawer covers it. */
|
|
188
|
-
[data-slot='sheet-content'] {
|
|
189
|
-
z-index: 200;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
186
|
/* Hide SheetContent's hardcoded built-in close button (no data-slot);
|
|
193
187
|
we render our own SheetClose above with loading-aware disable. */
|
|
194
188
|
[data-slot='sheet-content'] > button:not([data-slot]) {
|
|
@@ -3,74 +3,132 @@ import type { DropdownItem } from './types'
|
|
|
3
3
|
import Button from '../Button/index.vue'
|
|
4
4
|
import Dropdown from './index.vue'
|
|
5
5
|
|
|
6
|
+
const basicMenus: DropdownItem[] = [
|
|
7
|
+
{ label: 'Edit', icon: 'pencil' },
|
|
8
|
+
{ label: 'Duplicate', icon: 'copy' },
|
|
9
|
+
{ type: 'separator' },
|
|
10
|
+
{ label: 'Delete', icon: 'trash-2', color: 'danger' },
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
const accountMenus: DropdownItem[] = [
|
|
14
|
+
{ label: 'Profile', icon: 'user' },
|
|
15
|
+
{ label: 'Settings', icon: 'settings' },
|
|
16
|
+
{ label: 'Admin Panel', icon: 'shield', disabled: true },
|
|
17
|
+
{ type: 'separator' },
|
|
18
|
+
{ label: 'Logout', icon: 'log-out' },
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
const linkMenus: DropdownItem[] = [
|
|
22
|
+
{ label: 'Documentation', icon: 'book-open', href: 'https://example.com/docs', target: '_blank' },
|
|
23
|
+
{ label: 'Support', icon: 'life-buoy', href: 'https://example.com/support', target: '_blank' },
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
const groupedMenus: DropdownItem[] = [
|
|
27
|
+
{ type: 'label', label: 'Organization' },
|
|
28
|
+
{ label: 'Switch Org', icon: 'arrow-left-right' },
|
|
29
|
+
{ type: 'separator' },
|
|
30
|
+
{ type: 'label', label: 'Account' },
|
|
31
|
+
{ label: 'Profile', icon: 'user' },
|
|
32
|
+
{ label: 'Settings', icon: 'settings' },
|
|
33
|
+
{ type: 'separator' },
|
|
34
|
+
{ label: 'Logout', icon: 'log-out' },
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
const customMenus: DropdownItem[] = [
|
|
38
|
+
{
|
|
39
|
+
type: 'custom-label',
|
|
40
|
+
slot: 'profile',
|
|
41
|
+
title: 'Demo User',
|
|
42
|
+
email: 'demo@example.com',
|
|
43
|
+
},
|
|
44
|
+
{ type: 'separator' },
|
|
45
|
+
{ label: 'Profile', icon: 'user' },
|
|
46
|
+
{ label: 'Settings', icon: 'settings' },
|
|
47
|
+
{ type: 'separator' },
|
|
48
|
+
{
|
|
49
|
+
type: 'custom-action',
|
|
50
|
+
slot: 'logout',
|
|
51
|
+
command: () => alert('Logged out'),
|
|
52
|
+
},
|
|
53
|
+
]
|
|
54
|
+
|
|
6
55
|
const meta = {
|
|
7
56
|
title: 'UI/Dropdown',
|
|
8
57
|
component: Dropdown,
|
|
58
|
+
argTypes: {
|
|
59
|
+
menus: { control: 'object' },
|
|
60
|
+
trigger: { control: 'inline-radio', options: [ 'click', 'hover' ]},
|
|
61
|
+
side: { control: 'select', options: [ 'top', 'bottom', 'left', 'right' ]},
|
|
62
|
+
align: { control: 'select', options: [ 'start', 'center', 'end' ]},
|
|
63
|
+
sideOffset: { control: 'number' },
|
|
64
|
+
},
|
|
65
|
+
args: {
|
|
66
|
+
menus: basicMenus,
|
|
67
|
+
trigger: 'click',
|
|
68
|
+
side: undefined,
|
|
69
|
+
align: undefined,
|
|
70
|
+
sideOffset: undefined,
|
|
71
|
+
},
|
|
72
|
+
render: args => ({
|
|
73
|
+
components: { Dropdown, Button },
|
|
74
|
+
setup: () => ({ args }),
|
|
75
|
+
template: `
|
|
76
|
+
<Dropdown v-bind="args">
|
|
77
|
+
<Button variant="outline">Open Menu</Button>
|
|
78
|
+
</Dropdown>
|
|
79
|
+
`,
|
|
80
|
+
}),
|
|
9
81
|
} satisfies Meta<typeof Dropdown>
|
|
10
82
|
|
|
11
83
|
export default meta
|
|
12
84
|
type Story = StoryObj<typeof meta>
|
|
13
85
|
|
|
14
|
-
const
|
|
15
|
-
{ label: 'Edit', icon: 'pencil' },
|
|
16
|
-
{ label: 'Duplicate', icon: 'copy' },
|
|
17
|
-
{ type: 'separator' },
|
|
18
|
-
{ label: 'Delete', icon: 'trash-2', color: 'danger' },
|
|
19
|
-
]
|
|
86
|
+
export const Default: Story = {}
|
|
20
87
|
|
|
21
|
-
export const
|
|
88
|
+
export const HoverTrigger: Story = {
|
|
22
89
|
render: () => ({
|
|
23
90
|
components: { Dropdown, Button },
|
|
24
|
-
setup () {
|
|
25
|
-
const menus: DropdownItem[] = [
|
|
26
|
-
{ label: 'Profile', icon: 'user' },
|
|
27
|
-
{ label: 'Settings', icon: 'settings' },
|
|
28
|
-
{ label: 'Admin Panel', icon: 'shield', disabled: true },
|
|
29
|
-
{ type: 'separator' },
|
|
30
|
-
{ label: 'Logout', icon: 'log-out' },
|
|
31
|
-
]
|
|
32
|
-
|
|
33
|
-
const linkMenus: DropdownItem[] = [
|
|
34
|
-
{ label: 'Documentation', icon: 'book-open', href: 'https://example.com/docs', target: '_blank' },
|
|
35
|
-
{ label: 'Support', icon: 'life-buoy', href: 'https://example.com/support', target: '_blank' },
|
|
36
|
-
]
|
|
37
|
-
|
|
38
|
-
return { basicMenus, menus, linkMenus }
|
|
39
|
-
},
|
|
91
|
+
setup: () => ({ basicMenus }),
|
|
40
92
|
template: `
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
</Dropdown>
|
|
48
|
-
</section>
|
|
93
|
+
<Dropdown :menus="basicMenus" trigger="hover">
|
|
94
|
+
<Button variant="outline">Hover me</Button>
|
|
95
|
+
</Dropdown>
|
|
96
|
+
`,
|
|
97
|
+
}),
|
|
98
|
+
}
|
|
49
99
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
</
|
|
100
|
+
export const ClickTrigger: Story = {
|
|
101
|
+
render: () => ({
|
|
102
|
+
components: { Dropdown, Button },
|
|
103
|
+
setup: () => ({ basicMenus }),
|
|
104
|
+
template: `
|
|
105
|
+
<Dropdown :menus="basicMenus" trigger="click">
|
|
106
|
+
<Button variant="outline">Click me</Button>
|
|
107
|
+
</Dropdown>
|
|
108
|
+
`,
|
|
109
|
+
}),
|
|
110
|
+
}
|
|
57
111
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
</
|
|
112
|
+
export const WithDisabledItems: Story = {
|
|
113
|
+
render: () => ({
|
|
114
|
+
components: { Dropdown, Button },
|
|
115
|
+
setup: () => ({ accountMenus }),
|
|
116
|
+
template: `
|
|
117
|
+
<Dropdown :menus="accountMenus" trigger="click">
|
|
118
|
+
<Button variant="outline">Account</Button>
|
|
119
|
+
</Dropdown>
|
|
120
|
+
`,
|
|
121
|
+
}),
|
|
122
|
+
}
|
|
65
123
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
</
|
|
73
|
-
</
|
|
124
|
+
export const WithLinks: Story = {
|
|
125
|
+
render: () => ({
|
|
126
|
+
components: { Dropdown, Button },
|
|
127
|
+
setup: () => ({ linkMenus }),
|
|
128
|
+
template: `
|
|
129
|
+
<Dropdown :menus="linkMenus" trigger="click">
|
|
130
|
+
<Button variant="outline">Resources</Button>
|
|
131
|
+
</Dropdown>
|
|
74
132
|
`,
|
|
75
133
|
}),
|
|
76
134
|
}
|
|
@@ -78,20 +136,7 @@ export const Default: Story = {
|
|
|
78
136
|
export const WithGroups: Story = {
|
|
79
137
|
render: () => ({
|
|
80
138
|
components: { Dropdown, Button },
|
|
81
|
-
setup () {
|
|
82
|
-
const groupedMenus: DropdownItem[] = [
|
|
83
|
-
{ type: 'label', label: 'Organization' },
|
|
84
|
-
{ label: 'Switch Org', icon: 'arrow-left-right' },
|
|
85
|
-
{ type: 'separator' },
|
|
86
|
-
{ type: 'label', label: 'Account' },
|
|
87
|
-
{ label: 'Profile', icon: 'user' },
|
|
88
|
-
{ label: 'Settings', icon: 'settings' },
|
|
89
|
-
{ type: 'separator' },
|
|
90
|
-
{ label: 'Logout', icon: 'log-out' },
|
|
91
|
-
]
|
|
92
|
-
|
|
93
|
-
return { groupedMenus }
|
|
94
|
-
},
|
|
139
|
+
setup: () => ({ groupedMenus }),
|
|
95
140
|
template: `
|
|
96
141
|
<Dropdown :menus="groupedMenus" trigger="click">
|
|
97
142
|
<Button variant="outline">Menu with Groups</Button>
|
|
@@ -100,30 +145,10 @@ export const WithGroups: Story = {
|
|
|
100
145
|
}),
|
|
101
146
|
}
|
|
102
147
|
|
|
103
|
-
export const
|
|
148
|
+
export const CustomSlots: Story = {
|
|
104
149
|
render: () => ({
|
|
105
150
|
components: { Dropdown, Button },
|
|
106
|
-
setup () {
|
|
107
|
-
const customMenus: DropdownItem[] = [
|
|
108
|
-
{
|
|
109
|
-
type: 'custom-label',
|
|
110
|
-
slot: 'profile',
|
|
111
|
-
title: 'Demo User',
|
|
112
|
-
email: 'demo@example.com',
|
|
113
|
-
},
|
|
114
|
-
{ type: 'separator' },
|
|
115
|
-
{ label: 'Profile', icon: 'user' },
|
|
116
|
-
{ label: 'Settings', icon: 'settings' },
|
|
117
|
-
{ type: 'separator' },
|
|
118
|
-
{
|
|
119
|
-
type: 'custom-action',
|
|
120
|
-
slot: 'logout',
|
|
121
|
-
command: () => alert('Logged out'),
|
|
122
|
-
},
|
|
123
|
-
]
|
|
124
|
-
|
|
125
|
-
return { customMenus }
|
|
126
|
-
},
|
|
151
|
+
setup: () => ({ customMenus }),
|
|
127
152
|
template: `
|
|
128
153
|
<Dropdown :menus="customMenus" trigger="click">
|
|
129
154
|
<Button variant="outline">Custom Slots</Button>
|
|
@@ -143,3 +168,23 @@ export const WithCustomSlots: Story = {
|
|
|
143
168
|
`,
|
|
144
169
|
}),
|
|
145
170
|
}
|
|
171
|
+
|
|
172
|
+
export const PopupSlot: Story = {
|
|
173
|
+
render: () => ({
|
|
174
|
+
components: { Dropdown, Button },
|
|
175
|
+
template: `
|
|
176
|
+
<Dropdown trigger="click">
|
|
177
|
+
<Button variant="outline">Custom Popup</Button>
|
|
178
|
+
<template #popup="{ hide }">
|
|
179
|
+
<div class="flex flex-col gap-2 p-3 min-w-[220px]">
|
|
180
|
+
<div class="text-sm font-semibold">Custom content</div>
|
|
181
|
+
<p class="text-sm text-muted-foreground">
|
|
182
|
+
Use the <code>popup</code> slot to render arbitrary content inside the menu.
|
|
183
|
+
</p>
|
|
184
|
+
<Button size="sm" @click="hide">Close</Button>
|
|
185
|
+
</div>
|
|
186
|
+
</template>
|
|
187
|
+
</Dropdown>
|
|
188
|
+
`,
|
|
189
|
+
}),
|
|
190
|
+
}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
DropdownMenuLabel,
|
|
7
7
|
DropdownMenuSeparator,
|
|
8
8
|
DropdownMenuTrigger,
|
|
9
|
-
} from '
|
|
9
|
+
} from '../../shadcn/dropdown-menu'
|
|
10
10
|
import { cva } from 'class-variance-authority'
|
|
11
11
|
import type {
|
|
12
12
|
DropdownActionItem,
|
|
@@ -18,6 +18,10 @@ const actionColorVariants = cva('', {
|
|
|
18
18
|
variants: {
|
|
19
19
|
color: {
|
|
20
20
|
default: '',
|
|
21
|
+
primary: `
|
|
22
|
+
text-primary
|
|
23
|
+
focus:bg-primary/10 focus:text-primary
|
|
24
|
+
`,
|
|
21
25
|
success: `
|
|
22
26
|
text-success
|
|
23
27
|
focus:bg-success/10 focus:text-success
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Component } from 'vue'
|
|
2
2
|
|
|
3
|
-
export type DropdownItemColor = 'default' | 'success' | 'info' | 'help' | 'warn' | 'danger'
|
|
3
|
+
export type DropdownItemColor = 'default' | 'primary' | 'success' | 'info' | 'help' | 'warn' | 'danger'
|
|
4
4
|
|
|
5
5
|
export interface DropdownActionItem {
|
|
6
6
|
/** Defaults to 'action' when omitted. */
|