@rocketui/vue 0.0.46 → 0.0.47
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/.eslintrc.cjs +79 -0
- package/.gitattributes +2 -0
- package/.github/workflows/chromatic.yml +28 -0
- package/.github/workflows/publish-storybook.yml +41 -0
- package/.husky/pre-commit +4 -0
- package/.prettierrc.cjs +10 -0
- package/.storybook/Theme.js +17 -0
- package/.storybook/main.ts +20 -0
- package/.storybook/manager-head.html +3 -0
- package/.storybook/manager.js +8 -0
- package/.storybook/preview-head.html +3 -0
- package/.storybook/preview.ts +36 -0
- package/.storybook/source-panel/manager.js +28 -0
- package/.storybook/withSource.js +91 -0
- package/.vscode/extensions.json +11 -0
- package/.vscode/settings.json +20 -0
- package/index.html +13 -0
- package/lib/main.ts +48 -0
- package/package.json +2 -8
- package/postcss.config.cjs +9 -0
- package/resources/rocket-ui-logo-dark.svg +27 -0
- package/resources/rocket-ui-logo-light.svg +27 -0
- package/shims-rocketui.d.ts +9 -0
- package/src/App.vue +15 -0
- package/src/assets/blank-avatar.svg +3 -0
- package/src/assets/icons/mdi.js +7302 -0
- package/src/assets/logo.svg +1 -0
- package/src/components/Accordion/Accordion.mdx +88 -0
- package/src/components/Accordion/Accordion.stories.ts +257 -0
- package/src/components/Accordion/RAccordion.vue +73 -0
- package/src/components/Accordion/accordion.css +75 -0
- package/src/components/Accordion/accordion.spec.ts +123 -0
- package/src/components/Alert/Alert.mdx +120 -0
- package/src/components/Alert/Alert.stories.ts +118 -0
- package/src/components/Alert/RAlert.vue +119 -0
- package/src/components/Alert/alert.css +136 -0
- package/src/components/Alert/alert.spec.ts +32 -0
- package/src/components/Avatar/Avatar.mdx +96 -0
- package/src/components/Avatar/Avatar.stories.ts +65 -0
- package/src/components/Avatar/RAvatar.vue +115 -0
- package/src/components/Avatar/avatar.css +82 -0
- package/src/components/Avatar/avatar.spec.ts +38 -0
- package/src/components/Badge/Badge.mdx +112 -0
- package/src/components/Badge/Badge.stories.ts +99 -0
- package/src/components/Badge/RBadge.vue +89 -0
- package/src/components/Badge/badge.css +63 -0
- package/src/components/Badge/badge.spec.ts +20 -0
- package/src/components/Box/Box.mdx +20 -0
- package/src/components/Box/Box.stories.ts +56 -0
- package/src/components/Box/RBox.vue +97 -0
- package/src/components/Breadcrumb/Breadcrumb.stories.ts +115 -0
- package/src/components/Breadcrumb/RBreadcrumb.vue +43 -0
- package/src/components/Breadcrumb/breadcrumb.css +29 -0
- package/src/components/Button/Button.mdx +148 -0
- package/src/components/Button/Button.spec.ts +29 -0
- package/src/components/Button/Button.stories.ts +118 -0
- package/src/components/Button/RButton.vue +179 -0
- package/src/components/Button/button.css +146 -0
- package/src/components/Checkbox/Checkbox.mdx +100 -0
- package/src/components/Checkbox/Checkbox.stories.ts +67 -0
- package/src/components/Checkbox/RCheckbox.vue +195 -0
- package/src/components/Checkbox/checkbox.css +67 -0
- package/src/components/Checkbox/checkbox.spec.ts +60 -0
- package/src/components/Chips/Chip.mdx +113 -0
- package/src/components/Chips/Chip.stories.ts +122 -0
- package/src/components/Chips/RChip.vue +125 -0
- package/src/components/Chips/chip.css +62 -0
- package/src/components/Chips/chip.spec.ts +40 -0
- package/src/components/Dropdown/Dropdown.mdx +135 -0
- package/src/components/Dropdown/Dropdown.stories.ts +84 -0
- package/src/components/Dropdown/RDropdown.vue +392 -0
- package/src/components/Dropdown/dropdown.css +113 -0
- package/src/components/Dropdown/dropdown.spec.ts +98 -0
- package/src/components/Flex/Flex.mdx +20 -0
- package/src/components/Flex/Flex.stories.js +127 -0
- package/src/components/Flex/RFlex.vue +91 -0
- package/src/components/Grid/Grid.mdx +20 -0
- package/src/components/Grid/Grid.stories.js +107 -0
- package/src/components/Grid/RGrid.vue +138 -0
- package/src/components/Icon/Icon.mdx +68 -0
- package/src/components/Icon/Icon.stories.ts +33 -0
- package/src/components/Icon/RIcon.vue +56 -0
- package/src/components/Icon/icon.spec.ts +25 -0
- package/src/components/ItemGroup/ItemGroup.stories.ts +91 -0
- package/src/components/ItemGroup/RItem.vue +74 -0
- package/src/components/ItemGroup/RItemGroup.vue +122 -0
- package/src/components/ItemGroup/__snapshots__/itemgroup.spec.ts.snap +13 -0
- package/src/components/ItemGroup/itemgroup.spec.ts +67 -0
- package/src/components/Label/Label.mdx +50 -0
- package/src/components/Label/Label.stories.ts +38 -0
- package/src/components/Label/RLabel.vue +42 -0
- package/src/components/Label/label.css +0 -0
- package/src/components/Modal/Modal.mdx +91 -0
- package/src/components/Modal/Modal.stories.ts +125 -0
- package/src/components/Modal/RModal.vue +130 -0
- package/src/components/Modal/modal.css +41 -0
- package/src/components/Modal/modal.spec.ts +25 -0
- package/src/components/Pagination/Pagination.stories.ts +24 -0
- package/src/components/Pagination/RPagination.vue +103 -0
- package/src/components/Pagination/pagination.css +47 -0
- package/src/components/Pagination/pagination.spec.ts +17 -0
- package/src/components/ProgressBar/ProgressBar.stories.ts +34 -0
- package/src/components/ProgressBar/RProgressBar.vue +21 -0
- package/src/components/ProgressBar/progressbar.css +24 -0
- package/src/components/ProgressBar/progressbar.spec.ts +17 -0
- package/src/components/Shared/Enums.ts +1 -0
- package/src/components/Sidebar/RSidebar.vue +27 -0
- package/src/components/Sidebar/Sidebar.mdx +31 -0
- package/src/components/Sidebar/Sidebar.stories.ts +34 -0
- package/src/components/Sidebar/sidebar.css +18 -0
- package/src/components/Sidebar/sidebar.spec.ts +33 -0
- package/src/components/Snackbar/RSnackbar.vue +136 -0
- package/src/components/Snackbar/Snackbar.mdx +126 -0
- package/src/components/Snackbar/Snackbar.stories.ts +93 -0
- package/src/components/Snackbar/snackbar.css +99 -0
- package/src/components/Snackbar/snackbar.spec.ts +56 -0
- package/src/components/Switch/RSwitch.vue +147 -0
- package/src/components/Switch/Switch.mdx +102 -0
- package/src/components/Switch/Switch.stories.ts +79 -0
- package/src/components/Switch/switch.css +102 -0
- package/src/components/Switch/switch.spec.ts +31 -0
- package/src/components/TabItem/RTabItem.vue +175 -0
- package/src/components/TabItem/TabItem.mdx +95 -0
- package/src/components/TabItem/TabItem.spec.ts +29 -0
- package/src/components/TabItem/TabItem.stories.ts +97 -0
- package/src/components/TabItem/common.ts +6 -0
- package/src/components/TabItem/tab-item.css +29 -0
- package/src/components/Tabs/RTabs.vue +94 -0
- package/src/components/Tabs/Tabs.mdx +78 -0
- package/src/components/Tabs/Tabs.spec.ts +28 -0
- package/src/components/Tabs/Tabs.stories.ts +191 -0
- package/src/components/Tabs/tabs.css +13 -0
- package/src/components/Tabs/types.ts +11 -0
- package/src/components/TextArea/RTextArea.vue +142 -0
- package/src/components/TextArea/TextArea.mdx +108 -0
- package/src/components/TextArea/TextArea.stories.ts +55 -0
- package/src/components/TextArea/textarea.css +51 -0
- package/src/components/TextArea/textarea.spec.ts +36 -0
- package/src/components/Textfield/RTextfield.vue +372 -0
- package/src/components/Textfield/Textfield.mdx +159 -0
- package/src/components/Textfield/Textfield.stories.ts +121 -0
- package/src/components/Textfield/textfield.css +81 -0
- package/src/components/Textfield/textfield.spec.ts +34 -0
- package/src/components/Tooltip/RTooltip.vue +325 -0
- package/src/components/Tooltip/Tooltip.mdx +111 -0
- package/src/components/Tooltip/Tooltip.stories.ts +203 -0
- package/src/components/Tooltip/common.ts +91 -0
- package/src/components/Tooltip/tooltip.css +34 -0
- package/src/components/Tooltip/tooltip.spec.ts +81 -0
- package/src/components/Typography/Typography.mdx +109 -0
- package/src/components/Typography/typography.css +128 -0
- package/src/directives/index.ts +19 -0
- package/src/index.css +241 -0
- package/src/main.ts +5 -0
- package/src/scripts/buildIcons.js +21 -0
- package/src/stories/Colors.mdx +355 -0
- package/src/stories/GettingStarted.mdx +121 -0
- package/src/stories/Layout.mdx +15 -0
- package/tailwind.config.cjs +16 -0
- package/tsconfig.json +24 -0
- package/vite.config.ts +39 -0
- package/vitest.config.ts +12 -0
- package/dist/rocket-ui-vue.js +0 -9381
- package/dist/rocket-ui-vue.umd.cjs +0 -1
- package/dist/style.css +0 -2
- package/dist/types/main.d.ts +0 -25
- /package/{dist → public}/design-tokens.source.json +0 -0
- /package/{dist → public}/favicon.ico +0 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
@import '../../index.css';
|
|
2
|
+
|
|
3
|
+
fieldset {
|
|
4
|
+
@apply border-none m-0 p-0;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.textfield__wrapper {
|
|
8
|
+
@apply flex flex-col items-start justify-start;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.input-wrapper {
|
|
12
|
+
@apply flex flex-col items-start justify-start w-full;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
input {
|
|
16
|
+
@apply w-full border-none h-full bg-transparent focus:outline-none text-base m-0 p-0;
|
|
17
|
+
|
|
18
|
+
&::placeholder {
|
|
19
|
+
@apply text-[var(--neutral-500)];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.textfield {
|
|
24
|
+
@apply gap-2 box-border w-full flex items-center text-sm border border-solid border-[var(--neutral-200)] text-[var(--neutral-500)] bg-[var(--textfield-bg)] rounded-lg px-4 py-3.5;
|
|
25
|
+
|
|
26
|
+
&__label {
|
|
27
|
+
@apply text-[var(--neutral-900)] text-sm p-0 mb-2;
|
|
28
|
+
}
|
|
29
|
+
&__prepend-icon {
|
|
30
|
+
&--error {
|
|
31
|
+
@apply text-red-500;
|
|
32
|
+
}
|
|
33
|
+
&--loading {
|
|
34
|
+
@apply animate-spin-reverse;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
&__append-icon {
|
|
38
|
+
&--error {
|
|
39
|
+
@apply animate-bounce text-red-500;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
&__error {
|
|
43
|
+
@apply text-red-500 font-light text-xs tracking-wide mt-1;
|
|
44
|
+
}
|
|
45
|
+
&__hint {
|
|
46
|
+
@apply text-[var(--neutral-500)] font-light text-xs tracking-wide mt-1;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
&--focus {
|
|
50
|
+
@apply ring-inset ring-2 ring-[var(--primary-100)] border border-solid border-[var(--primary-500)] text-[var(--neutral-900)];
|
|
51
|
+
}
|
|
52
|
+
&--filled {
|
|
53
|
+
@apply bg-[var(--textfield-bg)] text-[var(--neutral-900)];
|
|
54
|
+
}
|
|
55
|
+
&--loading {
|
|
56
|
+
/* @apply animate-pulse; */
|
|
57
|
+
}
|
|
58
|
+
&--disabled {
|
|
59
|
+
@apply border-[var(--neutral-200)] text-[var(--neutral-300)] bg-[var(--textfield-bg-disabled)] cursor-not-allowed;
|
|
60
|
+
|
|
61
|
+
& > input {
|
|
62
|
+
@apply cursor-not-allowed;
|
|
63
|
+
|
|
64
|
+
&::placeholder {
|
|
65
|
+
@apply text-[var(--neutral-300)];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
&--error {
|
|
70
|
+
@apply border-red-500 ring-red-50;
|
|
71
|
+
input {
|
|
72
|
+
@apply text-red-500;
|
|
73
|
+
&:focus {
|
|
74
|
+
@apply text-[var(--neutral-900)];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
&--clearable > &__append-icon {
|
|
79
|
+
@apply cursor-pointer;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { mount } from '@vue/test-utils';
|
|
4
|
+
import Textfield from './RTextfield.vue';
|
|
5
|
+
|
|
6
|
+
describe('Textfield', () => {
|
|
7
|
+
it('renders properly', () => {
|
|
8
|
+
const wrapper = mount(Textfield, {
|
|
9
|
+
props: {
|
|
10
|
+
id: 'textfield-id',
|
|
11
|
+
label: 'Textfield label',
|
|
12
|
+
disabled: false,
|
|
13
|
+
required: false,
|
|
14
|
+
placeholder: 'Textfield placeholder',
|
|
15
|
+
type: 'text',
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
expect(wrapper.exists()).toBe(true);
|
|
19
|
+
expect(wrapper.find('label').exists()).toBe(true);
|
|
20
|
+
expect(wrapper.find('label').element.getAttribute('for')).toBe(
|
|
21
|
+
'textfield-id'
|
|
22
|
+
);
|
|
23
|
+
expect(wrapper.find('input').exists()).toBe(true);
|
|
24
|
+
expect(wrapper.find('input').element.getAttribute('id')).toBe(
|
|
25
|
+
'textfield-id'
|
|
26
|
+
);
|
|
27
|
+
expect(wrapper.find('input').element.getAttribute('type')).toBe('text');
|
|
28
|
+
expect(wrapper.find('input').element.getAttribute('disabled')).toBe(null);
|
|
29
|
+
expect(wrapper.find('input').element.getAttribute('required')).toBe(null);
|
|
30
|
+
expect(wrapper.find('input').element.getAttribute('placeholder')).toBe(
|
|
31
|
+
'Textfield placeholder'
|
|
32
|
+
);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import './tooltip.css';
|
|
3
|
+
import {
|
|
4
|
+
type Placements,
|
|
5
|
+
type Triggers,
|
|
6
|
+
Placement,
|
|
7
|
+
update,
|
|
8
|
+
Trigger,
|
|
9
|
+
} from './common';
|
|
10
|
+
import { computed, ref, watchEffect } from 'vue';
|
|
11
|
+
|
|
12
|
+
export interface IProps {
|
|
13
|
+
/**
|
|
14
|
+
* Placement of the tooltip
|
|
15
|
+
* @type Placements
|
|
16
|
+
* @default Placement.Top
|
|
17
|
+
* @example
|
|
18
|
+
* <Tooltip placement="top" />
|
|
19
|
+
*/
|
|
20
|
+
placement?: Placements;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Text of the tooltip content
|
|
24
|
+
* @type string
|
|
25
|
+
* @default ''
|
|
26
|
+
* @example
|
|
27
|
+
* <Tooltip text="Tooltip" />
|
|
28
|
+
*/
|
|
29
|
+
text?: string;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Dark theme of the tooltip deneme 1 2 3
|
|
33
|
+
* @type boolean
|
|
34
|
+
* @default true
|
|
35
|
+
* @example
|
|
36
|
+
* <Tooltip dark />
|
|
37
|
+
*/
|
|
38
|
+
dark?: boolean;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Light theme of the tooltip
|
|
42
|
+
* @type boolean
|
|
43
|
+
* @default false
|
|
44
|
+
* @example
|
|
45
|
+
* <Tooltip light />
|
|
46
|
+
*/
|
|
47
|
+
light?: boolean;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Triggers of the tooltip
|
|
51
|
+
* @type Triggers
|
|
52
|
+
* @default Trigger.Hover
|
|
53
|
+
* @example
|
|
54
|
+
* <Tooltip triggers="hover" />
|
|
55
|
+
*/
|
|
56
|
+
triggers?: Triggers;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Auto hide of the tooltip
|
|
60
|
+
* @type boolean
|
|
61
|
+
* @default true
|
|
62
|
+
* @example
|
|
63
|
+
* <Tooltip autoHide />
|
|
64
|
+
*/
|
|
65
|
+
autoHide?: boolean;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Hide delay of the tooltip
|
|
69
|
+
* @type number
|
|
70
|
+
* @default 3000
|
|
71
|
+
* @example
|
|
72
|
+
* <Tooltip hideDelay={3000} />
|
|
73
|
+
*/
|
|
74
|
+
hideDelay?: number;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Show delay of the tooltip
|
|
78
|
+
* @type number
|
|
79
|
+
* @default 0
|
|
80
|
+
* @example
|
|
81
|
+
* <Tooltip showDelay={0} />
|
|
82
|
+
*/
|
|
83
|
+
showDelay?: number;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Shown state of the tooltip
|
|
87
|
+
* @type boolean
|
|
88
|
+
* @default false
|
|
89
|
+
* @example
|
|
90
|
+
* <Tooltip shown />
|
|
91
|
+
*/
|
|
92
|
+
shown?: boolean;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Disabled state of the tooltip
|
|
96
|
+
* @type boolean
|
|
97
|
+
* @default false
|
|
98
|
+
* @example
|
|
99
|
+
* <Tooltip disabled />
|
|
100
|
+
*/
|
|
101
|
+
disabled?: boolean;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Offset of the tooltip
|
|
105
|
+
* @type number
|
|
106
|
+
* @default 0
|
|
107
|
+
* @example
|
|
108
|
+
* <Tooltip offset={0} />
|
|
109
|
+
* @link https://floating-ui.com/docs/tutorial#offset-middleware
|
|
110
|
+
*/
|
|
111
|
+
offset?: number;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Padding of the tooltip
|
|
115
|
+
* @type number
|
|
116
|
+
* @default 2
|
|
117
|
+
* @example
|
|
118
|
+
* <Tooltip padding={0} />
|
|
119
|
+
* @link https://floating-ui.com/docs/tutorial#shift-middleware
|
|
120
|
+
*/
|
|
121
|
+
padding?: number;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Outside click of the tooltip
|
|
125
|
+
* @type boolean
|
|
126
|
+
* @default false
|
|
127
|
+
* @example
|
|
128
|
+
* <Tooltip outsideClick />
|
|
129
|
+
*/
|
|
130
|
+
outsideClick?: boolean;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Trigger content of the tooltip
|
|
134
|
+
* @type string
|
|
135
|
+
* @default ''
|
|
136
|
+
* @example
|
|
137
|
+
* <Tooltip triggerContent="Trigger" />
|
|
138
|
+
*/
|
|
139
|
+
triggerContent?: string;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Resizable of the tooltip
|
|
143
|
+
* @type boolean
|
|
144
|
+
* @default true
|
|
145
|
+
* @example
|
|
146
|
+
* <Tooltip resizable />
|
|
147
|
+
* @link https://developer.mozilla.org/en-US/docs/Web/API/Window/resize_event
|
|
148
|
+
*/
|
|
149
|
+
resizable?: boolean;
|
|
150
|
+
}
|
|
151
|
+
const props = withDefaults(defineProps<IProps>(), {
|
|
152
|
+
placement: Placement.Top,
|
|
153
|
+
text: '',
|
|
154
|
+
dark: true,
|
|
155
|
+
light: false,
|
|
156
|
+
triggers: Trigger.Hover,
|
|
157
|
+
autoHide: true,
|
|
158
|
+
hideDelay: 3000,
|
|
159
|
+
showDelay: 0,
|
|
160
|
+
shown: false,
|
|
161
|
+
disabled: false,
|
|
162
|
+
offset: 0,
|
|
163
|
+
padding: 2,
|
|
164
|
+
outsideClick: false,
|
|
165
|
+
triggerContent: '',
|
|
166
|
+
resizable: true,
|
|
167
|
+
});
|
|
168
|
+
const emit = defineEmits(['show', 'hide']);
|
|
169
|
+
|
|
170
|
+
// @ts-ignore
|
|
171
|
+
const trigger = ref<HTMLDivElement>(null);
|
|
172
|
+
// @ts-ignore
|
|
173
|
+
const tooltip = ref<HTMLDivElement>(null);
|
|
174
|
+
// @ts-ignore
|
|
175
|
+
const arrowElement = ref<HTMLDivElement>(null);
|
|
176
|
+
|
|
177
|
+
function showTooltip() {
|
|
178
|
+
const { placement, offset, padding, disabled } = props;
|
|
179
|
+
if (disabled) return;
|
|
180
|
+
tooltip.value.style.display = 'block';
|
|
181
|
+
emit('show');
|
|
182
|
+
update(trigger, tooltip, arrowElement, placement, offset, padding);
|
|
183
|
+
handleAutoHide();
|
|
184
|
+
if (props.outsideClick) toggleOutsideClick('add');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function hideTooltip() {
|
|
188
|
+
tooltip.value.style.display = '';
|
|
189
|
+
emit('hide');
|
|
190
|
+
if (props.outsideClick) toggleOutsideClick('remove');
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const handleAutoHide = () => {
|
|
194
|
+
if (props.autoHide) {
|
|
195
|
+
setTimeout(() => {
|
|
196
|
+
hideTooltip();
|
|
197
|
+
}, props.hideDelay);
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const toggleOutsideClick = (toggle: string) => {
|
|
202
|
+
if (toggle === 'add') document.addEventListener('click', hideTooltip);
|
|
203
|
+
|
|
204
|
+
if (toggle === 'remove') document.removeEventListener('click', hideTooltip);
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const onClick = () => {
|
|
208
|
+
if (props.disabled) return;
|
|
209
|
+
if (props.triggers == Trigger.Click) {
|
|
210
|
+
if (tooltip.value.style.display === 'block') hideTooltip();
|
|
211
|
+
else showTooltip();
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
const onMouseEnter = () => {
|
|
216
|
+
if (props.disabled) return;
|
|
217
|
+
if (props.triggers === Trigger.Hover) showTooltip();
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
const onMouseLeave = () => {
|
|
221
|
+
if (props.disabled) return;
|
|
222
|
+
if (tooltip.value.style.display === '' && props.triggers === Trigger.Hover) {
|
|
223
|
+
showTooltip();
|
|
224
|
+
return;
|
|
225
|
+
} else if (
|
|
226
|
+
tooltip.value.style.display !== '' &&
|
|
227
|
+
props.triggers === Trigger.Hover
|
|
228
|
+
) {
|
|
229
|
+
hideTooltip();
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
const onMouseMove = () => {
|
|
234
|
+
const { placement, offset, padding, disabled } = props;
|
|
235
|
+
if (disabled) return;
|
|
236
|
+
if (props.triggers === Trigger.Hover)
|
|
237
|
+
update(trigger, tooltip, arrowElement, placement, offset, padding);
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
const classes = computed(() => {
|
|
241
|
+
return {
|
|
242
|
+
tooltip: true,
|
|
243
|
+
'tooltip--dark': props.dark,
|
|
244
|
+
'tooltip--light': props.light,
|
|
245
|
+
};
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Listen the resize event of window
|
|
250
|
+
* @link https://developer.mozilla.org/en-US/docs/Web/API/Window/resize_event
|
|
251
|
+
*/
|
|
252
|
+
window.onresize = () => {
|
|
253
|
+
const { placement, offset, padding, disabled } = props;
|
|
254
|
+
if (disabled) return;
|
|
255
|
+
if (props.resizable)
|
|
256
|
+
update(trigger, tooltip, arrowElement, placement, offset, padding);
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
watchEffect(
|
|
260
|
+
() => {
|
|
261
|
+
if (props.disabled) return;
|
|
262
|
+
if (props.shown && props.triggers === Trigger.Manual) showTooltip();
|
|
263
|
+
},
|
|
264
|
+
{ flush: 'post' } // this is important to avoid infinite loop & for fire on mounted
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
const animationDuration = computed(() => {
|
|
268
|
+
return `${props.showDelay}ms`;
|
|
269
|
+
});
|
|
270
|
+
</script>
|
|
271
|
+
|
|
272
|
+
<template>
|
|
273
|
+
<div
|
|
274
|
+
ref="trigger"
|
|
275
|
+
:aria-disabled="props.disabled"
|
|
276
|
+
class="trigger"
|
|
277
|
+
@click.stop="onClick"
|
|
278
|
+
@mouseenter.stop="onMouseEnter"
|
|
279
|
+
@mouseleave.stop="onMouseLeave"
|
|
280
|
+
@mousemove.stop="onMouseMove"
|
|
281
|
+
>
|
|
282
|
+
<slot name="trigger" />
|
|
283
|
+
|
|
284
|
+
<div v-if="!$slots['trigger']" v-html="props.triggerContent" />
|
|
285
|
+
</div>
|
|
286
|
+
<div id="tooltip" ref="tooltip" :class="classes" role="tooltip">
|
|
287
|
+
<slot name="content" />
|
|
288
|
+
<div
|
|
289
|
+
v-if="!$slots['content']"
|
|
290
|
+
:class="{
|
|
291
|
+
tooltip__content: true,
|
|
292
|
+
'tooltip__content--dark': props.dark,
|
|
293
|
+
'tooltip__content--light': props.light,
|
|
294
|
+
}"
|
|
295
|
+
>
|
|
296
|
+
{{ props.text }}
|
|
297
|
+
</div>
|
|
298
|
+
<div
|
|
299
|
+
v-if="!$slots['content']"
|
|
300
|
+
id="arrow"
|
|
301
|
+
ref="arrowElement"
|
|
302
|
+
:class="{
|
|
303
|
+
tooltip__arrow: true,
|
|
304
|
+
'tooltip__arrow--dark': props.dark,
|
|
305
|
+
'tooltip__arrow--light': props.light,
|
|
306
|
+
}"
|
|
307
|
+
/>
|
|
308
|
+
</div>
|
|
309
|
+
</template>
|
|
310
|
+
<style scoped>
|
|
311
|
+
.tooltip {
|
|
312
|
+
animation-name: tooltip-show;
|
|
313
|
+
animation-duration: v-bind('animationDuration');
|
|
314
|
+
animation-fill-mode: forwards;
|
|
315
|
+
animation-timing-function: ease-in-out;
|
|
316
|
+
}
|
|
317
|
+
@keyframes tooltip-show {
|
|
318
|
+
0% {
|
|
319
|
+
opacity: 0;
|
|
320
|
+
}
|
|
321
|
+
100% {
|
|
322
|
+
opacity: 1;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
</style>
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { Canvas, Meta, Story, Controls } from '@storybook/blocks';
|
|
2
|
+
import * as TooltipStories from './Tooltip.stories';
|
|
3
|
+
|
|
4
|
+
<Meta of={TooltipStories} />
|
|
5
|
+
|
|
6
|
+
# Tooltip
|
|
7
|
+
|
|
8
|
+
A tooltip is a small pop-up window that appears when the user hovers over an element. It can be used to provide additional information or context about the element.
|
|
9
|
+
|
|
10
|
+
- [Overview](#overview)
|
|
11
|
+
|
|
12
|
+
- [Usage with props](#usage)
|
|
13
|
+
|
|
14
|
+
- [Playground](#playground)
|
|
15
|
+
|
|
16
|
+
- [Stories](#stories)
|
|
17
|
+
|
|
18
|
+
- [Tips](#tips)
|
|
19
|
+
|
|
20
|
+
## Overview <a id="overview" />
|
|
21
|
+
|
|
22
|
+
The tooltip component allows developers to easily add tooltips to their applications.
|
|
23
|
+
|
|
24
|
+
<Canvas>
|
|
25
|
+
<Story of={TooltipStories.Overview} />
|
|
26
|
+
</Canvas>
|
|
27
|
+
|
|
28
|
+
### Playground <a id="playground" />
|
|
29
|
+
|
|
30
|
+
> Changes you make in the controls will be reflected in the example above.
|
|
31
|
+
|
|
32
|
+
<Controls
|
|
33
|
+
of={TooltipStories.Overview}
|
|
34
|
+
exclude={/^(trigger|content|click|on.*)/}
|
|
35
|
+
/>
|
|
36
|
+
|
|
37
|
+
## Stories <a id="stories" />
|
|
38
|
+
|
|
39
|
+
### Default
|
|
40
|
+
|
|
41
|
+
<Canvas>
|
|
42
|
+
<Story of={TooltipStories.Default} />
|
|
43
|
+
</Canvas>
|
|
44
|
+
|
|
45
|
+
### With Click Trigger
|
|
46
|
+
|
|
47
|
+
<Canvas>
|
|
48
|
+
<Story of={TooltipStories.WithClickTrigger} />
|
|
49
|
+
</Canvas>
|
|
50
|
+
|
|
51
|
+
### With Manual Trigger
|
|
52
|
+
|
|
53
|
+
<Canvas>
|
|
54
|
+
<Story of={TooltipStories.WithManualTrigger} />
|
|
55
|
+
</Canvas>
|
|
56
|
+
|
|
57
|
+
### With Content Slot
|
|
58
|
+
|
|
59
|
+
<Canvas>
|
|
60
|
+
<Story of={TooltipStories.WithContentSlot} />
|
|
61
|
+
</Canvas>
|
|
62
|
+
|
|
63
|
+
## With Directives
|
|
64
|
+
|
|
65
|
+
<Canvas>
|
|
66
|
+
<Story of={TooltipStories.WithDirectives} />
|
|
67
|
+
</Canvas>
|
|
68
|
+
|
|
69
|
+
## Usage with props <a id="usage" />
|
|
70
|
+
|
|
71
|
+
## placement (optional) and text (optional)
|
|
72
|
+
|
|
73
|
+
It supports various **placement** options such as top, right, bottom, and left, as well as more specific placements like top-start, top-end, right-start, right-end, bottom-start, bottom-end, left-start, and left-end. The **text** prop allows developers to specify the text that will be displayed in the tooltip.
|
|
74
|
+
|
|
75
|
+
## light (optional) and dark (optional)
|
|
76
|
+
|
|
77
|
+
The **light** and **dark** props can be used to change the color scheme of the tooltip.
|
|
78
|
+
|
|
79
|
+
## autoHide (optional) and hideDelay (optional)
|
|
80
|
+
|
|
81
|
+
The **autoHide** prop allows the tooltip to automatically hide after a specified delay, while the **hideDelay** and showDelay props can be used to control the delay before the tooltip is hidden or shown.
|
|
82
|
+
|
|
83
|
+
## shown (optional) and disabled (optional)
|
|
84
|
+
|
|
85
|
+
The **shown** prop can be used to manually control the visibility of the tooltip, while the **disabled** prop can be used to disable the tooltip entirely.
|
|
86
|
+
|
|
87
|
+
## offset (optional), padding (optional) and outsideClick (optional)
|
|
88
|
+
|
|
89
|
+
The **offset** and **padding** props can be used to adjust the position of the tooltip, and the **outsideClick** prop allows developers to specify whether the tooltip should be hidden when the user clicks outside of it.
|
|
90
|
+
|
|
91
|
+
## resizable (optional)
|
|
92
|
+
|
|
93
|
+
The **resizable** prop can be used to specify whether the tooltip should be resizable.
|
|
94
|
+
|
|
95
|
+
## Tips <a id="tips" />
|
|
96
|
+
|
|
97
|
+
💡 Tooltips are meant to provide additional information or context, so it's important to keep the text short and to the point. Avoid using long sentences or paragraphs of text, as it can make the tooltip difficult to read and may cause the user to lose interest.
|
|
98
|
+
|
|
99
|
+
💡 The placement of the tooltip can greatly affect its effectiveness. Use clear and consistent placement across your application to make it easy for the user to understand where the tooltip will appear.
|
|
100
|
+
|
|
101
|
+
💡 The delay before the tooltip appears and disappears can greatly affect the user's experience. Experiment with different values for the showDelay and hideDelay props to find the right balance between making the tooltip appear quickly enough to be useful but not so quickly that it becomes distracting.
|
|
102
|
+
|
|
103
|
+
💡 Use the light and dark props to match the tooltip color scheme with the overall theme of your application. This will make the tooltip feel like a natural part of the interface.
|
|
104
|
+
|
|
105
|
+
💡 The offset prop allows you to adjust the position of the tooltip relative to the trigger element. Use it to fine-tune the placement of the tooltip and make it feel more natural.
|
|
106
|
+
|
|
107
|
+
💡 The padding prop can be used to add space around the tooltip text, which can make it easier to read.
|
|
108
|
+
|
|
109
|
+
💡 This can improve the user experience by preventing the tooltip from staying visible when the user is no longer interacting with the trigger element.
|
|
110
|
+
|
|
111
|
+
💡 Always test the tooltip with real users to see how it works in practice and to gather feedback on how it can be improved.
|