PluginProbe
The Innovative Form Builder – IvyForms / 0.1.2
The Innovative Form Builder – IvyForms v0.1.2
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 / menu / IvyHeaderButton.vue

IvyHeaderButton.vue in The Innovative Form Builder – IvyForms 0.1.2, at frontend/src/views/_components/menu/IvyHeaderButton.vue

288 lines 6.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <template>
2 <div class="ivyforms-header-button-wrapper">
3 <ElMenuItem
4 :index="name"
5 :class="[
6 `size-${size}`,
7 'ivyforms-menu-item',
8 `priority-${priority}`,
9 `type-${type}`,
10 { 'is-active': isActive },
11 { 'has-coming-soon': comingSoon },
12 ]"
13 :disabled="disabled || comingSoon"
14 @click="onClick"
15 >
16 <IvyIcon v-if="iconStart?.name" v-bind="iconStart" />
17
18 <span>
19 {{ label }}
20 </span>
21
22 <IvyIcon v-if="iconEnd?.name" v-bind="iconEnd" />
23 </ElMenuItem>
24
25 <ComingSoonBadge
26 v-if="props.comingSoon"
27 class="ivyforms-header-button-wrapper__coming-soon"
28 :size="'s'"
29 />
30 </div>
31 </template>
32
33 <script setup lang="ts">
34 import { computed } from 'vue'
35 import type { IconCategory } from '@/types/icons/icon-category'
36 import type { IconType } from '@/types/icons/icon-type'
37
38 interface IconConfig {
39 name: string
40 type?: IconType
41 category?: IconCategory
42 size?: 'l' | 'd' | 's' | 'xs'
43 outerSize?: string
44 }
45
46 interface Props {
47 name?: string
48 label: string
49 priority?: 'primary' | 'secondary' | 'tertiary'
50 size?: 's' | 'd' | 'l'
51 type?: 'filled' | 'tonal' | 'white'
52 disabled?: boolean
53 isActive?: boolean
54 iconStartConfig?: IconConfig
55 iconEndConfig?: IconConfig
56 comingSoon?: boolean
57 }
58
59 // Default icon configuration
60 const defaultIconConfig: IconConfig = {
61 name: 'page',
62 size: 'l',
63 outerSize: '20px',
64 }
65
66 // Merge icon configuration only if the prop is passed
67 const getIconConfig = (iconConfig?: IconConfig) =>
68 iconConfig ? { ...defaultIconConfig, ...iconConfig } : undefined
69
70 const props = withDefaults(defineProps<Props>(), {
71 priority: 'primary',
72 size: 'd',
73 type: 'filled',
74 isActive: false,
75 disabled: false,
76 iconStartConfig: undefined,
77 iconEndConfig: undefined,
78 name: '',
79 comingSoon: false,
80 })
81
82 // Apply defaults only if the config exists
83 const iconStart = computed(() => getIconConfig(props.iconStartConfig))
84 const iconEnd = computed(() => getIconConfig(props.iconEndConfig))
85
86 const emit = defineEmits(['click'])
87
88 const onClick = () => {
89 if (!props.disabled) {
90 emit('click', props.name)
91 }
92 }
93 </script>
94
95 <style lang="scss">
96 @use 'sass:list' as *;
97 @use 'sass:meta' as *;
98
99 .ivyforms-header-button-wrapper {
100 justify-content: flex-start;
101 position: relative;
102 width: 100%;
103
104 &__coming-soon {
105 position: absolute;
106 top: -7px;
107 right: -4px;
108 }
109 }
110
111 .ivyforms-menu {
112 &.el-menu {
113 // Menu Item
114 .ivyforms-menu-item {
115 display: inline-flex;
116 align-items: center;
117 justify-content: center;
118 padding: 10px var(--spacing-04, 16px);
119 border-radius: 8px;
120 border: none;
121 min-width: 44px;
122 height: 40px;
123 //flex-shrink: 0;
124 transition: background-color 0.3s;
125 font-size: 14px;
126 margin: 0;
127 font-style: normal;
128 font-weight: 500;
129 gap: var(--spacing-01, 4px);
130 flex: 1;
131
132 // Define priorities and their styles
133 $priorities: (
134 'primary': (
135 transparent,
136 var(--map-base-text-0),
137 var(--map-base-brand-o05),
138 var(--map-base-brand-symbol-0),
139 var(--map-base-brand-fill-0),
140 $primitive-white,
141 ),
142 'secondary': (
143 transparent,
144 var(--map-base-text-0),
145 var(--map-base-purple-o05),
146 var(--map-base-purple-symbol-0),
147 var(--map-base-purple-fill-0),
148 $primitive-white,
149 ),
150 'tertiary': (
151 transparent,
152 var(--map-base-text-0),
153 var(--map-base-dusk-o10),
154 var(--map-base-text-0),
155 var(--map-base-dusk-o10),
156 var(--map-base-text-0),
157 ),
158 );
159
160 // Mixin for priority styles
161 @mixin menuStyles($priority, $colors: ()) {
162 $default-bg: nth($colors, 1);
163 $default-text: nth($colors, 2);
164 $hover-bg: nth($colors, 3);
165 $hover-text: nth($colors, 4);
166 $active-bg: nth($colors, 5);
167 $active-text: nth($colors, 6);
168
169 &.priority-#{$priority} {
170 background-color: $default-bg;
171 color: $default-text;
172
173 // Icon
174 .ivyforms-icon {
175 display: contents;
176 fill: $default-text;
177 width: 20px !important;
178 height: 20px;
179 svg {
180 transform: scale(0.67);
181 }
182 }
183
184 // Hover
185 &:hover,
186 &.is-hover {
187 background-color: $hover-bg;
188 color: $hover-text;
189
190 .ivyforms-icon {
191 fill: $hover-text;
192 }
193 }
194
195 // Active
196 &:active,
197 &.is-active {
198 border: none;
199 background-color: $active-bg;
200 color: $active-text !important;
201
202 .ivyforms-icon {
203 fill: $active-text;
204 }
205 }
206
207 // Focus
208 // Hover
209 &:focus,
210 &.is-focus {
211 background-color: $hover-bg;
212 color: $hover-text;
213
214 .ivyforms-icon {
215 fill: $hover-text;
216 }
217 }
218
219 &.type-tonal {
220 &:active,
221 &.is-active {
222 background-color: $hover-bg;
223 color: $hover-text !important;
224
225 .ivyforms-icon {
226 fill: $hover-text;
227 }
228 }
229 }
230
231 &.is-disabled {
232 &:active,
233 &.is-active {
234 color: $default-text !important;
235 }
236
237 &:hover,
238 &.is-hover,
239 &:focus,
240 &.is-focus {
241 background-color: $default-bg !important;
242 color: $default-text !important;
243 }
244 }
245
246 &.has-coming-soon {
247 margin: 0;
248 }
249 }
250
251 &.priority-tertiary {
252 &.is-active,
253 &:active {
254 border-radius: var(--radius-l, 8px);
255 background: var(--map-ground-level-3);
256 box-shadow: 0 4 15 0 rgba(0, 0, 0, 0.05);
257 }
258 }
259 }
260
261 // Generate styles for all priorities
262 @each $priority, $colors in $priorities {
263 @include menuStyles($priority, $colors);
264 }
265
266 // Size specific styles
267 &.size-s {
268 height: 32px;
269 max-height: 32px;
270 }
271
272 &.size-d {
273 height: 40px;
274 max-height: 40px;
275 }
276
277 &.size-l {
278 height: 48px;
279 max-height: 48px;
280 }
281 span {
282 line-height: 20px;
283 }
284 }
285 }
286 }
287 </style>
288