PluginProbe
The Innovative Form Builder – IvyForms / 0.4
The Innovative Form Builder – IvyForms v0.4
1.5.1 1.5 1.4.1 1.4 trunk 0.1.2 0.2 0.2.1 0.3 0.3.1 0.4 0.5 0.6 0.6.1 0.6.1-backup 0.6.1.1 0.7 0.8 0.8.1 0.8.2 0.9 0.9.1 1.0 1.1 1.1.1 All 27 releases
ivyforms / frontend / src / views / _components / tooltip / IvyTooltip.vue

IvyTooltip.vue in The Innovative Form Builder – IvyForms 0.4, at frontend/src/views/_components/tooltip/IvyTooltip.vue

172 lines 4.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <template>
2 <div class="ivyforms-tooltip" role="tooltip">
3 <ElTooltip
4 v-model="localModelValue"
5 :popper-class="['ivyforms-tooltip-popper', themeClass]"
6 effect="customized"
7 v-bind="$attrs"
8 :hide-after="validatedHideAfter"
9 :placement="placement"
10 :popper-options="{
11 modifiers: [
12 { name: 'preventOverflow', options: { boundary: 'viewport' } },
13 { name: 'flip', options: { fallbackPlacements: ['top', 'bottom', 'right', 'left'] } },
14 {
15 name: 'maxWidth',
16 enabled: true,
17 fn: ({ state }) => {
18 state.styles.popper.maxWidth = validatedMaxWidth
19 },
20 phase: 'beforeWrite',
21 requires: ['computeStyles'],
22 },
23 ],
24 }"
25 role="tooltip"
26 :aria-hidden="!localModelValue"
27 :aria-label="props.ariaLabel || getLabel('tooltip')"
28 >
29 <template #content>
30 <div :id="tooltipId">
31 <slot name="content">{{ props.content }}</slot>
32 </div>
33 </template>
34 <div ref="tooltipTrigger" :aria-describedby="tooltipId">
35 <slot />
36 </div>
37 </ElTooltip>
38 </div>
39 </template>
40
41 <script setup lang="ts">
42 import { ref, computed } from 'vue'
43 import { nanoid } from 'nanoid'
44 import { useLabels } from '@/composables/useLabels'
45 const { getLabel } = useLabels()
46
47 interface Props {
48 modelValue?: boolean
49 content?: string | undefined
50 maxWidth?: string
51 hideAfter?: number
52 placement?:
53 | 'top'
54 | 'top-start'
55 | 'top-end'
56 | 'bottom'
57 | 'bottom-start'
58 | 'bottom-end'
59 | 'left'
60 | 'left-start'
61 | 'left-end'
62 | 'right'
63 | 'right-start'
64 | 'right-end'
65 theme?: 'light' | 'inverted' | 'dusk'
66 ariaLabel?: string
67 }
68
69 const props = withDefaults(defineProps<Props>(), {
70 content: '',
71 maxWidth: '320px',
72 hideAfter: 0,
73 placement: 'top',
74 theme: 'inverted',
75 ariaLabel: '',
76 })
77
78 const emit = defineEmits(['update:modelValue'])
79
80 const localModelValue = computed({
81 get() {
82 return props.modelValue
83 },
84 set(value) {
85 emit('update:modelValue', value)
86 },
87 })
88
89 // Generate a unique tooltip ID
90 const tooltipId = ref(`ivyforms-tooltip-${nanoid(6)}`)
91
92 // Validation
93 const validatedHideAfter = computed(() =>
94 props.hideAfter && props.hideAfter > 0 ? props.hideAfter : 0,
95 )
96 const validatedMaxWidth = computed(() =>
97 /^(\d+(\.\d+)?(px|em|rem|%)|auto)$/.test(props.maxWidth ?? '320px') ? props.maxWidth : '320px',
98 )
99
100 const themeClass = computed(() => `ivyforms-tooltip-${props.theme}`)
101 </script>
102
103 <style lang="scss">
104 // Tooltip Popper
105 .ivyforms-tooltip-popper {
106 // Element Popper
107 &.el-popper {
108 border-radius: 8px;
109 box-shadow:
110 0 1px 2px 0 rgba(18, 26, 38, 0.3),
111 0 1px 3px 1px rgba(18, 26, 38, 0.15);
112 text-align: center;
113 font-size: 12px;
114 font-style: normal;
115 font-weight: 500;
116 line-height: 16px;
117 display: flex;
118 flex-direction: column;
119 align-items: flex-start;
120 gap: 4px;
121 color: var(--map-base-text-0);
122 background: var(--map-ground-level-2-foreground);
123
124 // Arrow
125 .el-popper__arrow {
126 &::before {
127 top: 0;
128 left: 0;
129 right: 0;
130 bottom: 0;
131 position: absolute;
132 border: none;
133 background: var(--map-ground-level-2-foreground);
134 }
135 }
136
137 // Themes
138 &.is-customized {
139 // Inverted
140 &.ivyforms-tooltip-inverted {
141 color: var(--map-base-dusk-fill--4);
142 background: var(--map-base-dusk-fill-4);
143 // Arrow
144 .el-popper__arrow::before {
145 background: var(--map-base-dusk-fill-4);
146 }
147 }
148
149 // Dusk
150 &.ivyforms-tooltip-dusk {
151 color: var(--map-base-text-0);
152 background: var(--map-base-dusk-fill--4);
153 // Arrow
154 .el-popper__arrow::before {
155 background: var(--map-base-dusk-fill--4) !important;
156 }
157 }
158
159 // Light
160 &.ivyforms-tooltip-light {
161 color: var(--map-base-text-0);
162 background: var(--map-ground-level-2-foreground);
163 // Arrow
164 .el-popper__arrow::before {
165 background: var(--map-ground-level-2-foreground);
166 }
167 }
168 }
169 }
170 }
171 </style>
172