@meistrari/tela-build 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -0
- package/app.config.ts +73 -0
- package/components/tela/animated/animated-calculating-number.vue +16 -0
- package/components/tela/animated/animated-number.mdx +248 -0
- package/components/tela/animated/animated-number.stories.ts +52 -0
- package/components/tela/animated/animated-number.vue +23 -0
- package/components/tela/animated/animated-text.vue +124 -0
- package/components/tela/animated/animated-value.vue +68 -0
- package/components/tela/avatar/avatar.mdx +117 -0
- package/components/tela/avatar/avatar.stories.ts +62 -0
- package/components/tela/avatar/avatar.vue +71 -0
- package/components/tela/avatar/group/avatar-group.stories.ts +78 -0
- package/components/tela/avatar/group/avatar-group.vue +46 -0
- package/components/tela/badge/badge.mdx +154 -0
- package/components/tela/badge/badge.stories.ts +82 -0
- package/components/tela/badge/badge.vue +41 -0
- package/components/tela/button/button.mdx +155 -0
- package/components/tela/button/button.stories.ts +202 -0
- package/components/tela/button/button.vue +107 -0
- package/components/tela/card.vue +30 -0
- package/components/tela/chart/chart-bar.vue +58 -0
- package/components/tela/chat/chat.mdx +268 -0
- package/components/tela/chat/chat.stories.ts +253 -0
- package/components/tela/chat/command/index.vue +41 -0
- package/components/tela/chat/command/mention/index.vue +138 -0
- package/components/tela/chat/index.vue +112 -0
- package/components/tela/chat/pure-text-input/chat-text-input.vue +190 -0
- package/components/tela/chat/text-input/chat-text-input.stories.ts +128 -0
- package/components/tela/chat/text-input/index.vue +217 -0
- package/components/tela/chat/text-message/chat-text-message.stories.ts +138 -0
- package/components/tela/chat/text-message/index.vue +355 -0
- package/components/tela/chat/types.ts +19 -0
- package/components/tela/checkbox/checkbox-card.vue +30 -0
- package/components/tela/checkbox/checkbox.mdx +164 -0
- package/components/tela/checkbox/checkbox.stories.ts +104 -0
- package/components/tela/checkbox/checkbox.vue +43 -0
- package/components/tela/collapsible/Collapsible.vue +15 -0
- package/components/tela/collapsible/CollapsibleContent.vue +59 -0
- package/components/tela/collapsible/CollapsibleTrigger.vue +12 -0
- package/components/tela/collapsible/collapsible.mdx +157 -0
- package/components/tela/collapsible-section/collapsible-section.mdx +180 -0
- package/components/tela/collapsible-section/collapsible-section.stories.ts +53 -0
- package/components/tela/collapsible-section/collapsible-section.vue +51 -0
- package/components/tela/collapsible-section-with-actions.vue +98 -0
- package/components/tela/combobox/combobox-anchor.vue +24 -0
- package/components/tela/combobox/combobox-empty.vue +19 -0
- package/components/tela/combobox/combobox-group.vue +24 -0
- package/components/tela/combobox/combobox-indicator.vue +22 -0
- package/components/tela/combobox/combobox-input.vue +31 -0
- package/components/tela/combobox/combobox-item.vue +28 -0
- package/components/tela/combobox/combobox-label.vue +24 -0
- package/components/tela/combobox/combobox-list.vue +90 -0
- package/components/tela/combobox/combobox-module-selector.vue +366 -0
- package/components/tela/combobox/combobox-root.vue +15 -0
- package/components/tela/combobox/combobox-trigger.vue +12 -0
- package/components/tela/combobox/combobox.mdx +285 -0
- package/components/tela/combobox/combobox.stories.ts +232 -0
- package/components/tela/combobox/combobox.vue +497 -0
- package/components/tela/command/command-dialog.vue +22 -0
- package/components/tela/command/command-empty.vue +25 -0
- package/components/tela/command/command-group.vue +46 -0
- package/components/tela/command/command-input.vue +38 -0
- package/components/tela/command/command-item.vue +78 -0
- package/components/tela/command/command-list.vue +78 -0
- package/components/tela/command/command-separator.vue +23 -0
- package/components/tela/command/command-shortcut.vue +13 -0
- package/components/tela/command/command.vue +88 -0
- package/components/tela/command/dialog-base.vue +15 -0
- package/components/tela/command/dialog-content.vue +50 -0
- package/components/tela/command/utils.ts +15 -0
- package/components/tela/complex-table/complex-table-cell.stories.ts +145 -0
- package/components/tela/complex-table/complex-table-cell.vue +45 -0
- package/components/tela/complex-table/complex-table-header-cell.stories.ts +103 -0
- package/components/tela/complex-table/complex-table-header-cell.vue +48 -0
- package/components/tela/complex-table/complex-table-header.stories.ts +89 -0
- package/components/tela/complex-table/complex-table-header.vue +70 -0
- package/components/tela/complex-table/complex-table-row.vue +199 -0
- package/components/tela/complex-table/complex-table-virtualized.vue +326 -0
- package/components/tela/complex-table/complex-table.stories.ts +358 -0
- package/components/tela/complex-table/complex-table.vue +237 -0
- package/components/tela/complex-table/composables/table-common.ts +93 -0
- package/components/tela/complex-table/composables/table-selection.ts +87 -0
- package/components/tela/complex-table/composables/virtual-scroll.ts +252 -0
- package/components/tela/complex-table/styles/table-shared.css +170 -0
- package/components/tela/complex-table/types.ts +63 -0
- package/components/tela/complex-table/utils.ts +35 -0
- package/components/tela/confirm-button/confirm-button.vue +137 -0
- package/components/tela/confirmation-modal/confirmation-modal.vue +72 -0
- package/components/tela/copy-button.vue +86 -0
- package/components/tela/date-range-picker.vue +221 -0
- package/components/tela/dialog/dialog.mdx +170 -0
- package/components/tela/dialog/dialog.vue +182 -0
- package/components/tela/disabled-area.vue +16 -0
- package/components/tela/disclaimer/disclaimer.mdx +238 -0
- package/components/tela/disclaimer/disclaimer.stories.ts +196 -0
- package/components/tela/disclaimer/disclaimer.vue +125 -0
- package/components/tela/dropdown-menu/DropdownMenu.vue +121 -0
- package/components/tela/dropdown-menu/DropdownMenuCheckboxItem.vue +40 -0
- package/components/tela/dropdown-menu/DropdownMenuContent.vue +75 -0
- package/components/tela/dropdown-menu/DropdownMenuGroup.vue +12 -0
- package/components/tela/dropdown-menu/DropdownMenuItem.vue +137 -0
- package/components/tela/dropdown-menu/DropdownMenuLabel.vue +26 -0
- package/components/tela/dropdown-menu/DropdownMenuRadioGroup.vue +18 -0
- package/components/tela/dropdown-menu/DropdownMenuRadioItem.vue +40 -0
- package/components/tela/dropdown-menu/DropdownMenuRoot.vue +15 -0
- package/components/tela/dropdown-menu/DropdownMenuSeparator.vue +21 -0
- package/components/tela/dropdown-menu/DropdownMenuShortcut.vue +14 -0
- package/components/tela/dropdown-menu/DropdownMenuSub.vue +18 -0
- package/components/tela/dropdown-menu/DropdownMenuSubContent.vue +30 -0
- package/components/tela/dropdown-menu/DropdownMenuSubTrigger.vue +35 -0
- package/components/tela/dropdown-menu/DropdownMenuTrigger.vue +14 -0
- package/components/tela/dropdown-menu/dropdown-menu.mdx +265 -0
- package/components/tela/dropdown-menu/dropdown-menu.stories.ts +156 -0
- package/components/tela/expandable-input.vue +96 -0
- package/components/tela/file-drop.vue +37 -0
- package/components/tela/file-upload/file-upload.mdx +189 -0
- package/components/tela/file-upload/file-upload.stories.ts +48 -0
- package/components/tela/file-upload/file-upload.vue +205 -0
- package/components/tela/filters/checkbox-filter.stories.ts +218 -0
- package/components/tela/filters/checkbox-filter.vue +165 -0
- package/components/tela/filters/date-filter.stories.ts +258 -0
- package/components/tela/filters/date-filter.vue +200 -0
- package/components/tela/filters/user-filter.stories.ts +344 -0
- package/components/tela/filters/user-filter.vue +271 -0
- package/components/tela/hover-card/hover-card.mdx +221 -0
- package/components/tela/hover-card/hover-card.stories.ts +87 -0
- package/components/tela/hover-card/hover-card.vue +61 -0
- package/components/tela/icon/custom.vue +319 -0
- package/components/tela/icon/spinner.vue +12 -0
- package/components/tela/icon-button/icon-button.vue +114 -0
- package/components/tela/icon.vue +37 -0
- package/components/tela/initials.vue +28 -0
- package/components/tela/inline-input.vue +77 -0
- package/components/tela/input/input.mdx +182 -0
- package/components/tela/input/input.stories.ts +153 -0
- package/components/tela/input/tela-input.vue +240 -0
- package/components/tela/kbd/kbd-return.vue +6 -0
- package/components/tela/kbd/kbd.mdx +238 -0
- package/components/tela/kbd/kbd.vue +18 -0
- package/components/tela/label/label.mdx +121 -0
- package/components/tela/label/label.stories.ts +37 -0
- package/components/tela/label/label.vue +25 -0
- package/components/tela/link-decoration/link-decoration.vue +19 -0
- package/components/tela/live-label.vue +32 -0
- package/components/tela/long-press-button.vue +98 -0
- package/components/tela/menubar/menubar-content.vue +77 -0
- package/components/tela/menubar/menubar-item.vue +32 -0
- package/components/tela/menubar/menubar-label.vue +14 -0
- package/components/tela/menubar/menubar-menu.vue +12 -0
- package/components/tela/menubar/menubar-root.vue +30 -0
- package/components/tela/menubar/menubar-separator.vue +17 -0
- package/components/tela/menubar/menubar-shortcut.vue +14 -0
- package/components/tela/menubar/menubar-sub-content.vue +36 -0
- package/components/tela/menubar/menubar-sub-trigger.vue +28 -0
- package/components/tela/menubar/menubar-sub.vue +20 -0
- package/components/tela/menubar/menubar-trigger.vue +27 -0
- package/components/tela/menubar/menubar.vue +298 -0
- package/components/tela/modal/modal.mdx +145 -0
- package/components/tela/modal/modal.vue +242 -0
- package/components/tela/multiple-select/multiple-select.mdx +274 -0
- package/components/tela/multiple-select/multiple-select.stories.ts +325 -0
- package/components/tela/multiple-select/multiple-select.vue +666 -0
- package/components/tela/pane.vue +110 -0
- package/components/tela/popover/popover-content.vue +48 -0
- package/components/tela/popover/popover-trigger.vue +12 -0
- package/components/tela/popover/popover.mdx +239 -0
- package/components/tela/popover/popover.stories.ts +150 -0
- package/components/tela/popover/popover.vue +15 -0
- package/components/tela/popover-list/popover-list-nested.vue +104 -0
- package/components/tela/popover-list/popover-list.stories.ts +330 -0
- package/components/tela/popover-list/popover-list.vue +191 -0
- package/components/tela/radio-button.vue +66 -0
- package/components/tela/radio-group/radio-group-item.vue +40 -0
- package/components/tela/radio-group/radio-group-root.vue +26 -0
- package/components/tela/radio-group/radio-group.mdx +78 -0
- package/components/tela/radio-group/radio-group.stories.ts +106 -0
- package/components/tela/radio-group/radio-group.vue +23 -0
- package/components/tela/range-calendar.stories.ts +110 -0
- package/components/tela/range-calendar.vue +109 -0
- package/components/tela/scroll-area/scroll-area.mdx +183 -0
- package/components/tela/scroll-area/scroll-area.vue +30 -0
- package/components/tela/scroll-area/scroll-bar.vue +31 -0
- package/components/tela/segment-toggle.stories.ts +114 -0
- package/components/tela/segment-toggle.vue +66 -0
- package/components/tela/select-menu/select-menu-content.vue +106 -0
- package/components/tela/select-menu/select-menu-down-button.vue +20 -0
- package/components/tela/select-menu/select-menu-group.vue +16 -0
- package/components/tela/select-menu/select-menu-item.vue +40 -0
- package/components/tela/select-menu/select-menu-root.vue +15 -0
- package/components/tela/select-menu/select-menu-trigger.vue +34 -0
- package/components/tela/select-menu/select-menu-up-button.vue +20 -0
- package/components/tela/select-menu/select-menu-value.vue +12 -0
- package/components/tela/select-menu/select-menu.mdx +221 -0
- package/components/tela/select-menu/select-menu.stories.ts +91 -0
- package/components/tela/select-menu/select-menu.vue +165 -0
- package/components/tela/selector/selector.vue +47 -0
- package/components/tela/sheet/sheet-close.vue +12 -0
- package/components/tela/sheet/sheet-content.vue +57 -0
- package/components/tela/sheet/sheet-description.vue +23 -0
- package/components/tela/sheet/sheet-footer.vue +18 -0
- package/components/tela/sheet/sheet-header.vue +15 -0
- package/components/tela/sheet/sheet-root.vue +18 -0
- package/components/tela/sheet/sheet-title.vue +23 -0
- package/components/tela/sheet/sheet-trigger.vue +12 -0
- package/components/tela/sheet/sheet.client.vue +150 -0
- package/components/tela/sheet/sheet.mdx +176 -0
- package/components/tela/sheet/sheet.stories.ts +201 -0
- package/components/tela/sheet/variants.ts +22 -0
- package/components/tela/side-sheet/side-sheet.mdx +131 -0
- package/components/tela/side-sheet/side-sheet.stories.ts +134 -0
- package/components/tela/side-sheet/side-sheet.vue +106 -0
- package/components/tela/skeleton/skeleton.mdx +165 -0
- package/components/tela/skeleton/skeleton.stories.ts +35 -0
- package/components/tela/skeleton/skeleton.vue +45 -0
- package/components/tela/skeleton-icon.vue +24 -0
- package/components/tela/span.vue +24 -0
- package/components/tela/star-button.vue +70 -0
- package/components/tela/status/status-lean.vue +30 -0
- package/components/tela/status/status.mdx +187 -0
- package/components/tela/status/status.stories.ts +160 -0
- package/components/tela/status/status.vue +420 -0
- package/components/tela/status-bar/status-bar.mdx +178 -0
- package/components/tela/status-bar/status-bar.stories.ts +64 -0
- package/components/tela/status-bar/status-bar.vue +56 -0
- package/components/tela/status-bar/types.ts +5 -0
- package/components/tela/switch/switch.mdx +118 -0
- package/components/tela/switch/switch.stories.ts +80 -0
- package/components/tela/switch/switch.vue +56 -0
- package/components/tela/table/table-body.vue +13 -0
- package/components/tela/table/table-caption.vue +13 -0
- package/components/tela/table/table-cell.vue +20 -0
- package/components/tela/table/table-empty.vue +37 -0
- package/components/tela/table/table-footer.vue +13 -0
- package/components/tela/table/table-head.vue +13 -0
- package/components/tela/table/table-header.vue +13 -0
- package/components/tela/table/table-row.vue +13 -0
- package/components/tela/table/table.mdx +230 -0
- package/components/tela/table/table.stories.ts +384 -0
- package/components/tela/table/table.vue +15 -0
- package/components/tela/tabs/tabs-content.vue +20 -0
- package/components/tela/tabs/tabs-indicator.vue +22 -0
- package/components/tela/tabs/tabs-list.vue +23 -0
- package/components/tela/tabs/tabs-root.vue +15 -0
- package/components/tela/tabs/tabs-trigger.vue +27 -0
- package/components/tela/tabs/tabs.mdx +138 -0
- package/components/tela/tabs/tabs.stories.ts +72 -0
- package/components/tela/tabs/tabs.vue +61 -0
- package/components/tela/tags/tags-select.mdx +318 -0
- package/components/tela/tags/tags-select.stories.ts +47 -0
- package/components/tela/tags/tags-select.vue +637 -0
- package/components/tela/tags/tags.mdx +151 -0
- package/components/tela/tags/tags.stories.ts +118 -0
- package/components/tela/tags/tags.vue +112 -0
- package/components/tela/textarea/textarea.mdx +102 -0
- package/components/tela/textarea/textarea.stories.ts +50 -0
- package/components/tela/textarea/textarea.vue +34 -0
- package/components/tela/toggle-group.vue +91 -0
- package/components/tela/tooltip/tooltip-content.vue +45 -0
- package/components/tela/tooltip/tooltip-provider.vue +12 -0
- package/components/tela/tooltip/tooltip-root.vue +15 -0
- package/components/tela/tooltip/tooltip-trigger.vue +12 -0
- package/components/tela/tooltip/tooltip.mdx +196 -0
- package/components/tela/tooltip/tooltip.stories.ts +200 -0
- package/components/tela/tooltip/tooltip.vue +91 -0
- package/components/tela/tooltip-group/tooltip-group-trigger.vue +92 -0
- package/components/tela/tooltip-group/tooltip-group.mdx +236 -0
- package/components/tela/tooltip-group/tooltip-group.stories.ts +465 -0
- package/components/tela/tooltip-group/tooltip-group.vue +35 -0
- package/components/tela/transparent-input.vue +151 -0
- package/components/tela/variable-icon.vue +28 -0
- package/components/tela/variable-input.vue +77 -0
- package/components/tela/wide-button/wide-button.vue +40 -0
- package/components.json +18 -0
- package/composables/status-toast.ts +67 -0
- package/css/reset.css +386 -0
- package/css/text.css +22 -0
- package/lib/doc-generator.ts +903 -0
- package/lib/extractors/volar-extract.ts +186 -0
- package/lib/type-resolver.ts +402 -0
- package/lib/utils.ts +6 -0
- package/modules/tela-build-docs/index.ts +139 -0
- package/nuxt.config.ts +80 -0
- package/package.json +84 -0
- package/plugins/test-id.ts +7 -0
- package/tsconfig.json +7 -0
- package/types/custom-icon.ts +1 -0
- package/types/index.ts +2 -0
- package/types/status.ts +1 -0
- package/unocss.config.ts +89 -0
- package/utils/component-utils.ts +30 -0
- package/utils/design-tokens.ts +431 -0
- package/utils/fold.ts +8 -0
- package/utils/select-menu.ts +10 -0
- package/utils/status.ts +1 -0
- package/utils/without-keys.ts +34 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import * as DropdownMenuStories from './dropdown-menu.stories.ts';
|
|
3
|
+
|
|
4
|
+
<Meta of={DropdownMenuStories} />
|
|
5
|
+
|
|
6
|
+
# TelaDropdownMenu
|
|
7
|
+
|
|
8
|
+
A dropdown menu component built on radix-vue. Provides a flexible menu system with support for grouping, icons, tooltips, checkboxes, and search functionality. Items can be organized into groups and can include click handlers, disabled states, and custom styling.
|
|
9
|
+
|
|
10
|
+
## Examples
|
|
11
|
+
|
|
12
|
+
### Basic Usage
|
|
13
|
+
|
|
14
|
+
<Canvas of={DropdownMenuStories.Simple} />
|
|
15
|
+
|
|
16
|
+
### With Groups
|
|
17
|
+
|
|
18
|
+
<Canvas of={DropdownMenuStories.WithGroups} />
|
|
19
|
+
|
|
20
|
+
### With Tooltips
|
|
21
|
+
|
|
22
|
+
<Canvas of={DropdownMenuStories.WithTooltips} />
|
|
23
|
+
|
|
24
|
+
### Basic Usage Code
|
|
25
|
+
|
|
26
|
+
```vue
|
|
27
|
+
<script setup>
|
|
28
|
+
const menuItems = [
|
|
29
|
+
{
|
|
30
|
+
label: 'New File',
|
|
31
|
+
icon: 'i-ph-file-plus',
|
|
32
|
+
click: () => console.log('New file')
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
label: 'Open',
|
|
36
|
+
icon: 'i-ph-folder-open',
|
|
37
|
+
click: () => console.log('Open')
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
label: 'Save',
|
|
41
|
+
icon: 'i-ph-floppy-disk',
|
|
42
|
+
click: () => console.log('Save')
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<template>
|
|
48
|
+
<TelaDropdownMenu :items="menuItems">
|
|
49
|
+
<TelaButton>Actions</TelaButton>
|
|
50
|
+
</TelaDropdownMenu>
|
|
51
|
+
</template>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### With Groups Code
|
|
55
|
+
|
|
56
|
+
```vue
|
|
57
|
+
<TelaDropdownMenu
|
|
58
|
+
:items="[
|
|
59
|
+
{
|
|
60
|
+
label: 'Output File',
|
|
61
|
+
group: 'Files',
|
|
62
|
+
icon: 'i-ph-file-pdf',
|
|
63
|
+
click: () => {}
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
label: 'Database 1',
|
|
67
|
+
group: 'Databases',
|
|
68
|
+
icon: 'i-ph-database',
|
|
69
|
+
click: () => {}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
label: 'Database 2',
|
|
73
|
+
group: 'Databases',
|
|
74
|
+
icon: 'i-ph-database',
|
|
75
|
+
click: () => {}
|
|
76
|
+
}
|
|
77
|
+
]"
|
|
78
|
+
>
|
|
79
|
+
<TelaButton>Select Resource</TelaButton>
|
|
80
|
+
</TelaDropdownMenu>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### With Tooltips Code
|
|
84
|
+
|
|
85
|
+
```vue
|
|
86
|
+
<TelaDropdownMenu
|
|
87
|
+
:items="[
|
|
88
|
+
{
|
|
89
|
+
label: 'Download',
|
|
90
|
+
icon: 'i-ph-download-simple',
|
|
91
|
+
tooltip: 'Download your files',
|
|
92
|
+
click: () => {}
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
label: 'Delete',
|
|
96
|
+
icon: 'i-ph-trash',
|
|
97
|
+
color: 'negative',
|
|
98
|
+
disabled: true,
|
|
99
|
+
tooltip: {
|
|
100
|
+
variant: 'multiline',
|
|
101
|
+
title: 'Cannot delete',
|
|
102
|
+
description: 'Some items are protected',
|
|
103
|
+
side: 'right'
|
|
104
|
+
},
|
|
105
|
+
click: () => {}
|
|
106
|
+
}
|
|
107
|
+
]"
|
|
108
|
+
>
|
|
109
|
+
<TelaButton>Actions</TelaButton>
|
|
110
|
+
</TelaDropdownMenu>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### With Search
|
|
114
|
+
|
|
115
|
+
```vue
|
|
116
|
+
<TelaDropdownMenu
|
|
117
|
+
:items="longItemList"
|
|
118
|
+
allow-search
|
|
119
|
+
search-placeholder="Search actions..."
|
|
120
|
+
>
|
|
121
|
+
<TelaButton>Many Actions</TelaButton>
|
|
122
|
+
</TelaDropdownMenu>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### With Checkboxes
|
|
126
|
+
|
|
127
|
+
```vue
|
|
128
|
+
<script setup>
|
|
129
|
+
const items = ref([
|
|
130
|
+
{
|
|
131
|
+
label: 'Show Grid',
|
|
132
|
+
checkbox: true,
|
|
133
|
+
checked: true,
|
|
134
|
+
click: (item) => { item.checked = !item.checked }
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
label: 'Show Rulers',
|
|
138
|
+
checkbox: true,
|
|
139
|
+
checked: false,
|
|
140
|
+
click: (item) => { item.checked = !item.checked }
|
|
141
|
+
}
|
|
142
|
+
])
|
|
143
|
+
</script>
|
|
144
|
+
|
|
145
|
+
<template>
|
|
146
|
+
<TelaDropdownMenu :items="items">
|
|
147
|
+
<TelaButton>View Options</TelaButton>
|
|
148
|
+
</TelaDropdownMenu>
|
|
149
|
+
</template>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Destructive Actions
|
|
153
|
+
|
|
154
|
+
```vue
|
|
155
|
+
<TelaDropdownMenu
|
|
156
|
+
:items="[
|
|
157
|
+
{
|
|
158
|
+
label: 'Edit',
|
|
159
|
+
icon: 'i-ph-pencil',
|
|
160
|
+
click: () => {}
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
label: 'Duplicate',
|
|
164
|
+
icon: 'i-ph-copy',
|
|
165
|
+
click: () => {}
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
label: 'Delete',
|
|
169
|
+
icon: 'i-ph-trash',
|
|
170
|
+
color: 'negative',
|
|
171
|
+
click: () => {}
|
|
172
|
+
}
|
|
173
|
+
]"
|
|
174
|
+
>
|
|
175
|
+
<TelaButton variant="ghost">⋮</TelaButton>
|
|
176
|
+
</TelaDropdownMenu>
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### With Custom Alignment
|
|
180
|
+
|
|
181
|
+
```vue
|
|
182
|
+
<!-- Align to start -->
|
|
183
|
+
<TelaDropdownMenu :items="items" align="start">
|
|
184
|
+
<TelaButton>Align Start</TelaButton>
|
|
185
|
+
</TelaDropdownMenu>
|
|
186
|
+
|
|
187
|
+
<!-- Align to end (default) -->
|
|
188
|
+
<TelaDropdownMenu :items="items" align="end">
|
|
189
|
+
<TelaButton>Align End</TelaButton>
|
|
190
|
+
</TelaDropdownMenu>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Props
|
|
194
|
+
|
|
195
|
+
<ArgTypes />
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
type DropdownMenuItem = {
|
|
199
|
+
label: string
|
|
200
|
+
icon?: string
|
|
201
|
+
click?: () => void
|
|
202
|
+
group?: string
|
|
203
|
+
color?: 'default' | 'negative'
|
|
204
|
+
disabled?: boolean
|
|
205
|
+
checkbox?: boolean
|
|
206
|
+
checked?: boolean
|
|
207
|
+
tooltip?: string | {
|
|
208
|
+
variant?: 'single' | 'multiline'
|
|
209
|
+
title?: string
|
|
210
|
+
description?: string
|
|
211
|
+
side?: 'top' | 'right' | 'bottom' | 'left'
|
|
212
|
+
align?: 'start' | 'center' | 'end'
|
|
213
|
+
alignOffset?: number
|
|
214
|
+
arrowOffset?: number
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
type DropdownMenuProps = {
|
|
219
|
+
items: DropdownMenuItem[]
|
|
220
|
+
sideOffset?: number
|
|
221
|
+
allowSearch?: boolean
|
|
222
|
+
searchPlaceholder?: string
|
|
223
|
+
shouldBeModal?: boolean
|
|
224
|
+
contentClass?: string
|
|
225
|
+
align?: 'start' | 'end' | 'center'
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Features
|
|
230
|
+
|
|
231
|
+
- **Flexible Items**: Support icons, groups, colors, and states
|
|
232
|
+
- **Search**: Optional search functionality for long lists
|
|
233
|
+
- **Grouping**: Organize items into labeled groups
|
|
234
|
+
- **Tooltips**: Add tooltips to menu items
|
|
235
|
+
- **Checkboxes**: Toggle options with checkbox items
|
|
236
|
+
- **Click Handlers**: Execute actions on item click
|
|
237
|
+
- **Disabled State**: Disable specific items
|
|
238
|
+
- **Color Options**: Default or negative (destructive) colors
|
|
239
|
+
- **Custom Styling**: Control content and item styling
|
|
240
|
+
- **Keyboard Navigation**: Arrow keys, Enter, Escape
|
|
241
|
+
- **Accessible**: Built on radix-vue primitives
|
|
242
|
+
|
|
243
|
+
## Item Colors
|
|
244
|
+
|
|
245
|
+
- **default**: Standard menu item
|
|
246
|
+
- **negative**: Red/destructive action (e.g., Delete)
|
|
247
|
+
|
|
248
|
+
## Best Practices
|
|
249
|
+
|
|
250
|
+
1. **Group Related Items**: Use groups for better organization
|
|
251
|
+
2. **Place Destructive Actions Last**: Put delete/remove at bottom
|
|
252
|
+
3. **Use Icons**: Icons help with quick scanning
|
|
253
|
+
4. **Enable Search**: For lists with 10+ items
|
|
254
|
+
5. **Provide Tooltips**: Explain disabled items
|
|
255
|
+
6. **Keep Labels Brief**: Short, action-oriented labels
|
|
256
|
+
|
|
257
|
+
## Accessibility
|
|
258
|
+
|
|
259
|
+
- Built on radix-vue primitives
|
|
260
|
+
- Proper ARIA attributes (role="menu", role="menuitem")
|
|
261
|
+
- Keyboard navigation (Arrow keys, Home, End, Enter)
|
|
262
|
+
- Focus management
|
|
263
|
+
- Disabled items skip focus
|
|
264
|
+
- Screen reader support
|
|
265
|
+
- Escape key to close
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
|
+
|
|
3
|
+
import DropdownMenu from './DropdownMenu.vue'
|
|
4
|
+
import Button from '../button/button.vue'
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof DropdownMenu> = {
|
|
7
|
+
title: 'Core/DropdownMenu',
|
|
8
|
+
component: DropdownMenu,
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: 'centered',
|
|
11
|
+
docs: {
|
|
12
|
+
description: {
|
|
13
|
+
component: 'A dropdown menu component built on radix-vue. Provides a flexible menu system with support for grouping, icons, tooltips, checkboxes, and search functionality. Items can be organized into groups and can include click handlers, disabled states, and custom styling.',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
argTypes: {
|
|
18
|
+
items: {
|
|
19
|
+
control: false,
|
|
20
|
+
description: 'Array of menu items to display. Each item can have a label, icon, click handler, group, color, disabled state, checkbox, and tooltip. Items are automatically grouped by the `group` property.',
|
|
21
|
+
},
|
|
22
|
+
sideOffset: {
|
|
23
|
+
control: 'number',
|
|
24
|
+
description: 'Distance in pixels from the trigger element to the menu content.',
|
|
25
|
+
},
|
|
26
|
+
allowSearch: {
|
|
27
|
+
control: 'boolean',
|
|
28
|
+
description: 'Enable search functionality within the dropdown menu. Adds a search input at the top of the menu.',
|
|
29
|
+
},
|
|
30
|
+
searchPlaceholder: {
|
|
31
|
+
control: 'text',
|
|
32
|
+
description: 'Placeholder text for the search input. Only used when `allowSearch` is true.',
|
|
33
|
+
},
|
|
34
|
+
shouldBeModal: {
|
|
35
|
+
control: 'boolean',
|
|
36
|
+
description: 'Whether the dropdown menu should behave as a modal dialog.',
|
|
37
|
+
},
|
|
38
|
+
contentClass: {
|
|
39
|
+
control: 'text',
|
|
40
|
+
description: 'Custom CSS classes to apply to the dropdown menu content container.',
|
|
41
|
+
},
|
|
42
|
+
align: {
|
|
43
|
+
control: 'select',
|
|
44
|
+
options: ['start', 'end', 'center'],
|
|
45
|
+
description: 'Alignment of the dropdown menu relative to the trigger element.',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export default meta
|
|
51
|
+
|
|
52
|
+
type Story = StoryObj<typeof meta>
|
|
53
|
+
|
|
54
|
+
export const Simple: Story = {
|
|
55
|
+
args: {
|
|
56
|
+
items: [
|
|
57
|
+
{
|
|
58
|
+
label: 'Item 1',
|
|
59
|
+
icon: 'i-ph-plus',
|
|
60
|
+
click: () => {},
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
render: args => ({
|
|
65
|
+
components: { DropdownMenu, Button },
|
|
66
|
+
setup() {
|
|
67
|
+
return { args }
|
|
68
|
+
},
|
|
69
|
+
template: '<DropdownMenu v-bind="args"><Button variant="secondary">Click me</Button></DropdownMenu>',
|
|
70
|
+
}),
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export const WithGroups: Story = {
|
|
74
|
+
args: {
|
|
75
|
+
items: [
|
|
76
|
+
{
|
|
77
|
+
label: 'Informe-Laudo-Exame-284321312-2024-01-01.pdf',
|
|
78
|
+
group: 'Output File',
|
|
79
|
+
icon: 'i-ph-file-pdf',
|
|
80
|
+
click: () => {},
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
label: 'Brasíndice Completo',
|
|
84
|
+
group: 'Project Database',
|
|
85
|
+
icon: 'i-ph-file',
|
|
86
|
+
click: () => {},
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
label: 'Tabela SIMPRO 2024',
|
|
90
|
+
group: 'Project Database',
|
|
91
|
+
icon: 'i-ph-file',
|
|
92
|
+
click: () => {},
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
label: 'Acme Saúde Regras',
|
|
96
|
+
group: 'Project Database',
|
|
97
|
+
icon: 'i-ph-file',
|
|
98
|
+
click: () => {},
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
render: args => ({
|
|
103
|
+
components: { DropdownMenu, Button },
|
|
104
|
+
setup() {
|
|
105
|
+
return { args }
|
|
106
|
+
},
|
|
107
|
+
template: '<DropdownMenu v-bind="args"><Button variant="secondary">Click me</Button></DropdownMenu>',
|
|
108
|
+
}),
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export const WithTooltips: Story = {
|
|
112
|
+
args: {
|
|
113
|
+
items: [
|
|
114
|
+
{
|
|
115
|
+
label: 'Download',
|
|
116
|
+
icon: 'i-ph-download-simple-bold',
|
|
117
|
+
click: () => console.log('Download'),
|
|
118
|
+
tooltip: 'Download your files',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
label: 'Share',
|
|
122
|
+
icon: 'i-ph-share-bold',
|
|
123
|
+
click: () => console.log('Share'),
|
|
124
|
+
tooltip: {
|
|
125
|
+
variant: 'multiline',
|
|
126
|
+
title: 'Share with team',
|
|
127
|
+
description: 'Share the selected items with your team members',
|
|
128
|
+
side: 'right',
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
label: 'Delete',
|
|
133
|
+
icon: 'i-ph-trash-bold',
|
|
134
|
+
color: 'negative',
|
|
135
|
+
click: () => console.log('Delete'),
|
|
136
|
+
disabled: true,
|
|
137
|
+
tooltip: {
|
|
138
|
+
variant: 'multiline',
|
|
139
|
+
side: 'top',
|
|
140
|
+
align: 'start',
|
|
141
|
+
title: 'Cannot delete',
|
|
142
|
+
description: 'Some items are protected and cannot be deleted',
|
|
143
|
+
alignOffset: -20,
|
|
144
|
+
arrowOffset: -25,
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
},
|
|
149
|
+
render: args => ({
|
|
150
|
+
components: { DropdownMenu, Button },
|
|
151
|
+
setup() {
|
|
152
|
+
return { args }
|
|
153
|
+
},
|
|
154
|
+
template: '<DropdownMenu v-bind="args"><Button variant="secondary">Actions with Tooltips</Button></DropdownMenu>',
|
|
155
|
+
}),
|
|
156
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const props = defineProps<{
|
|
3
|
+
placeholder?: string
|
|
4
|
+
type?: 'text' | 'textarea'
|
|
5
|
+
readonly?: boolean
|
|
6
|
+
}>()
|
|
7
|
+
|
|
8
|
+
const internalValue = defineModel<string>()
|
|
9
|
+
|
|
10
|
+
const isEditing = ref(false)
|
|
11
|
+
const containerEl = ref<HTMLDivElement | null>()
|
|
12
|
+
const inputEl = ref<HTMLTextAreaElement | null>()
|
|
13
|
+
|
|
14
|
+
const { width: containerWidth } = useElementBounding(containerEl)
|
|
15
|
+
|
|
16
|
+
function onStartEditing() {
|
|
17
|
+
if (props.readonly)
|
|
18
|
+
return
|
|
19
|
+
|
|
20
|
+
isEditing.value = true
|
|
21
|
+
setTimeout(() => {
|
|
22
|
+
inputEl.value?.focus()
|
|
23
|
+
}, 50)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function onStopEditing() {
|
|
27
|
+
isEditing.value = false
|
|
28
|
+
}
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<template>
|
|
32
|
+
<div
|
|
33
|
+
ref="containerEl"
|
|
34
|
+
font-inherit relative outline-none
|
|
35
|
+
:class="[
|
|
36
|
+
isEditing ? 'h-0px' : 'h-24px overflow-hidden truncate text-ellipsis',
|
|
37
|
+
]"
|
|
38
|
+
:cursor="props.readonly ? 'default' : 'pointer'"
|
|
39
|
+
rounded-4px
|
|
40
|
+
px-8px
|
|
41
|
+
mr-24px
|
|
42
|
+
class="hover:bg-gray-200"
|
|
43
|
+
:tabindex="isEditing ? 1 : 0"
|
|
44
|
+
@click="onStartEditing"
|
|
45
|
+
@focus="onStartEditing"
|
|
46
|
+
>
|
|
47
|
+
<div
|
|
48
|
+
:cursor="props.readonly ? 'default' : 'pointer'"
|
|
49
|
+
flex="~" items-center
|
|
50
|
+
:class="[
|
|
51
|
+
isEditing && 'op-0',
|
|
52
|
+
]"
|
|
53
|
+
h-24px
|
|
54
|
+
w-auto
|
|
55
|
+
truncate
|
|
56
|
+
>
|
|
57
|
+
<slot v-if="$slots.label" name="label" :internal-value="internalValue" :placeholder="placeholder" />
|
|
58
|
+
<span
|
|
59
|
+
v-else
|
|
60
|
+
font-inherit
|
|
61
|
+
whitespace-nowrap overflow-hidden text-ellipsis
|
|
62
|
+
z-1
|
|
63
|
+
>
|
|
64
|
+
{{ internalValue || placeholder }}
|
|
65
|
+
</span>
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<textarea
|
|
69
|
+
v-if="isEditing"
|
|
70
|
+
ref="inputEl"
|
|
71
|
+
v-model="internalValue"
|
|
72
|
+
:placeholder="placeholder"
|
|
73
|
+
:style="{ width: `${containerWidth}px`, height: type === 'textarea' ? '100px' : 'auto', overflow: type === 'textarea' ? 'auto' : 'hidden' }"
|
|
74
|
+
absolute
|
|
75
|
+
z-3
|
|
76
|
+
rounded-4px
|
|
77
|
+
top--19.5px
|
|
78
|
+
left--2.5px
|
|
79
|
+
px-10px
|
|
80
|
+
py-10px
|
|
81
|
+
resize-none
|
|
82
|
+
autoresize
|
|
83
|
+
bg-gray-100
|
|
84
|
+
font-inherit
|
|
85
|
+
tabindex="0"
|
|
86
|
+
b=".5 gray-200"
|
|
87
|
+
shadow-flying
|
|
88
|
+
:spellcheck="false"
|
|
89
|
+
v-bind="$attrs"
|
|
90
|
+
@keydown.enter="onStopEditing"
|
|
91
|
+
@blur="onStopEditing"
|
|
92
|
+
@focusleave="onStopEditing"
|
|
93
|
+
@keydown.esc="onStopEditing"
|
|
94
|
+
/>
|
|
95
|
+
</div>
|
|
96
|
+
</template>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { useDropZone } from '@vueuse/core'
|
|
3
|
+
|
|
4
|
+
const props = defineProps<{
|
|
5
|
+
accept?: string[]
|
|
6
|
+
}>()
|
|
7
|
+
|
|
8
|
+
const emit = defineEmits<{
|
|
9
|
+
fileDrop: [files: File[] | null]
|
|
10
|
+
}>()
|
|
11
|
+
|
|
12
|
+
const isOverDropZone = defineModel<boolean>()
|
|
13
|
+
|
|
14
|
+
const dropZoneRef = ref<HTMLElement>()
|
|
15
|
+
|
|
16
|
+
const { isOverDropZone: _isOverDropZone } = useDropZone(dropZoneRef, {
|
|
17
|
+
onDrop,
|
|
18
|
+
// specify the types of data to be received.
|
|
19
|
+
dataTypes: props.accept,
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
watch(_isOverDropZone, (isOver) => {
|
|
23
|
+
isOverDropZone.value = isOver
|
|
24
|
+
}, { immediate: true })
|
|
25
|
+
|
|
26
|
+
function onDrop(files: File[] | null) {
|
|
27
|
+
emit('fileDrop', files)
|
|
28
|
+
}
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<template>
|
|
32
|
+
<div
|
|
33
|
+
ref="dropZoneRef"
|
|
34
|
+
>
|
|
35
|
+
<slot />
|
|
36
|
+
</div>
|
|
37
|
+
</template>
|