@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
package/README.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Nuxt 3 Minimal Starter
|
|
2
|
+
|
|
3
|
+
Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
Make sure to install the dependencies:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# npm
|
|
11
|
+
npm install
|
|
12
|
+
|
|
13
|
+
# pnpm
|
|
14
|
+
pnpm install
|
|
15
|
+
|
|
16
|
+
# yarn
|
|
17
|
+
yarn install
|
|
18
|
+
|
|
19
|
+
# bun
|
|
20
|
+
bun install
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Development Server
|
|
24
|
+
|
|
25
|
+
Start the development server on `http://localhost:3000`:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# npm
|
|
29
|
+
npm run dev
|
|
30
|
+
|
|
31
|
+
# pnpm
|
|
32
|
+
pnpm run dev
|
|
33
|
+
|
|
34
|
+
# yarn
|
|
35
|
+
yarn dev
|
|
36
|
+
|
|
37
|
+
# bun
|
|
38
|
+
bun run dev
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Production
|
|
42
|
+
|
|
43
|
+
Build the application for production:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# npm
|
|
47
|
+
npm run build
|
|
48
|
+
|
|
49
|
+
# pnpm
|
|
50
|
+
pnpm run build
|
|
51
|
+
|
|
52
|
+
# yarn
|
|
53
|
+
yarn build
|
|
54
|
+
|
|
55
|
+
# bun
|
|
56
|
+
bun run build
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Locally preview production build:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# npm
|
|
63
|
+
npm run preview
|
|
64
|
+
|
|
65
|
+
# pnpm
|
|
66
|
+
pnpm run preview
|
|
67
|
+
|
|
68
|
+
# yarn
|
|
69
|
+
yarn preview
|
|
70
|
+
|
|
71
|
+
# bun
|
|
72
|
+
bun run preview
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
|
package/app.config.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
export default defineAppConfig({
|
|
2
|
+
ui: {
|
|
3
|
+
primary: 'black',
|
|
4
|
+
selectMenu: {
|
|
5
|
+
rounded: 'rounded-8px',
|
|
6
|
+
ring: 'ring-0 b-1 b-gray-200',
|
|
7
|
+
background: '!bg-red',
|
|
8
|
+
},
|
|
9
|
+
button: {
|
|
10
|
+
variant: {
|
|
11
|
+
solid: 'text-black bg-white shadow-none b-1 b-#EDEDED hover:bg-#F7F7F7 hover:b-#DEDEDE transition disabled:bg-white disabled:cursor-not-allowed ',
|
|
12
|
+
},
|
|
13
|
+
size: {
|
|
14
|
+
'2xs': 'text-xs',
|
|
15
|
+
'xs': 'text-xs',
|
|
16
|
+
'sm': 'text-[13px] h-32px',
|
|
17
|
+
'md': 'text-[13px] h-40px',
|
|
18
|
+
'lg': 'text-sm',
|
|
19
|
+
'xl': 'text-base',
|
|
20
|
+
},
|
|
21
|
+
padding: {
|
|
22
|
+
md: '!px-16px !py-15px',
|
|
23
|
+
},
|
|
24
|
+
default: {
|
|
25
|
+
size: 'md',
|
|
26
|
+
variant: 'solid',
|
|
27
|
+
color: 'primary',
|
|
28
|
+
loadingIcon: 'i-ph-arrows-clockwise',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
input: {
|
|
32
|
+
base: '!ring-0 !shadow-none !bg-pink',
|
|
33
|
+
padding: {
|
|
34
|
+
sm: '!pb-50px',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
modal: {
|
|
38
|
+
container: 'flex min-h-full items-center sm:items-center justify-center text-center',
|
|
39
|
+
},
|
|
40
|
+
notifications: {
|
|
41
|
+
position: 'right-0',
|
|
42
|
+
width: 'sm:!w-[420px]',
|
|
43
|
+
},
|
|
44
|
+
notification: {
|
|
45
|
+
background: '!bg-[#031E22]',
|
|
46
|
+
container: 'b-1 b-[#01292F/08]',
|
|
47
|
+
rounded: 'rounded-8px',
|
|
48
|
+
title: 'text-16px text-white font-semibold tracking--0.01em leading-20px',
|
|
49
|
+
description: 'text-14px text-white/60 leading-1.08em',
|
|
50
|
+
ring: 'ring-0',
|
|
51
|
+
},
|
|
52
|
+
toggle: {
|
|
53
|
+
container: {
|
|
54
|
+
base: 'pointer-events-none relative inline-block h-4 w-4 rounded-full bg-white dark:bg-gray-900 shadow ring-0 transition ease-in-out duration-200',
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
tooltip: {
|
|
58
|
+
popper: {
|
|
59
|
+
arrow: true,
|
|
60
|
+
|
|
61
|
+
},
|
|
62
|
+
rounded: 'rounded-full',
|
|
63
|
+
arrow: {
|
|
64
|
+
ring: 'before:ring-[#000000]',
|
|
65
|
+
background: 'before:!bg-[#000000]',
|
|
66
|
+
},
|
|
67
|
+
background: '!bg-[#01292F]',
|
|
68
|
+
ring: '!ring-1 !ring-black',
|
|
69
|
+
base: '[@media(pointer:coarse)]:hidden h-6 px-12px py-4px truncate relative text-10px font-semibold !text-white',
|
|
70
|
+
shadow: 'shadow-none',
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
})
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const props = defineProps<{ value: number | null; min: number; max: number }>()
|
|
3
|
+
const currentNumber = ref(props.value)
|
|
4
|
+
|
|
5
|
+
const timer = setInterval(() => {
|
|
6
|
+
currentNumber.value = Math.floor(Math.random() * (props.max - props.min) + props.min)
|
|
7
|
+
}, 350)
|
|
8
|
+
|
|
9
|
+
onUnmounted(() => {
|
|
10
|
+
clearInterval(timer)
|
|
11
|
+
})
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<template>
|
|
15
|
+
<TelaAnimatedValue :value="value !== null ? value : currentNumber" />
|
|
16
|
+
</template>
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import * as AnimatedNumberStories from './animated-number.stories.ts';
|
|
3
|
+
|
|
4
|
+
<Meta of={AnimatedNumberStories} />
|
|
5
|
+
|
|
6
|
+
# TelaAnimatedNumber
|
|
7
|
+
|
|
8
|
+
An animated number component that smoothly animates number changes with counting effects. Supports currency formatting, decimal precision, and locale customization. Useful for displaying metrics, statistics, or financial data with engaging animations.
|
|
9
|
+
|
|
10
|
+
## Examples
|
|
11
|
+
|
|
12
|
+
### With Currency
|
|
13
|
+
|
|
14
|
+
<Canvas of={AnimatedNumberStories.WithCurrency} />
|
|
15
|
+
|
|
16
|
+
### Basic Usage
|
|
17
|
+
|
|
18
|
+
```vue
|
|
19
|
+
<script setup>
|
|
20
|
+
import { ref } from 'vue'
|
|
21
|
+
|
|
22
|
+
const count = ref(0)
|
|
23
|
+
|
|
24
|
+
const increment = () => {
|
|
25
|
+
count.value += 100
|
|
26
|
+
}
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<template>
|
|
30
|
+
<div>
|
|
31
|
+
<TelaAnimatedNumber :value="count" />
|
|
32
|
+
<TelaButton @click="increment">Increment</TelaButton>
|
|
33
|
+
</div>
|
|
34
|
+
</template>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### With Currency Code Examples
|
|
38
|
+
|
|
39
|
+
```vue
|
|
40
|
+
<TelaAnimatedNumber
|
|
41
|
+
:value="123456.78"
|
|
42
|
+
currency="USD"
|
|
43
|
+
:locales="['en-US']"
|
|
44
|
+
/>
|
|
45
|
+
<!-- Output: $123,456.78 -->
|
|
46
|
+
|
|
47
|
+
<TelaAnimatedNumber
|
|
48
|
+
:value="123456.78"
|
|
49
|
+
currency="BRL"
|
|
50
|
+
:locales="['pt-BR']"
|
|
51
|
+
/>
|
|
52
|
+
<!-- Output: R$ 123.456,78 -->
|
|
53
|
+
|
|
54
|
+
<TelaAnimatedNumber
|
|
55
|
+
:value="123456.78"
|
|
56
|
+
currency="EUR"
|
|
57
|
+
:locales="['de-DE']"
|
|
58
|
+
/>
|
|
59
|
+
<!-- Output: 123.456,78 € -->
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### With Precision
|
|
63
|
+
|
|
64
|
+
```vue
|
|
65
|
+
<!-- 2 decimal places -->
|
|
66
|
+
<TelaAnimatedNumber
|
|
67
|
+
:value="123.456789"
|
|
68
|
+
:precision="2"
|
|
69
|
+
/>
|
|
70
|
+
<!-- Output: 123.46 -->
|
|
71
|
+
|
|
72
|
+
<!-- No decimal places -->
|
|
73
|
+
<TelaAnimatedNumber
|
|
74
|
+
:value="123.456789"
|
|
75
|
+
:precision="0"
|
|
76
|
+
/>
|
|
77
|
+
<!-- Output: 123 -->
|
|
78
|
+
|
|
79
|
+
<!-- 4 decimal places -->
|
|
80
|
+
<TelaAnimatedNumber
|
|
81
|
+
:value="123.456789"
|
|
82
|
+
:precision="4"
|
|
83
|
+
/>
|
|
84
|
+
<!-- Output: 123.4568 -->
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Counter Example
|
|
88
|
+
|
|
89
|
+
```vue
|
|
90
|
+
<script setup>
|
|
91
|
+
import { ref } from 'vue'
|
|
92
|
+
|
|
93
|
+
const visitors = ref(1234)
|
|
94
|
+
|
|
95
|
+
setInterval(() => {
|
|
96
|
+
visitors.value += Math.floor(Math.random() * 10)
|
|
97
|
+
}, 2000)
|
|
98
|
+
</script>
|
|
99
|
+
|
|
100
|
+
<template>
|
|
101
|
+
<div>
|
|
102
|
+
<div class="text-4xl font-bold">
|
|
103
|
+
<TelaAnimatedNumber :value="visitors" />
|
|
104
|
+
</div>
|
|
105
|
+
<div class="text-sm text-gray-600">
|
|
106
|
+
Active visitors
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
</template>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Sales Dashboard
|
|
113
|
+
|
|
114
|
+
```vue
|
|
115
|
+
<script setup>
|
|
116
|
+
import { ref } from 'vue'
|
|
117
|
+
|
|
118
|
+
const revenue = ref(45678.90)
|
|
119
|
+
const orders = ref(234)
|
|
120
|
+
const conversion = ref(3.45)
|
|
121
|
+
</script>
|
|
122
|
+
|
|
123
|
+
<template>
|
|
124
|
+
<div class="grid grid-cols-3 gap-4">
|
|
125
|
+
<div class="p-4 bg-white rounded shadow">
|
|
126
|
+
<div class="text-2xl font-bold">
|
|
127
|
+
<TelaAnimatedNumber
|
|
128
|
+
:value="revenue"
|
|
129
|
+
currency="USD"
|
|
130
|
+
:locales="['en-US']"
|
|
131
|
+
/>
|
|
132
|
+
</div>
|
|
133
|
+
<div class="text-sm text-gray-600">Total Revenue</div>
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
<div class="p-4 bg-white rounded shadow">
|
|
137
|
+
<div class="text-2xl font-bold">
|
|
138
|
+
<TelaAnimatedNumber :value="orders" />
|
|
139
|
+
</div>
|
|
140
|
+
<div class="text-sm text-gray-600">Orders</div>
|
|
141
|
+
</div>
|
|
142
|
+
|
|
143
|
+
<div class="p-4 bg-white rounded shadow">
|
|
144
|
+
<div class="text-2xl font-bold">
|
|
145
|
+
<TelaAnimatedNumber
|
|
146
|
+
:value="conversion"
|
|
147
|
+
:precision="2"
|
|
148
|
+
/>%
|
|
149
|
+
</div>
|
|
150
|
+
<div class="text-sm text-gray-600">Conversion Rate</div>
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
</template>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Different Locales
|
|
157
|
+
|
|
158
|
+
```vue
|
|
159
|
+
<!-- US Format -->
|
|
160
|
+
<TelaAnimatedNumber
|
|
161
|
+
:value="1234567.89"
|
|
162
|
+
:locales="['en-US']"
|
|
163
|
+
/>
|
|
164
|
+
<!-- Output: 1,234,567.89 -->
|
|
165
|
+
|
|
166
|
+
<!-- Brazilian Format -->
|
|
167
|
+
<TelaAnimatedNumber
|
|
168
|
+
:value="1234567.89"
|
|
169
|
+
:locales="['pt-BR']"
|
|
170
|
+
/>
|
|
171
|
+
<!-- Output: 1.234.567,89 -->
|
|
172
|
+
|
|
173
|
+
<!-- German Format -->
|
|
174
|
+
<TelaAnimatedNumber
|
|
175
|
+
:value="1234567.89"
|
|
176
|
+
:locales="['de-DE']"
|
|
177
|
+
/>
|
|
178
|
+
<!-- Output: 1.234.567,89 -->
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Props
|
|
182
|
+
|
|
183
|
+
<ArgTypes />
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
type AnimatedNumberProps = {
|
|
187
|
+
value: number
|
|
188
|
+
precision?: number
|
|
189
|
+
currency?: string
|
|
190
|
+
locales?: string[]
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Features
|
|
195
|
+
|
|
196
|
+
- **Smooth Animation**: Numbers count up/down smoothly
|
|
197
|
+
- **Currency Formatting**: Support for all currency codes
|
|
198
|
+
- **Locale Support**: Format according to different locales
|
|
199
|
+
- **Precision Control**: Set decimal places
|
|
200
|
+
- **Performance**: Optimized for rapid updates
|
|
201
|
+
- **Direction**: Automatically counts up or down
|
|
202
|
+
|
|
203
|
+
## Currency Codes
|
|
204
|
+
|
|
205
|
+
Common currency codes:
|
|
206
|
+
- USD - US Dollar
|
|
207
|
+
- EUR - Euro
|
|
208
|
+
- GBP - British Pound
|
|
209
|
+
- BRL - Brazilian Real
|
|
210
|
+
- JPY - Japanese Yen
|
|
211
|
+
- CNY - Chinese Yuan
|
|
212
|
+
- INR - Indian Rupee
|
|
213
|
+
|
|
214
|
+
## Locale Codes
|
|
215
|
+
|
|
216
|
+
Common locale codes:
|
|
217
|
+
- en-US - English (US)
|
|
218
|
+
- en-GB - English (UK)
|
|
219
|
+
- pt-BR - Portuguese (Brazil)
|
|
220
|
+
- es-ES - Spanish (Spain)
|
|
221
|
+
- fr-FR - French (France)
|
|
222
|
+
- de-DE - German (Germany)
|
|
223
|
+
- ja-JP - Japanese (Japan)
|
|
224
|
+
- zh-CN - Chinese (China)
|
|
225
|
+
|
|
226
|
+
## Use Cases
|
|
227
|
+
|
|
228
|
+
- **Dashboards**: Display real-time metrics
|
|
229
|
+
- **Statistics**: Animated counters for stats
|
|
230
|
+
- **Financial Data**: Show monetary values
|
|
231
|
+
- **Analytics**: User counts, page views
|
|
232
|
+
- **E-commerce**: Sales figures, revenue
|
|
233
|
+
- **Gaming**: Scores, points, levels
|
|
234
|
+
|
|
235
|
+
## Best Practices
|
|
236
|
+
|
|
237
|
+
1. **Set Appropriate Precision**: Use 2 decimals for currency
|
|
238
|
+
2. **Match Locale to Currency**: Use correct locale for currency
|
|
239
|
+
3. **Avoid Rapid Changes**: Limit update frequency
|
|
240
|
+
4. **Provide Context**: Label what the number represents
|
|
241
|
+
5. **Consider Performance**: Limit simultaneous animations
|
|
242
|
+
|
|
243
|
+
## Accessibility
|
|
244
|
+
|
|
245
|
+
- Numbers are readable by screen readers
|
|
246
|
+
- Provide context with labels
|
|
247
|
+
- Ensure sufficient color contrast
|
|
248
|
+
- Animation can be disabled via CSS
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
|
+
|
|
3
|
+
import AnimatedNumber from './animated-number.vue'
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof AnimatedNumber> = {
|
|
6
|
+
title: 'Core/Animated Number',
|
|
7
|
+
component: AnimatedNumber,
|
|
8
|
+
parameters: {
|
|
9
|
+
layout: 'centered',
|
|
10
|
+
docs: {
|
|
11
|
+
description: {
|
|
12
|
+
component: 'An animated number component that smoothly animates number changes with counting effects. Supports currency formatting, decimal precision, and locale customization. Useful for displaying metrics, statistics, or financial data with engaging animations.',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
argTypes: {
|
|
17
|
+
value: {
|
|
18
|
+
control: 'number',
|
|
19
|
+
description: 'The numeric value to display and animate.',
|
|
20
|
+
},
|
|
21
|
+
precision: {
|
|
22
|
+
control: 'number',
|
|
23
|
+
description: 'Number of decimal places to display.',
|
|
24
|
+
},
|
|
25
|
+
currency: {
|
|
26
|
+
control: 'text',
|
|
27
|
+
description: 'Currency code (e.g., "USD", "BRL") for currency formatting.',
|
|
28
|
+
},
|
|
29
|
+
locales: {
|
|
30
|
+
control: 'object',
|
|
31
|
+
description: 'Array of locale strings (e.g., ["pt-BR", "en-US"]) for number formatting.',
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export default meta
|
|
37
|
+
|
|
38
|
+
type Story = StoryObj<typeof meta>
|
|
39
|
+
|
|
40
|
+
export const Default: Story = {
|
|
41
|
+
args: {
|
|
42
|
+
value: 123456789,
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const WithCurrency: Story = {
|
|
47
|
+
args: {
|
|
48
|
+
value: 123456789,
|
|
49
|
+
currency: 'BRL',
|
|
50
|
+
locales: ['pt-BR'],
|
|
51
|
+
},
|
|
52
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import NumberFlow from '@number-flow/vue'
|
|
3
|
+
|
|
4
|
+
const props = defineProps<{
|
|
5
|
+
value: number
|
|
6
|
+
precision?: number
|
|
7
|
+
currency?: string
|
|
8
|
+
locales?: string[]
|
|
9
|
+
}>()
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<template>
|
|
13
|
+
<NumberFlow
|
|
14
|
+
:value="props.value"
|
|
15
|
+
:format="{
|
|
16
|
+
roundingMode: 'expand',
|
|
17
|
+
maximumFractionDigits: props.precision,
|
|
18
|
+
currency: props.currency?.length === 3 ? props.currency : undefined,
|
|
19
|
+
style: props.currency?.length === 3 ? 'currency' : undefined,
|
|
20
|
+
}"
|
|
21
|
+
:locales="props.locales"
|
|
22
|
+
/>
|
|
23
|
+
</template>
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { Virtualizer } from 'virtua/vue'
|
|
3
|
+
|
|
4
|
+
defineOptions({
|
|
5
|
+
inheritAttrs: false,
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
const props = defineProps<{
|
|
9
|
+
content: string | number | boolean | null | undefined
|
|
10
|
+
}>()
|
|
11
|
+
|
|
12
|
+
const chunkSize = 3000
|
|
13
|
+
|
|
14
|
+
const resolvedString = computed(() => {
|
|
15
|
+
if (typeof props.content === 'string')
|
|
16
|
+
return props.content
|
|
17
|
+
|
|
18
|
+
if (typeof props.content === 'number')
|
|
19
|
+
return props.content.toString()
|
|
20
|
+
|
|
21
|
+
if (typeof props.content === 'boolean')
|
|
22
|
+
return props.content ? 'true' : 'false'
|
|
23
|
+
|
|
24
|
+
if (props.content === null)
|
|
25
|
+
return 'null'
|
|
26
|
+
|
|
27
|
+
if (props.content === undefined)
|
|
28
|
+
return 'undefined'
|
|
29
|
+
|
|
30
|
+
return props.content
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const chunks = computed(() => {
|
|
34
|
+
if (resolvedString.value.length < chunkSize) {
|
|
35
|
+
return [resolvedString.value.split(' ')]
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function splitByEmptyLines(str: string) {
|
|
39
|
+
const lines = str.split('\n')
|
|
40
|
+
|
|
41
|
+
const chunks: string[][] = [[]]
|
|
42
|
+
|
|
43
|
+
for (const line of lines) {
|
|
44
|
+
if (line.trim() === '') {
|
|
45
|
+
chunks.push(['\n'])
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
chunks[chunks.length - 1].push(...line.split(' '))
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return chunks
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function splitByWords(str: string) {
|
|
56
|
+
const words = str.split(' ')
|
|
57
|
+
const chunks: string[][] = []
|
|
58
|
+
|
|
59
|
+
for (let i = 0; i < words.length; i += chunkSize) {
|
|
60
|
+
chunks.push(words.slice(i, i + chunkSize))
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return chunks
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// check if the chunks are too small, if so, we can split the chunks by words
|
|
67
|
+
function checkChunksSize(original: string, chunks: string[][]) {
|
|
68
|
+
const idealNumberOfChunks = Math.ceil(original.length / chunkSize)
|
|
69
|
+
const numberOfChunks = chunks.length
|
|
70
|
+
const avg = chunks.reduce((acc, chunk) => acc + chunk.length, 0) / chunks.length
|
|
71
|
+
|
|
72
|
+
// if the number of chunks is less than 70% of the ideal number of chunks
|
|
73
|
+
if (numberOfChunks < idealNumberOfChunks * 0.7) {
|
|
74
|
+
return false
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// if the average chunk length is less than 70% of the ideal chunk length
|
|
78
|
+
if (avg < chunkSize * 0.7) {
|
|
79
|
+
return false
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return true
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const chunks = splitByEmptyLines(resolvedString.value)
|
|
86
|
+
|
|
87
|
+
if (checkChunksSize(resolvedString.value, chunks)) {
|
|
88
|
+
return chunks
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return splitByWords(resolvedString.value)
|
|
92
|
+
})
|
|
93
|
+
</script>
|
|
94
|
+
|
|
95
|
+
<template>
|
|
96
|
+
<Virtualizer v-slot="{ item }" :data="chunks" class="block h-full">
|
|
97
|
+
<TransitionGroup name="word">
|
|
98
|
+
<span v-for="word, i in item" v-bind="$attrs" :key="`word-${i}`" whitespace="break-spaces">{{ `${word} ` }}</span>
|
|
99
|
+
</TransitionGroup>
|
|
100
|
+
</Virtualizer>
|
|
101
|
+
</template>
|
|
102
|
+
|
|
103
|
+
<style scoped>
|
|
104
|
+
.word-enter-active,
|
|
105
|
+
.word-leave-active {
|
|
106
|
+
transition:
|
|
107
|
+
top .35s ease-out,
|
|
108
|
+
opacity .8s ease-out;
|
|
109
|
+
opacity: 0.8;
|
|
110
|
+
position: relative;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.word-enter-from,
|
|
114
|
+
.word-leave-to {
|
|
115
|
+
opacity: 0;
|
|
116
|
+
top: 10px;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.word-enter-to,
|
|
120
|
+
.word-leave-from {
|
|
121
|
+
opacity: 1;
|
|
122
|
+
top: 0px;
|
|
123
|
+
}
|
|
124
|
+
</style>
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
|
|
4
|
+
const props = withDefaults(
|
|
5
|
+
defineProps<{
|
|
6
|
+
value: any,
|
|
7
|
+
direction?: 'vertical' | 'horizontal',
|
|
8
|
+
enterOffset?: string,
|
|
9
|
+
leaveOffset?: string
|
|
10
|
+
}>(),
|
|
11
|
+
{
|
|
12
|
+
direction: 'vertical',
|
|
13
|
+
enterOffset: '20px',
|
|
14
|
+
leaveOffset: '-20px',
|
|
15
|
+
},
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
const cssVars = computed(() => {
|
|
19
|
+
if (props.direction === 'horizontal') {
|
|
20
|
+
return {
|
|
21
|
+
'--enter-offset': props.enterOffset,
|
|
22
|
+
'--leave-offset': props.leaveOffset,
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return {}
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const directionClass = computed(() => props.direction)
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<template>
|
|
32
|
+
<Transition name="slide-fade" mode="out-in">
|
|
33
|
+
<p :key="value" :class="directionClass" :style="cssVars">
|
|
34
|
+
{{ value }}
|
|
35
|
+
</p>
|
|
36
|
+
</Transition>
|
|
37
|
+
</template>
|
|
38
|
+
|
|
39
|
+
<style scoped>
|
|
40
|
+
.slide-fade-enter-active {
|
|
41
|
+
transition: all 100ms ease;
|
|
42
|
+
}
|
|
43
|
+
.slide-fade-leave-active {
|
|
44
|
+
transition: all 100ms cubic-bezier(1.0, 0.5, 0.8, 1.0);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.horizontal.slide-fade-enter-active {
|
|
48
|
+
transition: all 200ms ease;
|
|
49
|
+
}
|
|
50
|
+
.horizontal.slide-fade-leave-active {
|
|
51
|
+
transition: all 200ms cubic-bezier(1.0, 0.5, 0.8, 1.0);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.horizontal.slide-fade-enter {
|
|
55
|
+
transform: translateX(var(--enter-offset));
|
|
56
|
+
opacity: 0;
|
|
57
|
+
}
|
|
58
|
+
.horizontal.slide-fade-leave-to {
|
|
59
|
+
transform: translateX(var(--leave-offset));
|
|
60
|
+
opacity: 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.vertical.slide-fade-enter,
|
|
64
|
+
.vertical.slide-fade-leave-to {
|
|
65
|
+
transform: translateY(-10px);
|
|
66
|
+
opacity: 0;
|
|
67
|
+
}
|
|
68
|
+
</style>
|