PluginProbe
The Innovative Form Builder – IvyForms / 1.0
The Innovative Form Builder – IvyForms v1.0
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 / toggle / IvyToggle.vue

IvyToggle.vue in The Innovative Form Builder – IvyForms 1.0, at frontend/src/views/_components/toggle/IvyToggle.vue

311 lines 6.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <template>
2 <div
3 class="ivyforms-toggle"
4 :class="[
5 `text-position-${props.textPosition}`,
6 `size-${props.size}`,
7 `priority-${props.priority}`,
8 `type-${props.type}`,
9 { 'is-disabled': props.disabled },
10 ]"
11 >
12 <ElSwitch
13 v-model="localModelValue"
14 v-bind="{ ...$props, ...$attrs, size: '' }"
15 :inline-prompt="props.type === 'stroke-with-text'"
16 :active-text="computedActiveText"
17 :inactive-text="computedInactiveText"
18 :aria-label="props.ariaLabel || getLabel('toggle_switch')"
19 @change="(eventValue: boolean | string | number) => $emit('change', eventValue)"
20 />
21 <div
22 v-if="props.title || props.tooltip || props.description"
23 class="ivyforms-toogle__text-block"
24 >
25 <div
26 v-if="props.title || props.tooltip"
27 class="ivyforms-toggle__text-block__title ivyforms-flex ivyforms-align-items-center"
28 >
29 <div v-if="props.title" class="regular-16">{{ props.title }}</div>
30 <IvyTooltip
31 v-if="props.tooltip"
32 :content="props.tooltip"
33 raw-content
34 placement="top"
35 theme="inverted"
36 :aria-label="props.title"
37 >
38 <IvyIcon
39 name="question"
40 type="outline"
41 size="s"
42 color="var(--map-base-dusk-symbol-2)"
43 @click.prevent
44 />
45 </IvyTooltip>
46 </div>
47
48 <div v-if="props.description" class="ivyforms-toogle__text-block__description">
49 {{ props.description }}
50 </div>
51 </div>
52 </div>
53 </template>
54
55 <script setup lang="ts">
56 import { computed } from 'vue'
57 import { useLabels } from '@/composables/useLabels'
58 const { getLabel } = useLabels()
59
60 interface Props {
61 modelValue?: boolean | string | number
62 label?: string
63 disabled?: boolean
64 size?: 's' | 'd' | 'l' | 'xl'
65 priority?: 'primary' | 'secondary' | 'amber'
66 type?: 'fill' | 'stroke' | 'stroke-with-text'
67 textPosition?: 'left' | 'right'
68 title?: string
69 description?: string
70 tooltip?: string
71 ariaLabel?: string
72 }
73
74 const props = withDefaults(defineProps<Props>(), {
75 disabled: false,
76 size: 'd',
77 priority: 'primary',
78 type: 'fill',
79 label: '',
80 modelValue: '',
81 textPosition: 'right',
82 title: '',
83 description: '',
84 tooltip: '',
85 ariaLabel: '',
86 })
87
88 const emit = defineEmits(['update:modelValue', 'change'])
89
90 const localModelValue = computed({
91 get() {
92 return props.modelValue
93 },
94 set(value) {
95 emit('update:modelValue', value)
96 },
97 })
98
99 const computedActiveText = computed(() =>
100 props.type === 'stroke-with-text' ? (props.label ? props.label : getLabel('on')) : '',
101 )
102 const computedInactiveText = computed(() =>
103 props.type === 'stroke-with-text' ? (props.label ? props.label : getLabel('off')) : '',
104 )
105 </script>
106
107 <style lang="scss">
108 @use 'sass:list' as *;
109
110 .ivyforms-toggle {
111 display: flex;
112 align-items: center;
113 gap: 12px;
114 min-height: 24px;
115 border-radius: 49%;
116
117 &.text-position-left {
118 flex-direction: row-reverse;
119 }
120 // Text Block
121 &__text-block {
122 // Title
123 &__title {
124 height: 24px;
125 color: var(--map-base-text-0);
126 }
127
128 // Switch Description
129 & &__description {
130 color: var(--map-base-text--1);
131 }
132 }
133
134 .el-switch__input {
135 background-color: transparent;
136 box-shadow: none;
137 color: transparent;
138 border: none;
139 }
140 .el-switch__inner {
141 align-items: flex-start;
142 justify-content: center;
143 .is-text {
144 font-weight: 400;
145 font-size: 12px;
146 line-height: 16px;
147 text-align: center;
148 position: absolute;
149 left: 50%;
150 }
151 }
152
153 &.is-disabled {
154 opacity: 0.5;
155 pointer-events: none;
156 }
157
158 .el-switch {
159 display: flex;
160
161 &__core {
162 background-color: var(--map-base-dusk-o05);
163 border-color: var(--map-base-dusk-fill--2);
164 border-radius: 49px;
165 min-width: 34px;
166
167 .el-switch__action {
168 background-color: var(--map-base-dusk-fill-1);
169 box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.04);
170 }
171
172 &:not(.is-checked):hover .el-switch__action {
173 background-color: var(--map-base-dusk-fill-2);
174 }
175
176 .el-switch__inner {
177 .is-text {
178 color: var(--map-base-text--1);
179 }
180 }
181 }
182 }
183
184 &__label {
185 font-size: 14px;
186 font-weight: 500;
187 }
188
189 $priorities: (
190 'primary': (
191 var(--map-base-brand-fill-0),
192 var(--map-base-brand-fill-1),
193 ),
194 'secondary': (
195 var(--map-base-purple-fill-0),
196 var(--map-base-purple-fill-1),
197 ),
198 'amber': (
199 var(--map-accent-amber-fill-0),
200 var(--map-accent-amber-fill-1),
201 ),
202 );
203
204 // Process each priority value if is array
205 @each $priority, $values in $priorities {
206 &.priority-#{$priority} {
207 .el-switch {
208 &.is-checked {
209 .el-switch__core {
210 background-color: nth($values, 1);
211 border-color: nth($values, 1);
212
213 .el-switch__action {
214 background-color: $primitive-white;
215 }
216
217 .el-switch__inner .is-text {
218 color: $primitive-white;
219 left: 20%;
220 }
221 }
222
223 // Hover state when checked
224 &:hover .el-switch__core {
225 background-color: nth($values, 2);
226 }
227 }
228 }
229 }
230 }
231
232 // Define sizes in a map
233 $sizes: (
234 'xl': (
235 70px,
236 36px,
237 32px,
238 28px,
239 ),
240 'l': (
241 64px,
242 32px,
243 28px,
244 24px,
245 ),
246 'd': (
247 46px,
248 24px,
249 20px,
250 16px,
251 ),
252 's': (
253 34px,
254 16px,
255 14px,
256 12px,
257 ),
258 );
259
260 // Process each size value if is array
261 @each $size, $values in $sizes {
262 &.size-#{$size} {
263 .el-switch {
264 .el-switch__core {
265 height: nth($values, 2);
266 width: nth($values, 1);
267
268 .el-switch__action {
269 height: nth($values, 3);
270 width: nth($values, 3);
271 left: calc(100% - nth($values, 3));
272 }
273 }
274
275 &:not(.is-checked) .el-switch__action {
276 left: 1px;
277 }
278 }
279 &.type-stroke-with-text {
280 .el-switch {
281 .el-switch__core {
282 .el-switch__action {
283 height: nth($values, 4);
284 width: nth($values, 4);
285 }
286 }
287 }
288 }
289 &.type-stroke {
290 .el-switch {
291 .el-switch__core {
292 height: nth($values, 4);
293 width: nth($values, 1);
294
295 .el-switch__action {
296 height: nth($values, 2);
297 width: nth($values, 2);
298 left: calc(100% - nth($values, 2) + 3px);
299 }
300 }
301
302 &:not(.is-checked) .el-switch__action {
303 left: -2px;
304 }
305 }
306 }
307 }
308 }
309 }
310 </style>
311