@cnamts/synapse 1.0.20 → 1.0.21
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/dist/{DateFilter-XURUmpMl.js → DateFilter-uN8OURoP.js} +1 -1
- package/dist/{NumberFilter-BZc0O8wV.js → NumberFilter-sm1dQNQi.js} +1 -1
- package/dist/{PeriodFilter-ZNdXcl3p.js → PeriodFilter-Cklsxnh9.js} +1 -1
- package/dist/{SelectFilter-DshYU5OK.js → SelectFilter-CWefj27Z.js} +1 -1
- package/dist/{TextFilter-D_c5dRPl.js → TextFilter-Ddyj885L.js} +1 -1
- package/dist/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.d.ts +160 -0
- package/dist/components/Customs/SyCheckBoxGroup/locales.d.ts +3 -0
- package/dist/components/Customs/SyCheckBoxGroup/types.d.ts +10 -0
- package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +1545 -2
- package/dist/components/Customs/SyRadioGroup/SyRadioGroup.d.ts +1495 -2
- package/dist/components/DeclarationAccessibilityPage/DeclarationAccessibilityPage.d.ts +60 -0
- package/dist/components/ErrorPage/ErrorPage.d.ts +1 -12
- package/dist/components/ErrorPage/locales.d.ts +18 -3
- package/dist/components/FileUpload/FileUpload.d.ts +2 -0
- package/dist/components/MaintenancePage/locales.d.ts +18 -2
- package/dist/components/NotFoundPage/locales.d.ts +20 -4
- package/dist/components/StatusPage/StatusPage.d.ts +39 -0
- package/dist/components/UploadWorkflow/UploadWorkflow.d.ts +13 -3
- package/dist/components/index.d.ts +3 -0
- package/dist/design-system-v3.js +126 -123
- package/dist/design-system-v3.umd.cjs +163 -163
- package/dist/{main-CuI6xaPq.js → main-CWniLr0s.js} +15191 -14668
- package/dist/style.css +1 -1
- package/dist/utils/theme/index.d.ts +6 -0
- package/package.json +7 -4
- package/src/components/ContextualMenu/ContextualMenu.stories.ts +0 -3
- package/src/components/ContextualMenu/accessibilite/Accessibility.mdx +67 -11
- package/src/components/CookieBanner/CookieBanner.stories.ts +11 -20
- package/src/components/CookieBanner/CookieBanner.vue +20 -5
- package/src/components/CookieBanner/accessibilite/Accessibility.mdx +67 -11
- package/src/components/CookieBanner/tests/CookieBanner.spec.ts +48 -4
- package/src/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.mdx +32 -0
- package/src/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.stories.ts +856 -0
- package/src/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.vue +334 -0
- package/src/components/Customs/SyCheckBoxGroup/accessibilite/Accessibility.mdx +243 -0
- package/src/components/Customs/SyCheckBoxGroup/locales.ts +3 -0
- package/src/components/Customs/SyCheckBoxGroup/tests/SyCheckBoxGroup.a11y.spec.ts +30 -0
- package/src/components/Customs/SyCheckBoxGroup/tests/SyCheckBoxGroup.spec.ts +152 -0
- package/src/components/Customs/SyCheckBoxGroup/types.ts +10 -0
- package/src/components/Customs/SyCheckbox/SyCheckbox.vue +16 -27
- package/src/components/Customs/SyCheckbox/accessibilite/Accessibility.mdx +1 -1
- package/src/components/Customs/SyForm/SyForm.a11y.spec.ts +1 -1
- package/src/components/Customs/SyRadioGroup/SyRadioGroup.vue +16 -43
- package/src/components/DatePicker/CalendarMode/DatePicker.vue +35 -11
- package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.stories.ts +43 -2
- package/src/components/DatePicker/DateTextInput/DateTextInput.vue +48 -21
- package/src/components/DatePicker/DateTextInput/NoCalendar.stories.ts +98 -0
- package/src/components/DeclarationAccessibilityPage/DeclarationAccessibilityPage.mdx +83 -0
- package/src/components/DeclarationAccessibilityPage/DeclarationAccessibilityPage.stories.ts +502 -0
- package/src/components/DeclarationAccessibilityPage/DeclarationAccessibilityPage.vue +428 -0
- package/src/components/DeclarationAccessibilityPage/accessibilite/Accessibility.mdx +75 -0
- package/src/components/DeclarationAccessibilityPage/tests/DeclarationAccessibilityPage.a11y.spec.ts +53 -0
- package/src/components/DeclarationAccessibilityPage/tests/DeclarationAccessibilityPage.spec.ts +59 -0
- package/src/components/DiacriticPicker/DiacriticPicker.vue +20 -1
- package/src/components/ErrorPage/ErrorPage.mdx +6 -16
- package/src/components/ErrorPage/ErrorPage.stories.ts +16 -87
- package/src/components/ErrorPage/ErrorPage.vue +38 -125
- package/src/components/ErrorPage/accessibilite/Accessibility.mdx +68 -6
- package/src/components/ErrorPage/assets/error-ap.svg +1774 -0
- package/src/components/ErrorPage/locales.ts +21 -3
- package/src/components/ErrorPage/tests/ErrorPage.a11y.spec.ts +5 -13
- package/src/components/ErrorPage/tests/ErrorPage.spec.ts +2 -41
- package/src/components/ErrorPage/tests/__snapshots__/ErrorPage.spec.ts.snap +8 -266
- package/src/components/FileUpload/FileUpload.vue +5 -0
- package/src/components/FooterBar/FooterBar.stories.ts +18 -14
- package/src/components/FooterBar/defaultSocialMediaLinks.ts +6 -4
- package/src/components/MaintenancePage/MaintenancePage.mdx +1 -1
- package/src/components/MaintenancePage/MaintenancePage.vue +15 -7
- package/src/components/MaintenancePage/accessibilite/Accessibility.mdx +61 -6
- package/src/components/MaintenancePage/assets/maintenance-ap.svg +1718 -0
- package/src/components/MaintenancePage/locales.ts +24 -3
- package/src/components/MaintenancePage/tests/MaintenancePage.a11y.spec.ts +75 -3
- package/src/components/MaintenancePage/tests/MaintenancePage.spec.ts +42 -2
- package/src/components/MaintenancePage/tests/__snapshots__/MaintenancePage.spec.ts.snap +3 -2
- package/src/components/NotFoundPage/NotFoundPage.mdx +1 -1
- package/src/components/NotFoundPage/NotFoundPage.stories.ts +3 -3
- package/src/components/NotFoundPage/NotFoundPage.vue +16 -11
- package/src/components/NotFoundPage/accessibilite/Accessibility.mdx +78 -6
- package/src/components/NotFoundPage/assets/not-found-ap.svg +2061 -0
- package/src/components/NotFoundPage/locales.ts +24 -4
- package/src/components/NotFoundPage/tests/NotFoundPage.a11y.spec.ts +168 -4
- package/src/components/NotFoundPage/tests/NotFoundPage.spec.ts +100 -12
- package/src/components/NotFoundPage/tests/__snapshots__/NotFoundPage.spec.ts.snap +2 -2
- package/src/components/NotificationBar/NotificationBar.mdx +2 -2
- package/src/components/NotificationBar/accessibilite/Accessibility.mdx +68 -8
- package/src/components/PageContainer/tests/PageContainer.a11y.spec.ts +14 -7
- package/src/components/PhoneField/PhoneField.stories.ts +46 -38
- package/src/components/SocialMediaLinks/DefaultSocialMediaLinks.ts +6 -4
- package/src/components/SocialMediaLinks/SocialMediaLinks.mdx +7 -5
- package/src/components/SocialMediaLinks/SocialMediaLinks.stories.ts +17 -13
- package/src/components/SocialMediaLinks/SocialMediaLinks.vue +9 -1
- package/src/components/SocialMediaLinks/accessibilite/Accessibility.mdx +63 -11
- package/src/components/SocialMediaLinks/tests/DefaultSocialMediaLinks.spec.ts +5 -5
- package/src/components/SocialMediaLinks/tests/SocialMediaLinks.a11y.spec.ts +59 -0
- package/src/components/SocialMediaLinks/tests/SocialMediaLinks.spec.ts +9 -7
- package/src/components/StatusPage/StatusPage.mdx +22 -0
- package/src/components/StatusPage/StatusPage.stories.ts +193 -0
- package/src/components/StatusPage/StatusPage.vue +145 -0
- package/src/components/StatusPage/accessibilite/Accessibility.mdx +81 -0
- package/src/components/StatusPage/tests/StatusPage.a11y.spec.ts +29 -0
- package/src/components/StatusPage/tests/StatusPage.spec.ts +50 -0
- package/src/components/StatusPage/tests/__snapshots__/StatusPage.spec.ts.snap +270 -0
- package/src/components/TableToolbar/TableToolbar.stories.ts +6 -6
- package/src/components/TableToolbar/TableToolbar.vue +1 -1
- package/src/components/TableToolbar/tests/__snapshots__/TableToolbar.spec.ts.snap +0 -5
- package/src/components/UploadWorkflow/UploadWorkflow.mdx +11 -1
- package/src/components/UploadWorkflow/UploadWorkflow.stories.ts +107 -3
- package/src/components/UploadWorkflow/UploadWorkflow.vue +35 -24
- package/src/components/UploadWorkflow/tests/UploadWorkflow.spec.ts +48 -0
- package/src/components/UploadWorkflow/tests/__snapshots__/UploadWorkflow.spec.ts.snap +9 -5
- package/src/components/UploadWorkflow/useFileList.ts +7 -0
- package/src/components/index.ts +3 -0
- package/src/composables/rules/tests/useFieldValidation.spec.ts +39 -3
- package/src/composables/rules/useFieldValidation.ts +24 -9
- package/src/stories/Accessibilite/KitDePreAudit/Preaudit.mdx +7 -0
- package/src/utils/theme/index.ts +19 -0
- package/src/utils/theme/tests/useThemeLocales.spec.ts +245 -0
- package/dist/components/MaintenancePage/index.d.ts +0 -2
- package/src/components/Customs/SyPagination/tests/SyPagination.a11y.spec.ts +0 -27
- package/src/components/Customs/SyTabs/tests/SyTabs.a11y.spec.ts +0 -51
- package/src/components/DataListItem/tests/DataListItem.a11y.spec.ts +0 -31
- package/src/components/DatePicker/CalendarMode/tests/DatePicker.a11y.spec.ts +0 -27
- package/src/components/DatePicker/ComplexDatePicker/tests/ComplexDatePicker.a11y.spec.ts +0 -26
- package/src/components/DatePicker/DateTextInput/tests/DateTextInput.a11y.spec.ts +0 -27
- package/src/components/DownloadBtn/tests/DownloadBtn.a11y.spec.ts +0 -26
- package/src/components/ExternalLinks/tests/ExternalLinks.a11y.spec.ts +0 -39
- package/src/components/HeaderNavigationBar/tests/HeaderNavigationBar.a11y.spec.ts +0 -45
- package/src/components/HeaderToolbar/tests/HeaderToolbar.a11y.spec.ts +0 -25
- package/src/components/LunarCalendar/tests/LunarCalendar.a11y.spec.ts +0 -31
- package/src/components/MaintenancePage/index.ts +0 -3
- package/src/components/PageContainer/Accessibilite/AccessibilityGuide.mdx +0 -0
- package/src/components/PaginatedTable/tests/PaginatedTable.a11y.spec.ts +0 -43
- package/src/components/PhoneField/tests/PhoneField.a11y.spec.ts +0 -34
- /package/src/components/NotFoundPage/assets/{not-found.svg → not-found-cnam.svg} +0 -0
- /package/src/components/PageContainer/{Accessibilite → accessibilite}/Accessibility.mdx +0 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
|
+
import StatusPage from './StatusPage.vue'
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'Templates/StatusPage',
|
|
6
|
+
component: StatusPage,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'fullscreen',
|
|
9
|
+
},
|
|
10
|
+
argTypes: {
|
|
11
|
+
'code': {
|
|
12
|
+
description: 'Code d\'erreur affiché en premier plan',
|
|
13
|
+
},
|
|
14
|
+
'codeErrorText': {
|
|
15
|
+
description: 'Text affiché avant le code d\'erreur pour les outils d\'accessibilité',
|
|
16
|
+
table: {
|
|
17
|
+
defaultValue: {
|
|
18
|
+
summary: 'Code d\'erreur\xa0: ',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
'additional-content': {
|
|
23
|
+
control: {
|
|
24
|
+
type: 'text',
|
|
25
|
+
},
|
|
26
|
+
table: {
|
|
27
|
+
type: {
|
|
28
|
+
summary: '{}',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
'action': {
|
|
33
|
+
control: {
|
|
34
|
+
type: 'text',
|
|
35
|
+
},
|
|
36
|
+
table: {
|
|
37
|
+
type: {
|
|
38
|
+
summary: '{}',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
'illustration': {
|
|
43
|
+
control: {
|
|
44
|
+
type: 'text',
|
|
45
|
+
},
|
|
46
|
+
table: {
|
|
47
|
+
type: {
|
|
48
|
+
summary: '{}',
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
} satisfies Meta<typeof StatusPage>
|
|
54
|
+
|
|
55
|
+
export default meta
|
|
56
|
+
|
|
57
|
+
type Story = StoryObj<typeof StatusPage>
|
|
58
|
+
|
|
59
|
+
export const Default: Story = {
|
|
60
|
+
args: {
|
|
61
|
+
pageTitle: 'une erreur est survenue',
|
|
62
|
+
code: '500',
|
|
63
|
+
message: 'Une erreur est survenue de notre côté, veuillez réessayer plus tard. Si le problème persiste veuillez nous contacter par téléphone au 3646',
|
|
64
|
+
},
|
|
65
|
+
parameters: {
|
|
66
|
+
sourceCode: [
|
|
67
|
+
{
|
|
68
|
+
name: 'Template',
|
|
69
|
+
code: `
|
|
70
|
+
<template>
|
|
71
|
+
<div style="padding: 20px; background: rgb(231, 236, 245)">
|
|
72
|
+
<StatusPage
|
|
73
|
+
page-title="une erreur est survenue"
|
|
74
|
+
code="500"
|
|
75
|
+
message="Une erreur est survenue de notre côté, veuillez réessayer plus tard. Si le problème persiste veuillez nous contacter par téléphone au 3646"
|
|
76
|
+
>
|
|
77
|
+
</div>
|
|
78
|
+
</template>
|
|
79
|
+
`,
|
|
80
|
+
}, {
|
|
81
|
+
name: 'Script',
|
|
82
|
+
code: `
|
|
83
|
+
<script setup lang="ts">
|
|
84
|
+
import { StatusPage } from '@cnamts/synapse'
|
|
85
|
+
</script>
|
|
86
|
+
|
|
87
|
+
`,
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
decorators: [
|
|
92
|
+
() => ({ template: '<div style="padding: 20px; background: rgb(231, 236, 245)"><story /></div>' }),
|
|
93
|
+
],
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export const WithLink: Story = {
|
|
97
|
+
args: {
|
|
98
|
+
...Default.args,
|
|
99
|
+
btnHref: '/',
|
|
100
|
+
btnText: 'Retour à l\'accueil',
|
|
101
|
+
},
|
|
102
|
+
parameters: {
|
|
103
|
+
sourceCode: [
|
|
104
|
+
{
|
|
105
|
+
name: 'Template',
|
|
106
|
+
code: `
|
|
107
|
+
<template>
|
|
108
|
+
<div style="padding: 20px; background: rgb(231, 236, 245)">
|
|
109
|
+
<StatusPage
|
|
110
|
+
page-title="une erreur est survenue"
|
|
111
|
+
code="500"
|
|
112
|
+
message="Une erreur est survenue de notre côté, veuillez réessayer plus tard. Si le problème persiste veuillez nous contacter par téléphone au 3646"
|
|
113
|
+
btn-href=""
|
|
114
|
+
btn-text="Retour à l'accueil"
|
|
115
|
+
>
|
|
116
|
+
</div>
|
|
117
|
+
</template>
|
|
118
|
+
`,
|
|
119
|
+
}, {
|
|
120
|
+
name: 'Script',
|
|
121
|
+
code: `
|
|
122
|
+
<script setup lang="ts">
|
|
123
|
+
import { StatusPage } from '@cnamts/synapse'
|
|
124
|
+
</script>
|
|
125
|
+
|
|
126
|
+
`,
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
},
|
|
130
|
+
decorators: [
|
|
131
|
+
() => ({ template: '<div style="padding: 20px; background: rgb(231, 236, 245)"><story /></div>' }),
|
|
132
|
+
],
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export const CustomIllustration: Story = {
|
|
136
|
+
args: {
|
|
137
|
+
...Default.args,
|
|
138
|
+
btnHref: '/',
|
|
139
|
+
btnText: 'Retour à l\'accueil',
|
|
140
|
+
},
|
|
141
|
+
parameters: {
|
|
142
|
+
sourceCode: [
|
|
143
|
+
{
|
|
144
|
+
name: 'Template',
|
|
145
|
+
code: `
|
|
146
|
+
<template>
|
|
147
|
+
<div style="padding: 20px; background: rgb(231, 236, 245)">
|
|
148
|
+
<StatusPage
|
|
149
|
+
page-title="une erreur est survenue"
|
|
150
|
+
code="500"
|
|
151
|
+
message="Une erreur est survenue de notre côté, veuillez réessayer plus tard."
|
|
152
|
+
btn-href="/"
|
|
153
|
+
btn-text="Retour à l'accueil"
|
|
154
|
+
>
|
|
155
|
+
<template #illustration>
|
|
156
|
+
<div style="width: 260px; height: 200px; display: grid; place-items: center; border-radius: 12px; background: white; border: 2px dashed #0D419A;">
|
|
157
|
+
<span style="font-weight: 700; color: #0D419A;">Illustration</span>
|
|
158
|
+
</div>
|
|
159
|
+
</template>
|
|
160
|
+
</StatusPage>
|
|
161
|
+
</div>
|
|
162
|
+
</template>
|
|
163
|
+
`,
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
name: 'Script',
|
|
167
|
+
code: `
|
|
168
|
+
<script setup lang="ts">
|
|
169
|
+
import { StatusPage } from '@cnamts/synapse'
|
|
170
|
+
</script>
|
|
171
|
+
`,
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
},
|
|
175
|
+
decorators: [
|
|
176
|
+
() => ({ template: '<div style="padding: 20px; background: rgb(231, 236, 245)"><story /></div>' }),
|
|
177
|
+
],
|
|
178
|
+
render: args => ({
|
|
179
|
+
components: { StatusPage },
|
|
180
|
+
setup() {
|
|
181
|
+
return { args }
|
|
182
|
+
},
|
|
183
|
+
template: `
|
|
184
|
+
<StatusPage v-bind="args">
|
|
185
|
+
<template #illustration>
|
|
186
|
+
<div style="width: 260px; height: 200px; display: grid; place-items: center; border-radius: 12px; background: white; border: 2px dashed #0D419A;">
|
|
187
|
+
<span style="font-weight: 700; color: #0D419A;">Illustration</span>
|
|
188
|
+
</div>
|
|
189
|
+
</template>
|
|
190
|
+
</StatusPage>
|
|
191
|
+
`,
|
|
192
|
+
}),
|
|
193
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { RouteRecordRaw } from 'vue-router'
|
|
3
|
+
import PageContainer from '../PageContainer/PageContainer.vue'
|
|
4
|
+
|
|
5
|
+
type MessagePart =
|
|
6
|
+
| { type: 'text', value: string }
|
|
7
|
+
| { type: 'phone', value: string }
|
|
8
|
+
|
|
9
|
+
// Fonction pour formater le message et ajouter des liens tel: aux numéros de téléphone
|
|
10
|
+
const splitMessage = (message?: string): MessagePart[] => {
|
|
11
|
+
// Regex pour détecter les numéros de téléphone
|
|
12
|
+
if (!message)
|
|
13
|
+
return []
|
|
14
|
+
|
|
15
|
+
const regex = /\b(\d{4}|\d{10})\b/g
|
|
16
|
+
const parts: MessagePart[] = []
|
|
17
|
+
let lastIndex = 0
|
|
18
|
+
let match: RegExpExecArray | null
|
|
19
|
+
|
|
20
|
+
while ((match = regex.exec(message)) !== null) {
|
|
21
|
+
if (match.index > lastIndex) {
|
|
22
|
+
parts.push({
|
|
23
|
+
type: 'text',
|
|
24
|
+
value: message.slice(lastIndex, match.index),
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
parts.push({
|
|
29
|
+
type: 'phone',
|
|
30
|
+
value: match[1]!,
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
lastIndex = regex.lastIndex
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (lastIndex < message.length) {
|
|
37
|
+
parts.push({
|
|
38
|
+
type: 'text',
|
|
39
|
+
value: message.slice(lastIndex),
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return parts
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
withDefaults(defineProps<{
|
|
47
|
+
pageTitle?: string
|
|
48
|
+
message?: string
|
|
49
|
+
code?: string
|
|
50
|
+
codeErrorText?: string
|
|
51
|
+
btnText?: string
|
|
52
|
+
btnHref?: string
|
|
53
|
+
btnLink?: RouteRecordRaw | string
|
|
54
|
+
hideBtn?: boolean
|
|
55
|
+
}>(), {
|
|
56
|
+
pageTitle: undefined,
|
|
57
|
+
message: undefined,
|
|
58
|
+
code: undefined,
|
|
59
|
+
codeErrorText: 'Code d\'erreur\xa0: ',
|
|
60
|
+
btnText: undefined,
|
|
61
|
+
btnLink: '/',
|
|
62
|
+
btnHref: undefined,
|
|
63
|
+
hideBtn: false,
|
|
64
|
+
})
|
|
65
|
+
</script>
|
|
66
|
+
|
|
67
|
+
<template>
|
|
68
|
+
<PageContainer size="md">
|
|
69
|
+
<VCard
|
|
70
|
+
:elevation="0"
|
|
71
|
+
class="pa-6 pa-sm-16"
|
|
72
|
+
>
|
|
73
|
+
<VRow class="max-width-none">
|
|
74
|
+
<VCol
|
|
75
|
+
:sm="$slots.illustration ? 6 : 12"
|
|
76
|
+
cols="12"
|
|
77
|
+
class="order-last order-sm-first text-center text-sm-left d-flex flex-column justify-center align-sm-start"
|
|
78
|
+
>
|
|
79
|
+
<div
|
|
80
|
+
v-if="code"
|
|
81
|
+
class="sy-code text-primary mb-4"
|
|
82
|
+
>
|
|
83
|
+
<span class="d-sr-only">{{ codeErrorText }}</span>
|
|
84
|
+
{{ code }}
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<h1
|
|
88
|
+
v-if="pageTitle"
|
|
89
|
+
class="mb-2 font-weight-bold text-h5 mb-4"
|
|
90
|
+
>
|
|
91
|
+
{{ pageTitle }}
|
|
92
|
+
</h1>
|
|
93
|
+
|
|
94
|
+
<p v-if="message">
|
|
95
|
+
<template
|
|
96
|
+
v-for="(part, index) in splitMessage(message)"
|
|
97
|
+
:key="index"
|
|
98
|
+
>
|
|
99
|
+
<span v-if="part.type === 'text'">
|
|
100
|
+
{{ part.value }}
|
|
101
|
+
</span>
|
|
102
|
+
<a
|
|
103
|
+
v-else
|
|
104
|
+
:href="`tel:${part.value}`"
|
|
105
|
+
>
|
|
106
|
+
{{ part.value }}
|
|
107
|
+
</a>
|
|
108
|
+
</template>
|
|
109
|
+
</p>
|
|
110
|
+
|
|
111
|
+
<slot name="additional-content" />
|
|
112
|
+
|
|
113
|
+
<slot name="action">
|
|
114
|
+
<VBtn
|
|
115
|
+
v-if="!hideBtn && btnText && (btnLink || btnHref)"
|
|
116
|
+
:to="btnHref ? undefined : btnLink"
|
|
117
|
+
:href="btnHref"
|
|
118
|
+
color="primary"
|
|
119
|
+
class="mt-6"
|
|
120
|
+
>
|
|
121
|
+
{{ btnText }}
|
|
122
|
+
</VBtn>
|
|
123
|
+
</slot>
|
|
124
|
+
</VCol>
|
|
125
|
+
|
|
126
|
+
<VCol
|
|
127
|
+
v-if="$slots.illustration"
|
|
128
|
+
cols="12"
|
|
129
|
+
sm="6"
|
|
130
|
+
class="d-flex align-center justify-center"
|
|
131
|
+
>
|
|
132
|
+
<slot name="illustration" />
|
|
133
|
+
</VCol>
|
|
134
|
+
</VRow>
|
|
135
|
+
</VCard>
|
|
136
|
+
</PageContainer>
|
|
137
|
+
</template>
|
|
138
|
+
|
|
139
|
+
<style lang="scss" scoped>
|
|
140
|
+
.sy-code {
|
|
141
|
+
font-size: 6rem;
|
|
142
|
+
line-height: 6rem;
|
|
143
|
+
font-weight: 400;
|
|
144
|
+
}
|
|
145
|
+
</style>
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Meta, Story } from '@storybook/blocks';
|
|
2
|
+
import * as StatusPageStories from '../StatusPage.stories.ts';
|
|
3
|
+
import AccessibilityIcon from '@/common/imgs/accessibility-svgrepo-com.svg';
|
|
4
|
+
import {
|
|
5
|
+
AccessibilityGuideLayout,
|
|
6
|
+
CriteriaSection,
|
|
7
|
+
CriteriaCard,
|
|
8
|
+
DemoSection,
|
|
9
|
+
BestPracticesSection,
|
|
10
|
+
ResourcesSection,
|
|
11
|
+
} from '@/stories/accessibility/AccessibilityGuideLayout.mdx';
|
|
12
|
+
|
|
13
|
+
<Meta of={StatusPageStories} />
|
|
14
|
+
|
|
15
|
+
<AccessibilityGuideLayout
|
|
16
|
+
componentName="StatusPage"
|
|
17
|
+
iconSrc={AccessibilityIcon}
|
|
18
|
+
>
|
|
19
|
+
|
|
20
|
+
<CriteriaSection>
|
|
21
|
+
<CriteriaCard icon="🔍" title="Structure sémantique">
|
|
22
|
+
<ul>
|
|
23
|
+
<li><strong>Titre de page</strong> : le titre est rendu dans une balise <code>h1</code>, unique et descriptif</li>
|
|
24
|
+
<li><strong>Code d'erreur</strong> : le code (ex. <code>500</code>, <code>404</code>) est précédé du texte masqué visuellement <code>codeErrorText</code> (par défaut <em>"Code d'erreur : "</em>) pour les lecteurs d'écran</li>
|
|
25
|
+
<li><strong>Rôles ARIA hérités</strong> via <code>PageContainer</code> :</li>
|
|
26
|
+
<ul>
|
|
27
|
+
<li>exemple : <code>role="main"</code> représente le contenu principal de la page</li>
|
|
28
|
+
</ul>
|
|
29
|
+
</ul>
|
|
30
|
+
</CriteriaCard>
|
|
31
|
+
|
|
32
|
+
<CriteriaCard icon="🔗" title="Liens et boutons">
|
|
33
|
+
<ul>
|
|
34
|
+
<li><strong>Numéros de téléphone</strong> : les numéros de 4 ou 10 chiffres (ex. <code>3646</code>) sont automatiquement transformés en liens <code>tel:</code> cliquables et vocalisables</li>
|
|
35
|
+
<li><strong>Bouton de retour</strong> : rendu via <code>btn-href</code> (balise <code>a</code>) ou <code>btn-link</code> (balise <code>router-link</code>)</li>
|
|
36
|
+
<li><strong>Texte du bouton</strong> : doit être explicite et décrire la destination, ex. <em>"Retour à l'accueil"</em></li>
|
|
37
|
+
<li><strong>Masquage du bouton</strong> : la prop <code>hide-btn</code> permet de masquer le bouton si une alternative de navigation est présente</li>
|
|
38
|
+
</ul>
|
|
39
|
+
</CriteriaCard>
|
|
40
|
+
|
|
41
|
+
<CriteriaCard icon="🖼️" title="Illustration">
|
|
42
|
+
<ul>
|
|
43
|
+
<li><strong>Image décorative</strong> : l'illustration doit avoir <code>alt=""</code> et <code>aria-hidden="true"</code> car elle est purement décorative</li>
|
|
44
|
+
<li><strong>Slot illustration</strong> : si une illustration personnalisée est fournie via le slot <code>#illustration</code>, les mêmes règles s'appliquent</li>
|
|
45
|
+
<li><strong>Mise en page adaptive</strong> : la colonne illustration n'est affichée que si le slot est fourni, évitant des zones vides</li>
|
|
46
|
+
</ul>
|
|
47
|
+
</CriteriaCard>
|
|
48
|
+
|
|
49
|
+
<CriteriaCard icon="📝" title="Contenu additionnel">
|
|
50
|
+
<ul>
|
|
51
|
+
<li><strong>Slot <code>additional-content</code></strong> : destiné à du contenu textuel complémentaire (ex. identifiant de support), doit rester lisible par les lecteurs d'écran</li>
|
|
52
|
+
<li><strong>Slot <code>action</code></strong> : permet d'ajouter des actions supplémentaires accessibles au clavier</li>
|
|
53
|
+
</ul>
|
|
54
|
+
</CriteriaCard>
|
|
55
|
+
</CriteriaSection>
|
|
56
|
+
|
|
57
|
+
<DemoSection title="Avec illustration personnalisée" componentName="StatusPage">
|
|
58
|
+
<Story of={StatusPageStories.CustomIllustration} />
|
|
59
|
+
</DemoSection>
|
|
60
|
+
|
|
61
|
+
<BestPracticesSection>
|
|
62
|
+
<ul>
|
|
63
|
+
<li>Toujours renseigner <code>page-title</code> avec un titre clair et unique décrivant l'erreur</li>
|
|
64
|
+
<li>Personnaliser <code>code-error-text</code> si nécessaire pour un contexte métier spécifique</li>
|
|
65
|
+
<li>Fournir un <code>btn-text</code> explicite — éviter les libellés génériques comme <em>"Cliquez ici"</em></li>
|
|
66
|
+
<li>Ne pas masquer le bouton (<code>hide-btn</code>) sans proposer une alternative de navigation claire</li>
|
|
67
|
+
<li>Les illustrations doivent toujours être décoratives (<code>aria-hidden="true"</code>) — ne jamais y placer d'information essentielle</li>
|
|
68
|
+
<li>Le contenu dans <code>additional-content</code> doit être lisible par les lecteurs d'écran : éviter le contenu purement visuel</li>
|
|
69
|
+
</ul>
|
|
70
|
+
</BestPracticesSection>
|
|
71
|
+
|
|
72
|
+
<ResourcesSection>
|
|
73
|
+
<ul>
|
|
74
|
+
<li><a href="https://www.w3.org/WAI/WCAG21/Understanding/info-and-relationships.html" target="_blank" style={{ color: '#0C41BD' }}>WCAG 1.3.1 – Info and Relationships</a></li>
|
|
75
|
+
<li><a href="https://www.w3.org/WAI/WCAG21/Understanding/link-purpose-in-context.html" target="_blank" style={{ color: '#0C41BD' }}>WCAG 2.4.4 – Link Purpose</a></li>
|
|
76
|
+
<li><a href="https://www.w3.org/WAI/WCAG21/Understanding/non-text-content.html" target="_blank" style={{ color: '#0C41BD' }}>WCAG 1.1.1 – Non-text Content</a></li>
|
|
77
|
+
<li><a href="https://www.w3.org/WAI/ARIA/apg/patterns/" target="_blank" style={{ color: '#0C41BD' }}>ARIA Authoring Practices Guide</a></li>
|
|
78
|
+
</ul>
|
|
79
|
+
</ResourcesSection>
|
|
80
|
+
|
|
81
|
+
</AccessibilityGuideLayout>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
|
|
3
|
+
import { describe, it } from 'vitest'
|
|
4
|
+
import { mount } from '@vue/test-utils'
|
|
5
|
+
import { axe } from 'vitest-axe'
|
|
6
|
+
import { assertNoA11yViolations } from '@tests/unit/accessibility/axeUtils'
|
|
7
|
+
import StatusPage from '../StatusPage.vue'
|
|
8
|
+
|
|
9
|
+
// Scénario d’accessibilité : page d’erreur avec titre, message, code
|
|
10
|
+
// et bouton de retour vers la page d’accueil.
|
|
11
|
+
|
|
12
|
+
describe('StatusPage – accessibility (axe)', () => {
|
|
13
|
+
it('has no obvious axe violations with title, message and action button', async () => {
|
|
14
|
+
const wrapper = mount(StatusPage, {
|
|
15
|
+
props: {
|
|
16
|
+
pageTitle: 'Une erreur est survenue',
|
|
17
|
+
message: 'Un problème technique est survenu. Merci de réessayer plus tard.',
|
|
18
|
+
code: '500',
|
|
19
|
+
btnText: 'Retour à l\'accueil',
|
|
20
|
+
btnHref: 'https://www.ameli.fr',
|
|
21
|
+
},
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const results = await axe(wrapper.element as HTMLElement)
|
|
25
|
+
assertNoA11yViolations(results, 'StatusPage – default page', {
|
|
26
|
+
ignoreRules: ['region'],
|
|
27
|
+
})
|
|
28
|
+
})
|
|
29
|
+
})
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { mount } from '@vue/test-utils'
|
|
3
|
+
import StatusPage from '../StatusPage.vue'
|
|
4
|
+
|
|
5
|
+
describe('StatusPage', () => {
|
|
6
|
+
it('renders correctly', () => {
|
|
7
|
+
const wrapper = mount(StatusPage, {
|
|
8
|
+
props: {
|
|
9
|
+
pageTitle: 'Something went wrong',
|
|
10
|
+
message: 'Error message',
|
|
11
|
+
},
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
expect(wrapper.text()).toContain('Something went wrong')
|
|
15
|
+
expect(wrapper.text()).toContain('Error message')
|
|
16
|
+
expect(wrapper.html()).toMatchSnapshot()
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
it('renders correctly with undefined route', () => {
|
|
20
|
+
const wrapper = mount(StatusPage, {
|
|
21
|
+
props: {
|
|
22
|
+
code: '501',
|
|
23
|
+
pageTitle: 'Error',
|
|
24
|
+
message: 'Error message',
|
|
25
|
+
btnText: 'Go to...',
|
|
26
|
+
btnHref: 'https://google.com',
|
|
27
|
+
},
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
expect(wrapper.find('a').exists()).toBe(true)
|
|
31
|
+
expect(wrapper.html()).toMatchSnapshot()
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('uses href without router navigation when only btnHref is provided', () => {
|
|
35
|
+
const wrapper = mount(StatusPage, {
|
|
36
|
+
props: {
|
|
37
|
+
code: '401',
|
|
38
|
+
pageTitle: 'Auth error',
|
|
39
|
+
message: 'You are not authorized',
|
|
40
|
+
btnText: 'Logout',
|
|
41
|
+
btnHref: 'https://google.com',
|
|
42
|
+
},
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
const link = wrapper.find('a')
|
|
46
|
+
expect(link.exists()).toBe(true)
|
|
47
|
+
expect(link.attributes('href')).toBe('https://google.com')
|
|
48
|
+
expect(link.attributes('to')).toBeUndefined()
|
|
49
|
+
})
|
|
50
|
+
})
|