@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,268 @@
|
|
|
1
|
+
import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import * as ChatStories from './chat.stories.ts';
|
|
3
|
+
|
|
4
|
+
<Meta of={ChatStories} />
|
|
5
|
+
|
|
6
|
+
# TelaChat
|
|
7
|
+
|
|
8
|
+
A chat component that displays threaded messages with replies, avatars, timestamps, and user information. Supports nested replies, mentions, message threading, and user identification. Useful for chat interfaces, comment systems, and collaborative communication features.
|
|
9
|
+
|
|
10
|
+
## Examples
|
|
11
|
+
|
|
12
|
+
### Empty State
|
|
13
|
+
|
|
14
|
+
<Canvas of={ChatStories.Empty} />
|
|
15
|
+
|
|
16
|
+
### Nested Replies
|
|
17
|
+
|
|
18
|
+
<Canvas of={ChatStories.NestedReplies} />
|
|
19
|
+
|
|
20
|
+
### With Mentions
|
|
21
|
+
|
|
22
|
+
<Canvas of={ChatStories.NestedRepliesWithMentions} />
|
|
23
|
+
|
|
24
|
+
### Long Thread
|
|
25
|
+
|
|
26
|
+
<Canvas of={ChatStories.LongThread} />
|
|
27
|
+
|
|
28
|
+
### Basic Usage
|
|
29
|
+
|
|
30
|
+
```vue
|
|
31
|
+
<script setup>
|
|
32
|
+
import { ref } from 'vue'
|
|
33
|
+
|
|
34
|
+
const messages = ref([
|
|
35
|
+
{
|
|
36
|
+
id: '1',
|
|
37
|
+
content: 'Hello! How can I help you?',
|
|
38
|
+
timestamp: new Date(),
|
|
39
|
+
author: 'Support',
|
|
40
|
+
authorEmail: 'support@example.com'
|
|
41
|
+
}
|
|
42
|
+
])
|
|
43
|
+
|
|
44
|
+
const currentUser = {
|
|
45
|
+
id: '1',
|
|
46
|
+
name: 'John Doe',
|
|
47
|
+
email: 'john@example.com'
|
|
48
|
+
}
|
|
49
|
+
</script>
|
|
50
|
+
|
|
51
|
+
<template>
|
|
52
|
+
<TelaChat
|
|
53
|
+
:messages="messages"
|
|
54
|
+
:current-user="currentUser"
|
|
55
|
+
/>
|
|
56
|
+
</template>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Empty State Code
|
|
60
|
+
|
|
61
|
+
```vue
|
|
62
|
+
<TelaChat
|
|
63
|
+
:messages="[]"
|
|
64
|
+
:current-user="currentUser"
|
|
65
|
+
/>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### With Replies
|
|
69
|
+
|
|
70
|
+
```vue
|
|
71
|
+
<script setup>
|
|
72
|
+
const messages = [{
|
|
73
|
+
id: '1',
|
|
74
|
+
content: 'Main message',
|
|
75
|
+
timestamp: new Date(),
|
|
76
|
+
author: 'User',
|
|
77
|
+
authorEmail: 'user@example.com',
|
|
78
|
+
replies: [
|
|
79
|
+
{
|
|
80
|
+
id: '2',
|
|
81
|
+
content: 'Reply to main message',
|
|
82
|
+
timestamp: new Date(),
|
|
83
|
+
author: 'Other User',
|
|
84
|
+
authorEmail: 'other@example.com'
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
}]
|
|
88
|
+
</script>
|
|
89
|
+
|
|
90
|
+
<template>
|
|
91
|
+
<TelaChat :messages="messages" />
|
|
92
|
+
</template>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Nested Replies Code
|
|
96
|
+
|
|
97
|
+
```vue
|
|
98
|
+
<script setup>
|
|
99
|
+
const messages = [{
|
|
100
|
+
id: '1',
|
|
101
|
+
content: 'Main message',
|
|
102
|
+
timestamp: new Date(),
|
|
103
|
+
author: 'User 1',
|
|
104
|
+
authorEmail: 'user1@example.com',
|
|
105
|
+
replies: [
|
|
106
|
+
{
|
|
107
|
+
id: '2',
|
|
108
|
+
content: 'First reply',
|
|
109
|
+
timestamp: new Date(),
|
|
110
|
+
author: 'User 2',
|
|
111
|
+
authorEmail: 'user2@example.com',
|
|
112
|
+
replies: [
|
|
113
|
+
{
|
|
114
|
+
id: '3',
|
|
115
|
+
content: 'Nested reply',
|
|
116
|
+
timestamp: new Date(),
|
|
117
|
+
author: 'User 3',
|
|
118
|
+
authorEmail: 'user3@example.com'
|
|
119
|
+
}
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
]
|
|
123
|
+
}]
|
|
124
|
+
</script>
|
|
125
|
+
|
|
126
|
+
<template>
|
|
127
|
+
<TelaChat :messages="messages" />
|
|
128
|
+
</template>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### With Mentions Code
|
|
132
|
+
|
|
133
|
+
```vue
|
|
134
|
+
<script setup>
|
|
135
|
+
const messages = [{
|
|
136
|
+
id: '1',
|
|
137
|
+
content: '@jane@example.com Check this out!',
|
|
138
|
+
timestamp: new Date(),
|
|
139
|
+
author: 'John',
|
|
140
|
+
authorEmail: 'john@example.com'
|
|
141
|
+
}]
|
|
142
|
+
|
|
143
|
+
const otherUsers = [{
|
|
144
|
+
id: '2',
|
|
145
|
+
name: 'Jane',
|
|
146
|
+
email: 'jane@example.com'
|
|
147
|
+
}]
|
|
148
|
+
</script>
|
|
149
|
+
|
|
150
|
+
<template>
|
|
151
|
+
<TelaChat
|
|
152
|
+
:messages="messages"
|
|
153
|
+
:other-users="otherUsers"
|
|
154
|
+
/>
|
|
155
|
+
</template>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### With Avatars
|
|
159
|
+
|
|
160
|
+
```vue
|
|
161
|
+
<script setup>
|
|
162
|
+
const messages = [{
|
|
163
|
+
id: '1',
|
|
164
|
+
content: 'Hello!',
|
|
165
|
+
timestamp: new Date(),
|
|
166
|
+
author: 'John Doe',
|
|
167
|
+
authorEmail: 'john@example.com',
|
|
168
|
+
avatarUrl: 'https://example.com/avatar.jpg'
|
|
169
|
+
}]
|
|
170
|
+
</script>
|
|
171
|
+
|
|
172
|
+
<template>
|
|
173
|
+
<TelaChat :messages="messages" />
|
|
174
|
+
</template>
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Props
|
|
178
|
+
|
|
179
|
+
<ArgTypes />
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
type Message = {
|
|
183
|
+
id: string
|
|
184
|
+
content: string
|
|
185
|
+
timestamp: Date
|
|
186
|
+
author: string
|
|
187
|
+
authorEmail: string
|
|
188
|
+
avatarUrl?: string
|
|
189
|
+
version?: string
|
|
190
|
+
replies?: Message[]
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
type User = {
|
|
194
|
+
id: string
|
|
195
|
+
name: string
|
|
196
|
+
email: string
|
|
197
|
+
avatarUrl?: string
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
type ChatProps = {
|
|
201
|
+
messages: Message[]
|
|
202
|
+
currentUser?: User
|
|
203
|
+
otherUsers?: User[]
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Features
|
|
208
|
+
|
|
209
|
+
- **Threaded Messages**: Support for nested replies
|
|
210
|
+
- **User Identification**: Show author names and emails
|
|
211
|
+
- **Avatars**: Display user avatars
|
|
212
|
+
- **Timestamps**: Show when messages were sent
|
|
213
|
+
- **Mentions**: Highlight mentioned users
|
|
214
|
+
- **Version Info**: Show message version (for AI/bot messages)
|
|
215
|
+
- **Empty State**: Graceful handling of no messages
|
|
216
|
+
- **Scrollable**: Scroll through long conversations
|
|
217
|
+
- **Responsive**: Adapts to container size
|
|
218
|
+
|
|
219
|
+
## Message Structure
|
|
220
|
+
|
|
221
|
+
Messages can be nested infinitely:
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
{
|
|
225
|
+
id: '1',
|
|
226
|
+
content: 'Parent message',
|
|
227
|
+
timestamp: new Date(),
|
|
228
|
+
author: 'User',
|
|
229
|
+
authorEmail: 'user@example.com',
|
|
230
|
+
avatarUrl: 'https://...',
|
|
231
|
+
version: 'v1.0',
|
|
232
|
+
replies: [
|
|
233
|
+
{
|
|
234
|
+
id: '2',
|
|
235
|
+
content: 'Child message',
|
|
236
|
+
// ... same structure, can have more replies
|
|
237
|
+
replies: []
|
|
238
|
+
}
|
|
239
|
+
]
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Use Cases
|
|
244
|
+
|
|
245
|
+
- **Chat Applications**: Real-time messaging
|
|
246
|
+
- **Comment Systems**: Threaded discussions
|
|
247
|
+
- **Support Tickets**: Customer support conversations
|
|
248
|
+
- **Collaborative Tools**: Team communication
|
|
249
|
+
- **Review Systems**: Product reviews with replies
|
|
250
|
+
- **Q&A Forums**: Question and answer threads
|
|
251
|
+
|
|
252
|
+
## Best Practices
|
|
253
|
+
|
|
254
|
+
1. **Load Messages Lazily**: Paginate long conversations
|
|
255
|
+
2. **Show Timestamps**: Help users track conversation flow
|
|
256
|
+
3. **Highlight Mentions**: Make @mentions stand out
|
|
257
|
+
4. **Limit Nesting Depth**: Avoid deep nesting (max 3-4 levels)
|
|
258
|
+
5. **Provide Reply UI**: Add buttons to reply to messages
|
|
259
|
+
6. **Real-time Updates**: Use WebSockets for live updates
|
|
260
|
+
|
|
261
|
+
## Accessibility
|
|
262
|
+
|
|
263
|
+
- Semantic HTML structure
|
|
264
|
+
- Proper heading hierarchy
|
|
265
|
+
- ARIA labels for avatars
|
|
266
|
+
- Keyboard navigation
|
|
267
|
+
- Screen reader friendly timestamps
|
|
268
|
+
- Focus management for replies
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
|
+
import TelaChat from './index.vue'
|
|
3
|
+
import type { Message } from './types'
|
|
4
|
+
|
|
5
|
+
const mockMessages: Message[] = [
|
|
6
|
+
{
|
|
7
|
+
id: '1',
|
|
8
|
+
content: 'Hello! How can I help you today?',
|
|
9
|
+
timestamp: new Date('2024-03-20T10:00:00'),
|
|
10
|
+
authorEmail: 'ai.assistant@example.com',
|
|
11
|
+
author: 'AI Assistant',
|
|
12
|
+
avatarUrl: 'https://api.dicebear.com/7.x/bottts/svg?seed=1',
|
|
13
|
+
version: 'v1.0',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
id: '2',
|
|
17
|
+
content: 'I have a question about the API integration.',
|
|
18
|
+
timestamp: new Date('2024-03-20T10:01:00'),
|
|
19
|
+
authorEmail: 'john.doe@example.com',
|
|
20
|
+
author: 'John Doe',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
id: '3',
|
|
24
|
+
content: 'Sure, I can help with that. What specific aspect of the API integration would you like to know about?',
|
|
25
|
+
timestamp: new Date('2024-03-20T10:02:00'),
|
|
26
|
+
authorEmail: 'ai.assistant@example.com',
|
|
27
|
+
author: 'AI Assistant',
|
|
28
|
+
avatarUrl: 'https://api.dicebear.com/7.x/bottts/svg?seed=1',
|
|
29
|
+
version: 'v1.0',
|
|
30
|
+
replies: [
|
|
31
|
+
{
|
|
32
|
+
id: '4',
|
|
33
|
+
content: 'I\'m wondering about authentication methods.',
|
|
34
|
+
timestamp: new Date('2024-03-20T10:03:00'),
|
|
35
|
+
authorEmail: 'john.doe@example.com',
|
|
36
|
+
author: 'John Doe',
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
const meta = {
|
|
43
|
+
title: 'Tela/Chat',
|
|
44
|
+
component: TelaChat,
|
|
45
|
+
parameters: {
|
|
46
|
+
layout: 'centered',
|
|
47
|
+
docs: {
|
|
48
|
+
description: {
|
|
49
|
+
component: 'A chat component that displays threaded messages with replies, avatars, timestamps, and user information. Supports nested replies, mentions, message threading, and user identification. Useful for chat interfaces, comment systems, and collaborative communication features.',
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
argTypes: {
|
|
54
|
+
messages: {
|
|
55
|
+
control: 'object',
|
|
56
|
+
description: 'Array of message objects. Each message should have `id`, `content`, `timestamp`, `author`, `authorEmail`, and optionally `avatarUrl`, `version`, and `replies` (nested messages) properties.',
|
|
57
|
+
},
|
|
58
|
+
currentUser: {
|
|
59
|
+
control: 'object',
|
|
60
|
+
description: 'Current user object with `id`, `name`, `email`, and optionally `avatarUrl` properties.',
|
|
61
|
+
},
|
|
62
|
+
otherUsers: {
|
|
63
|
+
control: 'object',
|
|
64
|
+
description: 'Array of other user objects for mentions and user identification.',
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
args: {
|
|
68
|
+
messages: mockMessages,
|
|
69
|
+
},
|
|
70
|
+
} satisfies Meta<typeof TelaChat>
|
|
71
|
+
|
|
72
|
+
export default meta
|
|
73
|
+
type Story = StoryObj<typeof meta>
|
|
74
|
+
|
|
75
|
+
export const Default: Story = {
|
|
76
|
+
args: {
|
|
77
|
+
messages: mockMessages,
|
|
78
|
+
currentUser: {
|
|
79
|
+
id: '1',
|
|
80
|
+
name: 'John Doe',
|
|
81
|
+
email: 'john.doe@example.com',
|
|
82
|
+
avatarUrl: 'https://api.dicebear.com/7.x/bottts/svg?seed=1',
|
|
83
|
+
},
|
|
84
|
+
otherUsers: [
|
|
85
|
+
{
|
|
86
|
+
id: '2',
|
|
87
|
+
name: 'Jane Doe',
|
|
88
|
+
email: 'jane.doe@example.com',
|
|
89
|
+
avatarUrl: 'https://api.dicebear.com/7.x/bottts/svg?seed=2',
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export const Empty: Story = {
|
|
96
|
+
args: {
|
|
97
|
+
messages: [],
|
|
98
|
+
currentUser: {
|
|
99
|
+
id: '1',
|
|
100
|
+
name: 'John Doe',
|
|
101
|
+
email: 'john.doe@example.com',
|
|
102
|
+
avatarUrl: 'https://api.dicebear.com/7.x/bottts/svg?seed=1',
|
|
103
|
+
},
|
|
104
|
+
otherUsers: [],
|
|
105
|
+
},
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export const LongThread: Story = {
|
|
109
|
+
args: {
|
|
110
|
+
messages: [
|
|
111
|
+
...mockMessages,
|
|
112
|
+
{
|
|
113
|
+
id: '5',
|
|
114
|
+
content: 'Here\'s a detailed explanation of our authentication methods...',
|
|
115
|
+
timestamp: new Date('2024-03-20T10:04:00'),
|
|
116
|
+
author: 'AI Assistant',
|
|
117
|
+
authorEmail: 'ai.assistant@example.com',
|
|
118
|
+
avatarUrl: 'https://api.dicebear.com/7.x/bottts/svg?seed=1',
|
|
119
|
+
version: 'v1.0',
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: '6',
|
|
123
|
+
content: 'Thanks! That\'s very helpful.',
|
|
124
|
+
timestamp: new Date('2024-03-20T10:05:00'),
|
|
125
|
+
authorEmail: 'john.doe@example.com',
|
|
126
|
+
author: 'John Doe',
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
currentUser: {
|
|
130
|
+
id: '1',
|
|
131
|
+
name: 'John Doe',
|
|
132
|
+
email: 'john.doe@example.com',
|
|
133
|
+
avatarUrl: 'https://api.dicebear.com/7.x/bottts/svg?seed=1',
|
|
134
|
+
},
|
|
135
|
+
otherUsers: [],
|
|
136
|
+
},
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export const NestedReplies: Story = {
|
|
140
|
+
args: {
|
|
141
|
+
messages: [
|
|
142
|
+
{
|
|
143
|
+
id: '1',
|
|
144
|
+
content: 'Main message',
|
|
145
|
+
timestamp: new Date('2024-03-20T10:00:00'),
|
|
146
|
+
author: 'AI Assistant',
|
|
147
|
+
authorEmail: 'ai.assistant@example.com',
|
|
148
|
+
avatarUrl: 'https://api.dicebear.com/7.x/bottts/svg?seed=1',
|
|
149
|
+
version: 'v1.0',
|
|
150
|
+
replies: [
|
|
151
|
+
{
|
|
152
|
+
id: '2',
|
|
153
|
+
content: 'First reply',
|
|
154
|
+
timestamp: new Date('2024-03-20T10:01:00'),
|
|
155
|
+
authorEmail: 'john.doe@example.com',
|
|
156
|
+
author: 'John Doe',
|
|
157
|
+
replies: [
|
|
158
|
+
{
|
|
159
|
+
id: '3',
|
|
160
|
+
content: 'Nested reply',
|
|
161
|
+
timestamp: new Date('2024-03-20T10:02:00'),
|
|
162
|
+
author: 'AI Assistant',
|
|
163
|
+
authorEmail: 'ai.assistant@example.com',
|
|
164
|
+
avatarUrl: 'https://api.dicebear.com/7.x/bottts/svg?seed=1',
|
|
165
|
+
version: 'v1.0',
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
currentUser: {
|
|
173
|
+
id: '1',
|
|
174
|
+
name: 'John Doe',
|
|
175
|
+
email: 'john.doe@example.com',
|
|
176
|
+
avatarUrl: 'https://api.dicebear.com/7.x/bottts/svg?seed=1',
|
|
177
|
+
},
|
|
178
|
+
otherUsers: [],
|
|
179
|
+
},
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export const NestedRepliesWithButton: Story = {
|
|
183
|
+
args: {
|
|
184
|
+
messages: [
|
|
185
|
+
{
|
|
186
|
+
id: '1',
|
|
187
|
+
content: 'Main message',
|
|
188
|
+
timestamp: new Date('2024-03-20T10:00:00'),
|
|
189
|
+
author: 'AI Assistant',
|
|
190
|
+
authorEmail: 'ai.assistant@example.com',
|
|
191
|
+
avatarUrl: 'https://api.dicebear.com/7.x/bottts/svg?seed=1',
|
|
192
|
+
version: 'v1.0',
|
|
193
|
+
replies: [
|
|
194
|
+
{
|
|
195
|
+
id: '2',
|
|
196
|
+
content: 'First reply',
|
|
197
|
+
timestamp: new Date('2024-03-20T10:01:00'),
|
|
198
|
+
authorEmail: 'john.doe@example.com',
|
|
199
|
+
author: 'John Doe',
|
|
200
|
+
replies: [],
|
|
201
|
+
},
|
|
202
|
+
],
|
|
203
|
+
},
|
|
204
|
+
],
|
|
205
|
+
currentUser: {
|
|
206
|
+
id: '1',
|
|
207
|
+
name: 'John Doe',
|
|
208
|
+
email: 'john.doe@example.com',
|
|
209
|
+
avatarUrl: 'https://api.dicebear.com/7.x/bottts/svg?seed=1',
|
|
210
|
+
},
|
|
211
|
+
otherUsers: [],
|
|
212
|
+
},
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export const NestedRepliesWithMentions: Story = {
|
|
216
|
+
args: {
|
|
217
|
+
messages: [
|
|
218
|
+
{
|
|
219
|
+
id: '1',
|
|
220
|
+
content: 'Main message',
|
|
221
|
+
timestamp: new Date('2024-03-20T10:00:00'),
|
|
222
|
+
author: 'AI Assistant',
|
|
223
|
+
authorEmail: 'ai.assistant@example.com',
|
|
224
|
+
avatarUrl: 'https://api.dicebear.com/7.x/bottts/svg?seed=1',
|
|
225
|
+
version: 'v1.0',
|
|
226
|
+
replies: [
|
|
227
|
+
{
|
|
228
|
+
id: '2',
|
|
229
|
+
content: '@jane.doe@example.com... This is a reply to the main message.',
|
|
230
|
+
timestamp: new Date('2024-03-20T10:01:00'),
|
|
231
|
+
authorEmail: 'jane.doe@example.com',
|
|
232
|
+
author: 'You',
|
|
233
|
+
replies: [],
|
|
234
|
+
},
|
|
235
|
+
],
|
|
236
|
+
},
|
|
237
|
+
],
|
|
238
|
+
currentUser: {
|
|
239
|
+
id: '1',
|
|
240
|
+
name: 'John Doe',
|
|
241
|
+
email: 'john.doe@example.com',
|
|
242
|
+
avatarUrl: 'https://api.dicebear.com/7.x/bottts/svg?seed=1',
|
|
243
|
+
},
|
|
244
|
+
otherUsers: [
|
|
245
|
+
{
|
|
246
|
+
id: '2',
|
|
247
|
+
name: 'Jane Doe',
|
|
248
|
+
email: 'jane.doe@example.com',
|
|
249
|
+
avatarUrl: 'https://api.dicebear.com/7.x/bottts/svg?seed=2',
|
|
250
|
+
},
|
|
251
|
+
],
|
|
252
|
+
},
|
|
253
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { User } from '../types'
|
|
3
|
+
|
|
4
|
+
type CommandType = '@'
|
|
5
|
+
|
|
6
|
+
interface BaseCommandProps {
|
|
7
|
+
isOpen: boolean
|
|
8
|
+
onClose: () => void
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface MentionProps extends BaseCommandProps {
|
|
12
|
+
chatMessage: string
|
|
13
|
+
members: User[]
|
|
14
|
+
onSelect: (user: User) => void
|
|
15
|
+
searchTerm: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type CommandProps = {
|
|
19
|
+
commands: CommandType[]
|
|
20
|
+
mentionProps?: MentionProps
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const props = withDefaults(defineProps<CommandProps>(), {
|
|
24
|
+
mentionProps: undefined,
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
const hasMention = computed(() => props.commands.includes('@'))
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<template>
|
|
31
|
+
<div>
|
|
32
|
+
<TelaChatCommandMention
|
|
33
|
+
v-if="hasMention"
|
|
34
|
+
v-bind="mentionProps"
|
|
35
|
+
>
|
|
36
|
+
<template #trigger>
|
|
37
|
+
<slot name="mention" />
|
|
38
|
+
</template>
|
|
39
|
+
</TelaChatCommandMention>
|
|
40
|
+
</div>
|
|
41
|
+
</template>
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { User } from '../../types'
|
|
3
|
+
import { onClickOutside } from '@vueuse/core'
|
|
4
|
+
|
|
5
|
+
const props = defineProps<{
|
|
6
|
+
members: User[]
|
|
7
|
+
chatMessage: string
|
|
8
|
+
isOpen: boolean
|
|
9
|
+
searchTerm: string
|
|
10
|
+
}>()
|
|
11
|
+
|
|
12
|
+
const emit = defineEmits<{
|
|
13
|
+
(e: 'close'): void
|
|
14
|
+
(e: 'select', user: User): void
|
|
15
|
+
}>()
|
|
16
|
+
|
|
17
|
+
const filteredUsers = computed(() => {
|
|
18
|
+
const isValidArray = Array.isArray(props.members) && props.members.length > 0
|
|
19
|
+
const hasInsufficientLength = props.searchTerm.length < 3
|
|
20
|
+
if (!isValidArray || hasInsufficientLength)
|
|
21
|
+
return props.members
|
|
22
|
+
|
|
23
|
+
const searchTerm = props.searchTerm.replace('@', '').toLowerCase()
|
|
24
|
+
return props.members?.filter((user) => {
|
|
25
|
+
const name = user.name.toLowerCase()
|
|
26
|
+
const email = user.email.toLowerCase()
|
|
27
|
+
return name.includes(searchTerm) || email.includes(searchTerm)
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
const isVisible = computed(() => props.isOpen && filteredUsers.value.length > 0)
|
|
31
|
+
|
|
32
|
+
const dropdownRef = ref<HTMLElement | null>(null)
|
|
33
|
+
onClickOutside(dropdownRef, () => {
|
|
34
|
+
if (props.isOpen) {
|
|
35
|
+
emit('close')
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
const selectedIndex = ref(0)
|
|
39
|
+
|
|
40
|
+
// Handle keyboard navigation
|
|
41
|
+
function handleKeydown(e: KeyboardEvent) {
|
|
42
|
+
if (!isVisible.value)
|
|
43
|
+
return
|
|
44
|
+
|
|
45
|
+
switch (e.key) {
|
|
46
|
+
case 'ArrowDown':
|
|
47
|
+
e.preventDefault()
|
|
48
|
+
selectedIndex.value = (selectedIndex.value + 1) % filteredUsers.value.length
|
|
49
|
+
break
|
|
50
|
+
case 'ArrowUp':
|
|
51
|
+
e.preventDefault()
|
|
52
|
+
selectedIndex.value = selectedIndex.value - 1 < 0
|
|
53
|
+
? filteredUsers.value.length - 1
|
|
54
|
+
: selectedIndex.value - 1
|
|
55
|
+
break
|
|
56
|
+
case 'Enter':
|
|
57
|
+
e.preventDefault()
|
|
58
|
+
if (filteredUsers.value[selectedIndex.value]) {
|
|
59
|
+
emit('select', filteredUsers.value[selectedIndex.value])
|
|
60
|
+
}
|
|
61
|
+
break
|
|
62
|
+
case 'Escape':
|
|
63
|
+
e.preventDefault()
|
|
64
|
+
emit('close')
|
|
65
|
+
break
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Add keyboard event listener
|
|
70
|
+
onMounted(() => {
|
|
71
|
+
window.addEventListener('keydown', handleKeydown)
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
onUnmounted(() => {
|
|
75
|
+
window.removeEventListener('keydown', handleKeydown)
|
|
76
|
+
})
|
|
77
|
+
</script>
|
|
78
|
+
|
|
79
|
+
<template>
|
|
80
|
+
<slot name="trigger" />
|
|
81
|
+
<Transition name="fade">
|
|
82
|
+
<div
|
|
83
|
+
v-if="isVisible"
|
|
84
|
+
ref="dropdownRef"
|
|
85
|
+
bg-white
|
|
86
|
+
shadow-flying
|
|
87
|
+
rounded-10px
|
|
88
|
+
p-4px
|
|
89
|
+
text-gray-800
|
|
90
|
+
flex="~ col"
|
|
91
|
+
w-244px
|
|
92
|
+
absolute
|
|
93
|
+
top-full
|
|
94
|
+
left-0
|
|
95
|
+
z-10000
|
|
96
|
+
>
|
|
97
|
+
<div
|
|
98
|
+
v-for="(member, index) in filteredUsers"
|
|
99
|
+
:key="member.id"
|
|
100
|
+
py-9px
|
|
101
|
+
px-12px
|
|
102
|
+
transition
|
|
103
|
+
ease
|
|
104
|
+
text-left
|
|
105
|
+
flex
|
|
106
|
+
items-center
|
|
107
|
+
gap-12px
|
|
108
|
+
rounded-8px
|
|
109
|
+
hover="bg-gray-200"
|
|
110
|
+
:class="{ 'bg-gray-200': index === selectedIndex }"
|
|
111
|
+
cursor-pointer
|
|
112
|
+
@click="$emit('select', member)"
|
|
113
|
+
>
|
|
114
|
+
<TelaAvatar :src="member.avatarUrl" size="sm" />
|
|
115
|
+
<div flex="~ col" gap-3px text-14px>
|
|
116
|
+
<div body-12-semibold>
|
|
117
|
+
{{ member.name }}
|
|
118
|
+
</div>
|
|
119
|
+
<div text-xs text-gray-500>
|
|
120
|
+
{{ member.email }}
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
</Transition>
|
|
126
|
+
</template>
|
|
127
|
+
|
|
128
|
+
<style scoped>
|
|
129
|
+
.fade-enter-active,
|
|
130
|
+
.fade-leave-active {
|
|
131
|
+
transition: opacity 0.2s ease;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.fade-enter-from,
|
|
135
|
+
.fade-leave-to {
|
|
136
|
+
opacity: 0;
|
|
137
|
+
}
|
|
138
|
+
</style>
|