PluginProbe
The Innovative Form Builder – IvyForms / 0.3
The Innovative Form Builder – IvyForms v0.3
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 / notification / IvyNotification.vue

IvyNotification.vue in The Innovative Form Builder – IvyForms 0.3, at frontend/src/views/_components/notification/IvyNotification.vue

316 lines 8.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <template>
2 <div
3 :class="[
4 'ivyforms-notification ivyforms-flex ivyforms-align-items-center ivyforms-gap-12 ivyforms-p-8',
5 `ivyforms-notification--type-${type}`,
6 `ivyforms-notification--state-${state}`,
7 `ivyforms-notification--style-${style}`,
8 ]"
9 role="alert"
10 :aria-live="state === 'danger' ? 'assertive' : 'polite'"
11 >
12 <!-- Content -->
13 <div class="ivyforms-notification__content ivyforms-flex-1">
14 <!-- Title -->
15 <div v-if="title" class="ivyforms-notification__title ivyforms-flex ivyforms-gap-4">
16 <IvyIcon
17 v-if="showTitleIcon"
18 :name="getTitleIconName()"
19 :type="getTitleIconType()"
20 :category="getTitleIconCategory()"
21 size="s"
22 :color="getTitleIconColor()"
23 class="ivyforms-notification__title-icon"
24 />
25 <span
26 class="ivyforms-notification__title-text medium-14 ivyforms-flex-1 ivyforms-align-items-center ivyforms-mt-2"
27 >{{ title }}</span
28 >
29 </div>
30
31 <!-- Description -->
32 <div
33 v-if="description"
34 class="ivyforms-notification__description ivyforms-flex ivyforms-gap-4"
35 >
36 <IvyIcon
37 v-if="showDescriptionIcon"
38 :name="getDescriptionIconName()"
39 :type="getDescriptionIconType()"
40 :category="getDescriptionIconCategory()"
41 size="s"
42 :color="getDescriptionIconColor()"
43 class="ivyforms-notification__description-icon ivyforms-mt-2"
44 />
45 <span
46 class="ivyforms-notification__description-text regular-14 ivyforms-flex-1 ivyforms-align-items-center ivyforms-mt-2"
47 >
48 {{ description }}
49 <a
50 v-if="showLink"
51 class="ivyforms-notification__description-text__link"
52 :href="linkUrl"
53 target="_blank"
54 >{{ linkText }}
55 </a>
56 </span>
57 </div>
58 </div>
59
60 <!-- Actions -->
61 <div
62 v-if="showButton || $slots.actions"
63 class="ivyforms-notification__actions ivyforms-flex ivyforms-align-items-center ivyforms-gap-4"
64 >
65 <slot name="actions">
66 <IvyButtonAction
67 v-if="showButton"
68 :priority="getButtonPriority()"
69 :type="getButtonType()"
70 size="xs"
71 @click="handleButtonClick"
72 >
73 {{ buttonLabel || getLabel('action') }}
74 </IvyButtonAction>
75 </slot>
76 </div>
77 </div>
78 </template>
79
80 <script setup lang="ts">
81 import IvyIcon from '@/views/_components/icon/IvyIcon.vue'
82 import IvyButtonAction from '@/views/_components/button/IvyButtonAction.vue'
83 import type { IconType } from '@/types/icons/icon-type'
84 import type { IconCategory } from '@/types/icons/icon-category'
85 import { useLabels } from '@/composables/useLabels'
86 import { useTheme } from '@/composables/useTheme'
87
88 const { getLabel } = useLabels()
89 const { isDark } = useTheme()
90
91 type NotificationType = 'stripe'
92 type NotificationState = 'default' | 'success' | 'danger' | 'warning' | 'upcoming' | 'pro' | 'notes'
93 type NotificationStyle = 'fill' | 'stripe'
94
95 export interface IvyNotificationProps {
96 type?: NotificationType
97 state?: NotificationState
98 style?: NotificationStyle
99 title?: string
100 description?: string
101 showIcon?: boolean
102 showTitleIcon?: boolean
103 showDescriptionIcon?: boolean
104 showButton?: boolean
105 buttonLabel?: string
106 showLink?: boolean
107 linkText?: string
108 linkUrl?: string
109 }
110
111 const props = withDefaults(defineProps<IvyNotificationProps>(), {
112 type: 'stripe',
113 state: 'default',
114 style: 'fill',
115 title: '',
116 description: '',
117 showIcon: false,
118 showTitleIcon: true,
119 showDescriptionIcon: true,
120 showButton: false,
121 buttonLabel: '',
122 showLink: false,
123 linkText: '',
124 linkUrl: '',
125 })
126
127 const emit = defineEmits<{
128 buttonClick: []
129 }>()
130
131 // Icon logic based on state
132 const getIconName = () => {
133 switch (props.state) {
134 case 'success':
135 case 'notes':
136 return 'check-circle'
137 case 'danger':
138 case 'warning':
139 return 'danger'
140 case 'upcoming':
141 return 'upcoming-soon-colored'
142 case 'pro':
143 return 'bolt-lightning'
144 default:
145 return 'info'
146 }
147 }
148
149 const getButtonPriority = () => {
150 switch (props.state) {
151 case 'success':
152 case 'notes':
153 return 'primary'
154 case 'danger':
155 return 'danger'
156 case 'warning':
157 return 'warning'
158 case 'upcoming':
159 case 'pro':
160 return 'secondary'
161 default:
162 return 'tertiary'
163 }
164 }
165 const getButtonType = () => {
166 switch (props.state) {
167 case 'default':
168 return 'border'
169 default:
170 return 'fill'
171 }
172 }
173
174 const getIconType = (): IconType => {
175 switch (props.state) {
176 case 'pro':
177 return 'fill'
178 case 'upcoming':
179 return isDark() ? 'outline' : 'fill'
180 default:
181 return 'fill-duo'
182 }
183 }
184
185 const getIconCategory = (): IconCategory => {
186 switch (props.state) {
187 case 'upcoming':
188 return 'promotion'
189 default:
190 return 'global'
191 }
192 }
193
194 const getIconColor = () => {
195 switch (props.state) {
196 case 'success':
197 return 'var(--map-status-success-symbol-0)'
198 case 'danger':
199 return 'var(--map-status-error-symbol-0)'
200 case 'warning':
201 return 'var(--map-status-warning-symbol-0)'
202 case 'upcoming':
203 return 'var(--map-base-purple-symbol-0)'
204 case 'pro':
205 return 'var(--map-accent-amber-symbol-0)'
206 case 'notes':
207 return 'var(--map-status-success-symbol-0)'
208 default:
209 return 'var(--map-base-dusk-symbol-0)'
210 }
211 }
212
213 // Title icon logic
214 const getTitleIconName = () => getIconName()
215 const getTitleIconType = (): IconType => getIconType()
216 const getTitleIconCategory = (): IconCategory => getIconCategory()
217 const getTitleIconColor = () => getIconColor()
218
219 // Description icon logic
220 const getDescriptionIconName = () => getIconName()
221 const getDescriptionIconType = (): IconType => getIconType()
222 const getDescriptionIconCategory = (): IconCategory => getIconCategory()
223 const getDescriptionIconColor = () => getIconColor()
224
225 // Event handlers
226 const handleButtonClick = () => {
227 emit('buttonClick')
228 }
229 </script>
230
231 <style lang="scss">
232 @use 'sass:map';
233 .ivyforms-notification {
234 border-radius: var(--Radius-radius-md, 8px);
235 position: relative;
236 transition: all 0.2s ease-in-out;
237 flex-direction: row;
238
239 &--style-fill {
240 border: none;
241 box-shadow: none;
242 }
243
244 &--style-stripe {
245 border-left: 2px solid;
246 box-shadow: none;
247 }
248
249 &__content {
250 min-width: 0;
251 }
252
253 &__title,
254 &__description {
255 align-items: self-end;
256
257 &-icon {
258 flex-shrink: 0;
259 }
260 }
261
262 // --- State color definitions ---
263 $notification-states: (
264 default: (
265 bg: var(--map-base-dusk-o10),
266 border: var(--map-base-dusk-stroke-0),
267 text: var(--map-base-text-0),
268 ),
269 success: (
270 bg: var(--map-status-success-o10),
271 border: var(--map-status-success-stroke-0),
272 text: var(--map-status-success-symbol-0),
273 ),
274 danger: (
275 bg: var(--map-status-error-o10),
276 border: var(--map-status-error-stroke-0),
277 text: var(--map-status-error-symbol-0),
278 ),
279 warning: (
280 bg: var(--map-status-warning-o10),
281 border: var(--map-status-warning-stroke-0),
282 text: var(--map-status-warning-symbol-0),
283 ),
284 upcoming: (
285 bg: var(--map-accent-maroon-o10),
286 border: var(--map-accent-maroon-stroke-0),
287 text: var(--map-accent-maroon-fill-0),
288 ),
289 pro: (
290 bg: var(--map-accent-amber-o10),
291 border: var(--map-accent-amber-symbol-0),
292 text: var(--map-accent-amber-symbol-0),
293 ),
294 notes: (
295 bg: var(--map-status-success-o10),
296 border: var(--map-status-success-stroke-0),
297 text: var(--map-status-success-symbol-0),
298 ),
299 );
300
301 // --- Loop through states ---
302 @each $name, $colors in $notification-states {
303 &--state-#{$name} {
304 background-color: map.get($colors, bg);
305 border-left-color: map.get($colors, border);
306
307 .ivyforms-notification__title-text,
308 .ivyforms-notification__description-text,
309 .ivyforms-notification__description-text__link {
310 color: map.get($colors, text);
311 }
312 }
313 }
314 }
315 </style>
316