srcdev-nuxt-components 9.1.55 → 9.1.57
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/.claude/settings.json +30 -2
- package/.claude/skills/components/alert-content-inner.md +60 -0
- package/.claude/skills/components/display-dialog.md +80 -0
- package/.claude/skills/components/display-prompt.md +163 -0
- package/.claude/skills/components/display-toast.md +235 -0
- package/.claude/skills/index.md +7 -3
- package/.claude/skills/theming-colour-ramps.md +328 -0
- package/.claude/skills/theming-override-default.md +115 -186
- package/.claude/skills/theming-partial-override.md +88 -75
- package/README.md +166 -0
- package/app/app.config.ts +44 -0
- package/app/assets/styles/setup/01.config/_head.css +3 -3
- package/app/assets/styles/setup/02.colours/_amber.css +12 -10
- package/app/assets/styles/setup/02.colours/_blue.css +10 -9
- package/app/assets/styles/setup/02.colours/_green.css +12 -11
- package/app/assets/styles/setup/02.colours/_orange.css +12 -10
- package/app/assets/styles/setup/02.colours/_red.css +10 -9
- package/app/assets/styles/setup/02.colours/_slate.css +12 -11
- package/app/assets/styles/setup/02.colours/_sunset.css +12 -10
- package/app/assets/styles/setup/02.colours/_theme-params.css +18 -0
- package/app/assets/styles/setup/02.colours/index.css +1 -0
- package/app/assets/styles/setup/03.theming/_default.css +87 -0
- package/app/assets/styles/setup/03.theming/_error.css +14 -0
- package/app/assets/styles/setup/03.theming/_success.css +4 -0
- package/app/assets/styles/setup/03.theming/_theme-slots.css +16 -0
- package/app/assets/styles/setup/03.theming/_warning.css +13 -0
- package/app/assets/styles/setup/03.theming/index.css +6 -4
- package/app/assets/styles/setup/03.theming/theme-ramp.css +19 -0
- package/app/assets/styles/setup/04.elements/forms/00.element-defaults.css +0 -7
- package/app/assets/styles/setup/04.elements/forms/06.button-geometry.css +1 -1
- package/app/assets/styles/setup/index.css +1 -1
- package/app/components/01.atoms/display-dialog/DisplayDialog.vue +74 -24
- package/app/components/01.atoms/display-dialog/tests/DisplayDialog.spec.ts +148 -14
- package/app/components/01.atoms/display-dialog/tests/__snapshots__/DisplayDialog.spec.ts.snap +3 -3
- package/app/components/01.atoms/prompt/DisplayPrompt.vue +113 -0
- package/app/components/01.atoms/prompt/stories/DisplayPrompt.stories.ts +112 -0
- package/app/components/01.atoms/prompt/tests/DisplayPrompt.spec.ts +205 -0
- package/app/components/01.atoms/toast/DisplayToast.vue +327 -0
- package/app/components/01.atoms/toast/DisplayToastProvider.vue +362 -0
- package/app/components/01.atoms/toast/stories/DisplayToast.stories.ts +195 -0
- package/app/components/01.atoms/toast/stories/DisplayToastProvider.stories.ts +142 -0
- package/app/components/01.atoms/toast/tests/DisplayToast.spec.ts +266 -0
- package/app/components/01.atoms/toast/tests/DisplayToastProvider.spec.ts +256 -0
- package/app/components/02.molecules/action-menu/ActionMenu.vue +8 -1
- package/app/components/02.molecules/action-menu/ActionMenuItemCore.vue +11 -3
- package/app/components/02.molecules/alert-content/AlertContent.vue +67 -0
- package/app/components/02.molecules/alert-content/AlertContentInner.vue +153 -0
- package/app/components/02.molecules/alert-content/stories/AlertContent.stories.ts +131 -0
- package/app/components/02.molecules/alert-content/tests/AlertContent.spec.ts +135 -0
- package/app/components/02.molecules/alert-content/tests/AlertContentInner.spec.ts +135 -0
- package/app/components/02.molecules/alert-masked-content/AlertMaskedContent.vue +78 -0
- package/app/components/02.molecules/alert-masked-content/stories/AlertMaskedContent.stories.ts +132 -0
- package/app/components/02.molecules/alert-masked-content/tests/AlertMaskedContent.spec.ts +149 -0
- package/app/components/05.forms/input-button/InputButtonCore.vue +35 -39
- package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadioButton.vue +8 -8
- package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadioCore.vue +5 -5
- package/app/components/05.forms/input-copy/InputCopyCore.vue +7 -7
- package/app/components/05.forms/input-number/InputNumberCore.vue +5 -5
- package/app/components/05.forms/input-select/InputSelectCore.vue +6 -6
- package/app/components/05.forms/input-text/InputTextCore.vue +6 -6
- package/app/components/05.forms/input-text/variants/InputTextAsNumberWithLabel.vue +2 -2
- package/app/components/05.forms/input-textarea/InputTextareaCore.vue +5 -5
- package/app/components/05.forms/pending-effect/PendingEffect.vue +60 -60
- package/app/components/05.forms/toggle-switch/ToggleSwitchCore.vue +10 -10
- package/app/components/05.forms/triple-toggle-switch/TripleToggleSwitchCore.vue +4 -4
- package/app/components/display-theme-switch/DisplayThemeSwitch.vue +4 -4
- package/app/components/display-tooltip/DisplayTooltip.vue +4 -4
- package/app/composables/useBodyLock.ts +21 -0
- package/app/composables/useDialogControls.ts +11 -11
- package/app/composables/useToastQueue.ts +39 -0
- package/app/layouts/default.vue +1 -1
- package/app/pages/ui/display-dialog.vue +275 -127
- package/app/pages/ui/display-prompt.vue +255 -52
- package/app/pages/ui/display-toast.vue +278 -299
- package/app/pages/ui/mask-element.vue +25 -3
- package/app/pages/ui/settings.vue +9 -35
- package/app/types/app-config.d.ts +41 -0
- package/app/types/components/display-prompt.d.ts +11 -0
- package/app/types/components/display-toast.d.ts +11 -9
- package/app/types/components/index.ts +2 -0
- package/app/types/components/semantic-theme.d.ts +1 -0
- package/nuxt.config.ts +16 -0
- package/package.json +8 -4
- package/ramps.config.mjs +28 -0
- package/scripts/check-ramps.mjs +50 -0
- package/scripts/generate-consumer-ramps.mjs +100 -0
- package/scripts/generate-ramps.mjs +92 -0
- package/app/assets/styles/setup/03.theming/default/_dark.css +0 -156
- package/app/assets/styles/setup/03.theming/default/_light.css +0 -166
- package/app/assets/styles/setup/03.theming/default/index.css +0 -2
- package/app/assets/styles/setup/03.theming/error/_dark.css +0 -56
- package/app/assets/styles/setup/03.theming/error/_light.css +0 -74
- package/app/assets/styles/setup/03.theming/error/index.css +0 -2
- package/app/assets/styles/setup/03.theming/success/_dark.css +0 -50
- package/app/assets/styles/setup/03.theming/success/_light.css +0 -65
- package/app/assets/styles/setup/03.theming/success/index.css +0 -2
- package/app/assets/styles/setup/03.theming/warning/_dark.css +0 -50
- package/app/assets/styles/setup/03.theming/warning/_light.css +0 -64
- package/app/assets/styles/setup/03.theming/warning/index.css +0 -2
- package/app/components/display-prompt/DisplayPromptCore.vue +0 -228
- package/app/components/display-prompt/variants/DisplayPromptError.vue +0 -53
- package/app/components/display-toast/DisplayToast.vue +0 -447
- package/app/components/display-toast/molecules/DefaultToastContent.vue +0 -163
- package/app/components/display-toast/stories/DisplayToast.stories.ts +0 -380
|
@@ -2,331 +2,310 @@
|
|
|
2
2
|
<div>
|
|
3
3
|
<NuxtLayout name="default">
|
|
4
4
|
<template #layout-content>
|
|
5
|
-
<PageRow tag="div" variant="
|
|
6
|
-
<h2 class="page-heading-2">DisplayToast
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
<PageRow tag="div" variant="content" :style-class-passthrough="['mbe-20', 'p-20']">
|
|
6
|
+
<h2 class="page-heading-2">DisplayToast Masked / DisplayToastProvider</h2>
|
|
7
|
+
|
|
8
|
+
<div v-if="isDev" class="qa-panel">
|
|
9
|
+
<details class="qa-panel__details">
|
|
10
|
+
<summary class="qa-panel__summary">
|
|
11
|
+
<span class="qa-panel__title">QA — DisplayToastProvider</span>
|
|
12
|
+
<code class="qa-panel__status">
|
|
13
|
+
{{ qaTheme }} · {{ qaPosition }}-{{ qaAlignment }} ·
|
|
14
|
+
{{ qaAutoDismiss ? `auto ${qaDuration}ms` : "manual" }} · max:{{ qaMaxVisible }} ·
|
|
15
|
+
{{ qaIsMasked ? "masked" : "solid" }}
|
|
16
|
+
</code>
|
|
17
|
+
</summary>
|
|
18
|
+
<div class="qa-panel__body">
|
|
19
|
+
<div class="qa-panel__group">
|
|
20
|
+
<span class="qa-panel__label">Theme</span>
|
|
21
|
+
<div class="qa-panel__chips">
|
|
22
|
+
<button
|
|
23
|
+
v-for="opt in themes"
|
|
24
|
+
:key="opt"
|
|
25
|
+
class="qa-panel__chip"
|
|
26
|
+
:class="{ 'is-active': qaTheme === opt }"
|
|
27
|
+
@click="qaTheme = opt"
|
|
28
|
+
>
|
|
29
|
+
{{ opt }}
|
|
30
|
+
</button>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div class="qa-panel__group">
|
|
35
|
+
<span class="qa-panel__label">Position</span>
|
|
36
|
+
<div class="qa-panel__chips">
|
|
37
|
+
<button
|
|
38
|
+
v-for="opt in positions"
|
|
39
|
+
:key="opt"
|
|
40
|
+
class="qa-panel__chip"
|
|
41
|
+
:class="{ 'is-active': qaPosition === opt }"
|
|
42
|
+
@click="qaPosition = opt"
|
|
43
|
+
>
|
|
44
|
+
{{ opt }}
|
|
45
|
+
</button>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<div class="qa-panel__group">
|
|
50
|
+
<span class="qa-panel__label">Alignment</span>
|
|
51
|
+
<div class="qa-panel__chips">
|
|
52
|
+
<button
|
|
53
|
+
v-for="opt in alignments"
|
|
54
|
+
:key="opt"
|
|
55
|
+
class="qa-panel__chip"
|
|
56
|
+
:class="{ 'is-active': qaAlignment === opt }"
|
|
57
|
+
@click="qaAlignment = opt"
|
|
58
|
+
>
|
|
59
|
+
{{ opt }}
|
|
60
|
+
</button>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<div class="qa-panel__group">
|
|
65
|
+
<span class="qa-panel__label">Masked</span>
|
|
66
|
+
<div class="qa-panel__chips">
|
|
67
|
+
<button
|
|
68
|
+
v-for="opt in [true, false]"
|
|
69
|
+
:key="String(opt)"
|
|
70
|
+
class="qa-panel__chip"
|
|
71
|
+
:class="{ 'is-active': qaIsMasked === opt }"
|
|
72
|
+
@click="qaIsMasked = opt"
|
|
73
|
+
>
|
|
74
|
+
{{ opt ? "yes" : "no" }}
|
|
75
|
+
</button>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<div class="qa-panel__group">
|
|
80
|
+
<span class="qa-panel__label">Full Width</span>
|
|
81
|
+
<div class="qa-panel__chips">
|
|
82
|
+
<button
|
|
83
|
+
v-for="opt in [true, false]"
|
|
84
|
+
:key="String(opt)"
|
|
85
|
+
class="qa-panel__chip"
|
|
86
|
+
:class="{ 'is-active': qaFullWidth === opt }"
|
|
87
|
+
@click="qaFullWidth = opt"
|
|
88
|
+
>
|
|
89
|
+
{{ opt ? "yes" : "no" }}
|
|
90
|
+
</button>
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
<div class="qa-panel__group">
|
|
95
|
+
<span class="qa-panel__label">Auto Dismiss</span>
|
|
96
|
+
<div class="qa-panel__chips">
|
|
97
|
+
<button
|
|
98
|
+
v-for="opt in [true, false]"
|
|
99
|
+
:key="String(opt)"
|
|
100
|
+
class="qa-panel__chip"
|
|
101
|
+
:class="{ 'is-active': qaAutoDismiss === opt }"
|
|
102
|
+
@click="qaAutoDismiss = opt"
|
|
103
|
+
>
|
|
104
|
+
{{ opt ? "yes" : "no" }}
|
|
105
|
+
</button>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
|
|
109
|
+
<div class="qa-panel__group">
|
|
110
|
+
<span class="qa-panel__label">Duration</span>
|
|
111
|
+
<div class="qa-panel__chips">
|
|
112
|
+
<button
|
|
113
|
+
v-for="opt in durations"
|
|
114
|
+
:key="opt"
|
|
115
|
+
class="qa-panel__chip"
|
|
116
|
+
:class="{ 'is-active': qaDuration === opt }"
|
|
117
|
+
@click="qaDuration = opt"
|
|
118
|
+
>
|
|
119
|
+
{{ opt }}ms
|
|
120
|
+
</button>
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
|
|
124
|
+
<div class="qa-panel__group">
|
|
125
|
+
<span class="qa-panel__label">Max Visible</span>
|
|
126
|
+
<div class="qa-panel__chips">
|
|
127
|
+
<button
|
|
128
|
+
v-for="opt in [1, 2, 3, 4, 5]"
|
|
129
|
+
:key="opt"
|
|
130
|
+
class="qa-panel__chip"
|
|
131
|
+
:class="{ 'is-active': qaMaxVisible === opt }"
|
|
132
|
+
@click="qaMaxVisible = opt"
|
|
133
|
+
>
|
|
134
|
+
{{ opt }}
|
|
135
|
+
</button>
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
</details>
|
|
140
|
+
</div>
|
|
141
|
+
|
|
11
142
|
<form class="form-wrapper">
|
|
12
|
-
<
|
|
13
|
-
<InputButtonCore
|
|
14
|
-
|
|
15
|
-
:readonly="firstToastActive"
|
|
16
|
-
button-text="Trigger First Toast (current value: {{ firstToastActive }})"
|
|
17
|
-
theme="default"
|
|
18
|
-
:style-class-passthrough="['mbe-10']"
|
|
19
|
-
@click.prevent="triggerFirstToast()"
|
|
20
|
-
/>
|
|
21
|
-
</p>
|
|
22
|
-
<hr class="mbe-20" />
|
|
23
|
-
<p class="page-body-normal">Trigger ERROR prompt as toast with auto dismiss</p>
|
|
24
|
-
<p>
|
|
25
|
-
<InputButtonCore
|
|
26
|
-
ref="secondToastButton"
|
|
27
|
-
:readonly="secondToastActive"
|
|
28
|
-
button-text="Trigger Second Toast (current value: {{ secondToastActive }})"
|
|
29
|
-
theme="default"
|
|
30
|
-
:style-class-passthrough="['mbe-10']"
|
|
31
|
-
@click.prevent="triggerSecondToast()"
|
|
32
|
-
/>
|
|
33
|
-
</p>
|
|
34
|
-
<hr class="mbe-20" />
|
|
35
|
-
<p class="page-body-normal">Trigger SUCCESS prompt as toast with manual dismiss</p>
|
|
36
|
-
<p>
|
|
37
|
-
<InputButtonCore
|
|
38
|
-
ref="thirdToastButton"
|
|
39
|
-
:readonly="thirdToastActive"
|
|
40
|
-
button-text="Trigger Third Toast (current value: {{ thirdToastActive }})"
|
|
41
|
-
theme="default"
|
|
42
|
-
:style-class-passthrough="['mbe-10']"
|
|
43
|
-
@click.prevent="triggerThirdToast()"
|
|
44
|
-
/>
|
|
45
|
-
</p>
|
|
46
|
-
<hr class="mbe-20" />
|
|
47
|
-
<p class="page-body-normal">Trigger INFO prompt as toast with auto dismiss (full-width)</p>
|
|
48
|
-
<p>
|
|
49
|
-
<InputButtonCore
|
|
50
|
-
ref="fourthToastButton"
|
|
51
|
-
:readonly="fourthToastActive"
|
|
52
|
-
button-text="Trigger Fourth Toast (current value: {{ fourthToastActive }})"
|
|
53
|
-
theme="default"
|
|
54
|
-
:style-class-passthrough="['mbe-10']"
|
|
55
|
-
@click.prevent="triggerFourthToast()"
|
|
56
|
-
/>
|
|
57
|
-
</p>
|
|
58
|
-
<hr class="mbe-20" />
|
|
59
|
-
<p class="page-body-normal">New config-based positioning examples:</p>
|
|
60
|
-
<div class="button-grid">
|
|
61
|
-
<InputButtonCore
|
|
62
|
-
ref="bottomLeftToastButton"
|
|
63
|
-
:readonly="bottomLeftToastActive"
|
|
64
|
-
button-text="Bottom Left Toast"
|
|
65
|
-
theme="default"
|
|
66
|
-
@click.prevent="triggerBottomLeftToast()"
|
|
67
|
-
/>
|
|
68
|
-
<InputButtonCore
|
|
69
|
-
ref="bottomCenterToastButton"
|
|
70
|
-
:readonly="bottomCenterToastActive"
|
|
71
|
-
button-text="Bottom Center Toast"
|
|
72
|
-
theme="default"
|
|
73
|
-
@click.prevent="triggerBottomCenterToast()"
|
|
74
|
-
/>
|
|
75
|
-
<InputButtonCore
|
|
76
|
-
ref="customIconToastButton"
|
|
77
|
-
:readonly="customIconToastActive"
|
|
78
|
-
button-text="Custom Icon Toast"
|
|
79
|
-
theme="default"
|
|
80
|
-
@click.prevent="triggerCustomIconToast()"
|
|
81
|
-
/>
|
|
143
|
+
<div class="demo-buttons">
|
|
144
|
+
<InputButtonCore button-text="Trigger Toast" theme="default" @click.prevent="triggerToast" />
|
|
145
|
+
<InputButtonCore button-text="Queue Multiple" theme="default" @click.prevent="queueMultiple" />
|
|
82
146
|
</div>
|
|
83
|
-
<hr class="mbe-20" />
|
|
84
|
-
<p class="page-body-normal">Toast with title and content slots:</p>
|
|
85
|
-
<p>
|
|
86
|
-
<InputButtonCore
|
|
87
|
-
ref="slottedToastButton"
|
|
88
|
-
:readonly="slottedToastActive"
|
|
89
|
-
button-text="Trigger Slotted Toast (current value: {{ slottedToastActive }})"
|
|
90
|
-
theme="default"
|
|
91
|
-
:style-class-passthrough="['mbe-10']"
|
|
92
|
-
@click.prevent="triggerSlottedToast()"
|
|
93
|
-
/>
|
|
94
|
-
</p>
|
|
95
147
|
</form>
|
|
96
148
|
</PageRow>
|
|
97
149
|
|
|
98
|
-
<
|
|
99
|
-
|
|
100
|
-
:
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
content: {
|
|
104
|
-
title: 'Warning Alert',
|
|
105
|
-
description: 'This is a toast notification message with structured content.',
|
|
106
|
-
},
|
|
107
|
-
}"
|
|
150
|
+
<DisplayToastProvider
|
|
151
|
+
:position="qaPosition"
|
|
152
|
+
:alignment="qaAlignment"
|
|
153
|
+
:full-width="qaFullWidth"
|
|
154
|
+
:max-visible="qaMaxVisible"
|
|
108
155
|
/>
|
|
109
|
-
|
|
110
|
-
<DisplayToast
|
|
111
|
-
v-model="secondToastActive"
|
|
112
|
-
:config="{
|
|
113
|
-
appearance: { theme: 'error', position: 'top', alignment: 'right' },
|
|
114
|
-
behavior: { returnFocusTo: secondToastButton },
|
|
115
|
-
}"
|
|
116
|
-
>
|
|
117
|
-
<DisplayPromptCore
|
|
118
|
-
v-model="secondToastActive"
|
|
119
|
-
theme="error"
|
|
120
|
-
:dismissible="false"
|
|
121
|
-
:style-class-passthrough="['dark', 'outlined']"
|
|
122
|
-
>
|
|
123
|
-
<template #customDecoratorIcon>
|
|
124
|
-
<Icon name="akar-icons:info" class="icon" />
|
|
125
|
-
</template>
|
|
126
|
-
<template #title>Info Prompt Title with content (Dismissable)</template>
|
|
127
|
-
<template #content>This is prompt content, it can contain html or plain text.</template>
|
|
128
|
-
</DisplayPromptCore>
|
|
129
|
-
</DisplayToast>
|
|
130
|
-
|
|
131
|
-
<DisplayToast
|
|
132
|
-
v-model="thirdToastActive"
|
|
133
|
-
:config="{
|
|
134
|
-
appearance: { theme: 'success', position: 'top', alignment: 'right' },
|
|
135
|
-
behavior: { autoDismiss: false, returnFocusTo: thirdToastButton },
|
|
136
|
-
}"
|
|
137
|
-
>
|
|
138
|
-
<DisplayPromptCore
|
|
139
|
-
v-model="thirdToastActive"
|
|
140
|
-
theme="success"
|
|
141
|
-
:dismissible="true"
|
|
142
|
-
:style-class-passthrough="['dark', 'outlined']"
|
|
143
|
-
:use-auto-focus="true"
|
|
144
|
-
>
|
|
145
|
-
<template #customDecoratorIcon>
|
|
146
|
-
<Icon name="akar-icons:info" class="icon" />
|
|
147
|
-
</template>
|
|
148
|
-
<template #title>Success Prompt Title with content (Dismissable)</template>
|
|
149
|
-
<template #content>This is prompt content, it can contain html or plain text.</template>
|
|
150
|
-
<template #customCloseIcon>
|
|
151
|
-
<Icon name="material-symbols:close-small" class="icon" />
|
|
152
|
-
</template>
|
|
153
|
-
<template #customTitle>Dismiss</template>
|
|
154
|
-
</DisplayPromptCore>
|
|
155
|
-
</DisplayToast>
|
|
156
|
-
|
|
157
|
-
<DisplayToast
|
|
158
|
-
v-model="fourthToastActive"
|
|
159
|
-
:config="{
|
|
160
|
-
appearance: { theme: 'info', position: 'top', fullWidth: true },
|
|
161
|
-
behavior: { returnFocusTo: fourthToastButton },
|
|
162
|
-
}"
|
|
163
|
-
>
|
|
164
|
-
<DisplayPromptCore
|
|
165
|
-
v-model="fourthToastActive"
|
|
166
|
-
theme="info"
|
|
167
|
-
:dismissible="false"
|
|
168
|
-
:style-class-passthrough="['dark', 'outlined']"
|
|
169
|
-
>
|
|
170
|
-
<template #title>Warning Prompt Title with content (Auto Dismiss)</template>
|
|
171
|
-
<template #content>This is prompt content, it can contain html or plain text.</template>
|
|
172
|
-
<template #customCloseIcon>
|
|
173
|
-
<Icon name="material-symbols:close-small" class="icon" />
|
|
174
|
-
</template>
|
|
175
|
-
<template #customTitle>Dismiss</template>
|
|
176
|
-
</DisplayPromptCore>
|
|
177
|
-
</DisplayToast>
|
|
178
|
-
|
|
179
|
-
<DisplayToast
|
|
180
|
-
v-model="bottomLeftToastActive"
|
|
181
|
-
:config="{
|
|
182
|
-
appearance: { theme: 'primary', position: 'bottom', alignment: 'left' },
|
|
183
|
-
behavior: { autoDismiss: true, duration: 3000, returnFocusTo: bottomLeftToastButton },
|
|
184
|
-
content: {
|
|
185
|
-
title: 'Warning Alert',
|
|
186
|
-
description: 'This is a toast notification message with structured content.',
|
|
187
|
-
},
|
|
188
|
-
}"
|
|
189
|
-
/>
|
|
190
|
-
|
|
191
|
-
<DisplayToast
|
|
192
|
-
v-model="bottomCenterToastActive"
|
|
193
|
-
:config="{
|
|
194
|
-
appearance: { theme: 'secondary', position: 'bottom', alignment: 'center' },
|
|
195
|
-
behavior: { autoDismiss: true, duration: 4000, returnFocusTo: bottomCenterToastButton },
|
|
196
|
-
content: {
|
|
197
|
-
title: 'Warning Alert',
|
|
198
|
-
description: 'This is a toast notification message with structured content.',
|
|
199
|
-
},
|
|
200
|
-
}"
|
|
201
|
-
/>
|
|
202
|
-
|
|
203
|
-
<DisplayToast
|
|
204
|
-
v-model="customIconToastActive"
|
|
205
|
-
:config="{
|
|
206
|
-
appearance: { theme: 'success', position: 'top', alignment: 'left' },
|
|
207
|
-
behavior: { autoDismiss: false, returnFocusTo: customIconToastButton },
|
|
208
|
-
content: {
|
|
209
|
-
title: 'Warning Alert',
|
|
210
|
-
description: 'This is a toast notification message with structured content.',
|
|
211
|
-
},
|
|
212
|
-
}"
|
|
213
|
-
/>
|
|
214
|
-
|
|
215
|
-
<DisplayToast
|
|
216
|
-
v-model="slottedToastActive"
|
|
217
|
-
:config="{
|
|
218
|
-
appearance: { theme: 'info', position: 'top', alignment: 'right' },
|
|
219
|
-
behavior: { autoDismiss: false, returnFocusTo: slottedToastButton },
|
|
220
|
-
}"
|
|
221
|
-
>
|
|
222
|
-
<template #title>
|
|
223
|
-
<strong>New Feature Available!</strong>
|
|
224
|
-
</template>
|
|
225
|
-
<template #description>
|
|
226
|
-
You can now use title and content slots to create more structured toast notifications with better typography
|
|
227
|
-
and layout.
|
|
228
|
-
</template>
|
|
229
|
-
</DisplayToast>
|
|
230
156
|
</template>
|
|
231
157
|
</NuxtLayout>
|
|
232
158
|
</div>
|
|
233
159
|
</template>
|
|
234
160
|
|
|
235
161
|
<script setup lang="ts">
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
* This playground demonstrates:
|
|
240
|
-
* 1. Legacy examples converted to new config structure
|
|
241
|
-
* 2. New positioning capabilities (bottom left, bottom center)
|
|
242
|
-
* 3. Custom icon support through config
|
|
243
|
-
* 4. Different behavior configurations (autoDismiss, duration)
|
|
244
|
-
* 5. Return focus functionality for accessibility
|
|
245
|
-
*
|
|
246
|
-
* The new config system groups props into logical sections:
|
|
247
|
-
* - appearance: theme, position, alignment, fullWidth
|
|
248
|
-
* - behavior: autoDismiss, duration, revealDuration, returnFocusTo
|
|
249
|
-
* - content: text, customIcon
|
|
250
|
-
*
|
|
251
|
-
* The returnFocusTo property accepts an HTMLElement or ComponentPublicInstance
|
|
252
|
-
* and will focus that element when the toast is dismissed, improving accessibility.
|
|
253
|
-
*/
|
|
254
|
-
|
|
255
|
-
definePageMeta({
|
|
256
|
-
layout: false,
|
|
257
|
-
});
|
|
162
|
+
import type { DisplayToastTheme, DisplayToastPosition, DisplayToastAlignment } from "~/types/components";
|
|
163
|
+
|
|
164
|
+
definePageMeta({ layout: false });
|
|
258
165
|
|
|
259
166
|
useHead({
|
|
260
|
-
title: "DisplayToast",
|
|
261
|
-
meta: [
|
|
262
|
-
|
|
263
|
-
name: "description",
|
|
264
|
-
content: "DisplayToast Meta description content",
|
|
265
|
-
},
|
|
266
|
-
],
|
|
267
|
-
bodyAttrs: {
|
|
268
|
-
class: "displayToast-page",
|
|
269
|
-
},
|
|
167
|
+
title: "DisplayToast Masked / DisplayToastProvider",
|
|
168
|
+
meta: [{ name: "description", content: "DisplayToast Masked component demo" }],
|
|
169
|
+
bodyAttrs: { class: "displayToast-page" },
|
|
270
170
|
});
|
|
271
171
|
|
|
272
|
-
|
|
273
|
-
const
|
|
274
|
-
const secondToastActive = ref(false);
|
|
275
|
-
const thirdToastActive = ref(false);
|
|
276
|
-
const fourthToastActive = ref(false);
|
|
277
|
-
const bottomLeftToastActive = ref(false);
|
|
278
|
-
const bottomCenterToastActive = ref(false);
|
|
279
|
-
const customIconToastActive = ref(false);
|
|
280
|
-
const slottedToastActive = ref(false);
|
|
281
|
-
|
|
282
|
-
// Template refs for focus return
|
|
283
|
-
const firstToastButton = useTemplateRef<HTMLButtonElement>("firstToastButton");
|
|
284
|
-
const secondToastButton = useTemplateRef<HTMLButtonElement>("secondToastButton");
|
|
285
|
-
const thirdToastButton = useTemplateRef<HTMLButtonElement>("thirdToastButton");
|
|
286
|
-
const fourthToastButton = useTemplateRef<HTMLButtonElement>("fourthToastButton");
|
|
287
|
-
const bottomLeftToastButton = useTemplateRef<HTMLButtonElement>("bottomLeftToastButton");
|
|
288
|
-
const bottomCenterToastButton = useTemplateRef<HTMLButtonElement>("bottomCenterToastButton");
|
|
289
|
-
const customIconToastButton = useTemplateRef<HTMLButtonElement>("customIconToastButton");
|
|
290
|
-
const slottedToastButton = useTemplateRef<HTMLButtonElement>("slottedToastButton");
|
|
291
|
-
|
|
292
|
-
const triggerFirstToast = () => {
|
|
293
|
-
firstToastActive.value = true;
|
|
294
|
-
};
|
|
172
|
+
const isDev = import.meta.dev;
|
|
173
|
+
const { show } = useToastQueue();
|
|
295
174
|
|
|
296
|
-
const
|
|
297
|
-
|
|
298
|
-
|
|
175
|
+
const themes = ["info", "success", "warning", "error"] as const;
|
|
176
|
+
const positions = ["top", "bottom"] as const;
|
|
177
|
+
const alignments = ["left", "center", "right"] as const;
|
|
178
|
+
const durations = [2000, 3000, 5000, 8000] as const;
|
|
299
179
|
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
180
|
+
const qaTheme = ref<DisplayToastTheme>("info");
|
|
181
|
+
const qaPosition = ref<DisplayToastPosition>("top");
|
|
182
|
+
const qaAlignment = ref<DisplayToastAlignment>("right");
|
|
183
|
+
const qaIsMasked = ref(true);
|
|
184
|
+
const qaFullWidth = ref(false);
|
|
185
|
+
const qaAutoDismiss = ref(true);
|
|
186
|
+
const qaDuration = ref(5000);
|
|
187
|
+
const qaMaxVisible = ref(1);
|
|
303
188
|
|
|
304
|
-
const
|
|
305
|
-
|
|
189
|
+
const messages: Record<DisplayToastTheme, { title: string; description: string }> = {
|
|
190
|
+
info: { title: "Information", description: "This is an informational notification." },
|
|
191
|
+
success: { title: "Success!", description: "Your action completed successfully." },
|
|
192
|
+
warning: { title: "Warning", description: "Please review this before continuing." },
|
|
193
|
+
error: { title: "Error", description: "Something went wrong. Please try again." },
|
|
306
194
|
};
|
|
307
195
|
|
|
308
|
-
const
|
|
309
|
-
|
|
196
|
+
const triggerToast = () => {
|
|
197
|
+
show({
|
|
198
|
+
appearance: { theme: qaTheme.value, masked: qaIsMasked.value },
|
|
199
|
+
behavior: { autoDismiss: qaAutoDismiss.value, duration: qaDuration.value },
|
|
200
|
+
content: messages[qaTheme.value],
|
|
201
|
+
});
|
|
310
202
|
};
|
|
311
203
|
|
|
312
|
-
const
|
|
313
|
-
|
|
204
|
+
const queueMultiple = () => {
|
|
205
|
+
themes.forEach((theme) => {
|
|
206
|
+
show({
|
|
207
|
+
appearance: { theme, masked: qaIsMasked.value },
|
|
208
|
+
behavior: { autoDismiss: qaAutoDismiss.value, duration: qaDuration.value },
|
|
209
|
+
content: messages[theme],
|
|
210
|
+
});
|
|
211
|
+
});
|
|
314
212
|
};
|
|
213
|
+
</script>
|
|
315
214
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
215
|
+
<style lang="css">
|
|
216
|
+
.demo-buttons {
|
|
217
|
+
display: flex;
|
|
218
|
+
flex-wrap: wrap;
|
|
219
|
+
gap: 1.2rem;
|
|
220
|
+
}
|
|
319
221
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
222
|
+
.displayToast-page {
|
|
223
|
+
.qa-panel {
|
|
224
|
+
background: oklch(15% 0 0);
|
|
225
|
+
color: white;
|
|
226
|
+
font-size: 1.3rem;
|
|
227
|
+
margin-block: 1.2rem;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.qa-panel__details {
|
|
231
|
+
padding: 1rem 2rem;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.qa-panel__summary {
|
|
235
|
+
cursor: pointer;
|
|
236
|
+
display: flex;
|
|
237
|
+
align-items: center;
|
|
238
|
+
gap: 1.6rem;
|
|
239
|
+
list-style: none;
|
|
240
|
+
user-select: none;
|
|
241
|
+
|
|
242
|
+
&::-webkit-details-marker {
|
|
243
|
+
display: none;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.qa-panel__title {
|
|
248
|
+
font-weight: 600;
|
|
249
|
+
font-size: 1.1rem;
|
|
250
|
+
text-transform: uppercase;
|
|
251
|
+
letter-spacing: 0.08em;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.qa-panel__status {
|
|
255
|
+
font-family: monospace;
|
|
256
|
+
font-size: 1.2rem;
|
|
257
|
+
background: oklch(0% 0 0 / 0.3);
|
|
258
|
+
padding: 0.2rem 0.8rem;
|
|
259
|
+
border-radius: 0.4rem;
|
|
260
|
+
user-select: text;
|
|
261
|
+
cursor: text;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.qa-panel__body {
|
|
265
|
+
display: flex;
|
|
266
|
+
flex-wrap: wrap;
|
|
267
|
+
gap: 2.4rem;
|
|
268
|
+
padding-block: 1.2rem 0.4rem;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.qa-panel__group {
|
|
272
|
+
display: flex;
|
|
273
|
+
flex-direction: column;
|
|
274
|
+
gap: 0.6rem;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.qa-panel__label {
|
|
278
|
+
font-size: 1.1rem;
|
|
279
|
+
text-transform: uppercase;
|
|
280
|
+
letter-spacing: 0.08em;
|
|
281
|
+
opacity: 0.55;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.qa-panel__chips {
|
|
285
|
+
display: flex;
|
|
286
|
+
flex-wrap: wrap;
|
|
287
|
+
gap: 0.4rem;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.qa-panel__chip {
|
|
291
|
+
font-family: monospace;
|
|
292
|
+
font-size: 1.2rem;
|
|
293
|
+
color: white;
|
|
294
|
+
background-color: oklch(0% 0 0 / 0.25);
|
|
295
|
+
border: 1px solid oklch(100% 0 0 / 0.18);
|
|
296
|
+
padding: 0.3rem 1rem;
|
|
297
|
+
border-radius: 0.4rem;
|
|
298
|
+
cursor: pointer;
|
|
299
|
+
transition: background-color 0.15s;
|
|
300
|
+
|
|
301
|
+
&:hover {
|
|
302
|
+
background-color: oklch(0% 0 0 / 0.4);
|
|
303
|
+
}
|
|
324
304
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
margin-bottom: 1rem;
|
|
305
|
+
&.is-active {
|
|
306
|
+
background-color: oklch(55% 0.18 240);
|
|
307
|
+
border-color: oklch(55% 0.18 240);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
331
310
|
}
|
|
332
311
|
</style>
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<AlertMaskCore
|
|
10
10
|
:config="{
|
|
11
11
|
backgroundColour: 'rgba(0,0,0,0.25)',
|
|
12
|
-
borderColour: 'var(--orange-
|
|
12
|
+
borderColour: 'var(--orange-06)',
|
|
13
13
|
radiusLeft: 12,
|
|
14
14
|
radiusRight: 4,
|
|
15
15
|
borderLeft: 12,
|
|
@@ -23,6 +23,27 @@
|
|
|
23
23
|
<p>Constant-radius masked border demo, and some more text</p>
|
|
24
24
|
</div>
|
|
25
25
|
</AlertMaskCore>
|
|
26
|
+
|
|
27
|
+
<div class="test-mask-element">
|
|
28
|
+
<AlertMaskCore
|
|
29
|
+
:left-border-only="true"
|
|
30
|
+
:config="{
|
|
31
|
+
backgroundColour: 'rgba(0,0,0,0.25)',
|
|
32
|
+
borderColour: 'var(--red-06)',
|
|
33
|
+
radiusLeft: 12,
|
|
34
|
+
radiusRight: 4,
|
|
35
|
+
borderLeft: 12,
|
|
36
|
+
borderTop: 1,
|
|
37
|
+
borderRight: 1,
|
|
38
|
+
borderBottom: 1,
|
|
39
|
+
}"
|
|
40
|
+
:style-class-passthrough="['test-alert']"
|
|
41
|
+
>
|
|
42
|
+
<div class="some-local-class">
|
|
43
|
+
<p>Compact</p>
|
|
44
|
+
</div>
|
|
45
|
+
</AlertMaskCore>
|
|
46
|
+
</div>
|
|
26
47
|
</div>
|
|
27
48
|
</PageRow>
|
|
28
49
|
</template>
|
|
@@ -67,12 +88,13 @@ useHead({
|
|
|
67
88
|
|
|
68
89
|
.alert-mask-core {
|
|
69
90
|
&.test-alert {
|
|
70
|
-
width: 600px;
|
|
91
|
+
/* width: 600px; */
|
|
71
92
|
|
|
72
93
|
.alert-mask-content-slot {
|
|
73
94
|
.some-local-class {
|
|
74
95
|
color: white;
|
|
75
|
-
padding:
|
|
96
|
+
padding-block: 0.4rem;
|
|
97
|
+
padding-inline: 0.8rem;
|
|
76
98
|
}
|
|
77
99
|
}
|
|
78
100
|
}
|