@cnamts/synapse 1.0.22 → 1.0.23

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.
Files changed (190) hide show
  1. package/dist/{DateFilter-B5n-ZkLi.js → DateFilter-Dc-gSGwk.js} +1 -1
  2. package/dist/{NumberFilter-CtiZ9uj8.js → NumberFilter-vP38Wp6j.js} +1 -1
  3. package/dist/{PeriodFilter-DzqiMb-b.js → PeriodFilter-Ba1uYUnT.js} +1 -1
  4. package/dist/{SelectFilter-BOYlF7rX.js → SelectFilter-BioGT6Nn.js} +1 -1
  5. package/dist/{TextFilter-BOFRNfcX.js → TextFilter-B84dpnoq.js} +1 -1
  6. package/dist/components/Accordion/Accordion.d.ts +13 -2
  7. package/dist/components/Accordion/composables/useAccordionState.d.ts +2 -1
  8. package/dist/components/Amelipro/AmeliproAutoCompleteField/AmeliproAutoCompleteField.d.ts +7 -7
  9. package/dist/components/Amelipro/AmeliproCheckbox/AmeliproCheckbox.d.ts +1 -1
  10. package/dist/components/Amelipro/AmeliproCustomSelector/AmeliproCustomSelector.d.ts +1 -1
  11. package/dist/components/Amelipro/AmeliproPostalAddressField/AmeliproPostalAddressField.d.ts +1 -1
  12. package/dist/components/Amelipro/AmeliproSelect/AmeliproSelect.d.ts +7 -7
  13. package/dist/components/Amelipro/AmeliproTabs/AmeliproTabs.d.ts +16 -16
  14. package/dist/components/Amelipro/AmeliproTextArea/AmeliproTextArea.d.ts +1 -1
  15. package/dist/components/Amelipro/AmeliproTextField/AmeliproTextField.d.ts +1 -1
  16. package/dist/components/Customs/Selects/SyAutocomplete/SyAutocomplete.d.ts +22 -1
  17. package/dist/components/Customs/Selects/SyAutocomplete/locales.d.ts +5 -0
  18. package/dist/components/Customs/Selects/SyInputSelect/SyInputSelect.d.ts +1 -1
  19. package/dist/components/Customs/Selects/SySelect/SySelect.d.ts +1 -1
  20. package/dist/components/Customs/Selects/SySelect/locales.d.ts +1 -0
  21. package/dist/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.d.ts +1 -1
  22. package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +1 -1
  23. package/dist/components/Customs/SyRadioGroup/SyRadioGroup.d.ts +1 -1
  24. package/dist/components/Customs/SyTextField/SyTextField.d.ts +5 -2
  25. package/dist/components/DatePicker/CalendarMode/DatePicker.d.ts +13 -9
  26. package/dist/components/DatePicker/ComplexDatePicker/ComplexDatePicker.d.ts +7 -5
  27. package/dist/components/DatePicker/DateTextInput/DateTextInput.d.ts +2 -1
  28. package/dist/components/ErrorPage/ErrorPage.d.ts +3 -1
  29. package/dist/components/FileList/UploadItem/UploadItem.d.ts +6 -0
  30. package/dist/components/FileList/UploadItem/locales.d.ts +1 -4
  31. package/dist/components/FileUpload/FileUploadContent.d.ts +2 -0
  32. package/dist/components/FileUpload/validateFiles.d.ts +2 -1
  33. package/dist/components/HeaderBar/HeaderBar.d.ts +2 -1
  34. package/dist/components/HeaderBar/HeaderLogo/HeaderLogo.d.ts +2 -1
  35. package/dist/components/HeaderNavigationBar/HeaderNavigationBar.d.ts +2 -1
  36. package/dist/components/MonthPicker/MonthPicker.d.ts +1939 -0
  37. package/dist/components/MonthPicker/MonthPickerText/MonthPickerInput.d.ts +1899 -0
  38. package/dist/components/MonthPicker/MonthPickerText/useTextField.d.ts +21 -0
  39. package/dist/components/MonthPicker/MonthPickerVisual/MonthPickerVisual.d.ts +21 -0
  40. package/dist/components/MonthPicker/MonthPickerVisual/MonthPickerVisualProps.d.ts +12 -0
  41. package/dist/components/MonthPicker/MonthPickerVisual/MonthSelector.d.ts +11 -0
  42. package/dist/components/MonthPicker/MonthPickerVisual/VisualPickerFooter.d.ts +6 -0
  43. package/dist/components/MonthPicker/MonthPickerVisual/VisualPickerHeader.d.ts +14 -0
  44. package/dist/components/MonthPicker/MonthPickerVisual/YearSelector.d.ts +14 -0
  45. package/dist/components/MonthPicker/MonthPickerVisual/useMonthGrid.d.ts +9 -0
  46. package/dist/components/MonthPicker/MonthPickerVisual/useYearGrid.d.ts +8 -0
  47. package/dist/components/MonthPicker/MonthPickerVisual/utils.d.ts +8 -0
  48. package/dist/components/MonthPicker/locales.d.ts +12 -0
  49. package/dist/components/MonthPicker/useMonthPickerValidation.d.ts +25 -0
  50. package/dist/components/NirField/NirField.d.ts +3 -1
  51. package/dist/components/NotificationBar/Notification/Notification.d.ts +3 -0
  52. package/dist/components/PasswordField/PasswordField.d.ts +1 -1
  53. package/dist/components/PeriodField/PeriodField.d.ts +29 -21
  54. package/dist/components/PhoneField/PhoneField.d.ts +2 -1
  55. package/dist/components/SyBtnMenu/SyBtnMenu.d.ts +1 -1
  56. package/dist/components/SyHeading/SyHeading.a11y.test.d.ts +1 -0
  57. package/dist/components/SyHeading/SyHeading.d.ts +4 -2
  58. package/dist/components/SyHeading/SyHeading.test.d.ts +1 -0
  59. package/dist/components/SyTextArea/SyTextArea.d.ts +1 -1
  60. package/dist/components/Tables/SyServerTable/SyServerTable.d.ts +4 -4
  61. package/dist/components/Tables/SyTable/SyTable.d.ts +4 -4
  62. package/dist/components/Tables/common/SyTablePagination.d.ts +6 -6
  63. package/dist/components/index.d.ts +1 -0
  64. package/dist/design-system-v3.js +102 -99
  65. package/dist/design-system-v3.umd.cjs +126 -126
  66. package/dist/designTokens/tokens/cnam/cnamContextual.d.ts +5 -0
  67. package/dist/{main-CEl4J8_T.js → main-aLKwdMi1.js} +11167 -10522
  68. package/dist/main.d.ts +1 -0
  69. package/dist/style.css +1 -1
  70. package/package.json +10 -4
  71. package/src/assets/apTokens.scss +2 -2
  72. package/src/assets/overrides/_btns.scss +8 -0
  73. package/src/assets/overrides/_forms.scss +9 -0
  74. package/src/assets/overrides/_icons.scss +38 -9
  75. package/src/assets/overrides/_tables.scss +19 -0
  76. package/src/components/Accordion/Accordion.mdx +23 -9
  77. package/src/components/Accordion/Accordion.stories.ts +153 -3
  78. package/src/components/Accordion/Accordion.vue +7 -6
  79. package/src/components/Accordion/composables/__tests__/useAccordionState.spec.ts +40 -12
  80. package/src/components/Accordion/composables/useAccordionState.ts +3 -4
  81. package/src/components/Accordion/tests/accordion.spec.ts +131 -19
  82. package/src/components/Amelipro/AmeliproPagination/AmeliproPagination.mdx +3 -1
  83. package/src/components/Amelipro/AmeliproPagination/AmeliproPagination.stories.ts +8 -0
  84. package/src/components/BackBtn/accessibilite/Accessibility.mdx +62 -10
  85. package/src/components/BackToTopBtn/BackToTopBtn.stories.ts +9 -3
  86. package/src/components/BackToTopBtn/accessibilite/Accessibility.mdx +86 -6
  87. package/src/components/Captcha/tests/Captcha.spec.ts +0 -29
  88. package/src/components/Captcha/tests/__snapshots__/Captcha.spec.ts.snap +2 -110
  89. package/src/components/Customs/Selects/SelectBtnField/accessibilite/Accessibility.mdx +133 -10
  90. package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.stories.ts +379 -93
  91. package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.vue +144 -83
  92. package/src/components/Customs/Selects/SyAutocomplete/accessibilite/Accessibilite.stories.ts +40 -1
  93. package/src/components/Customs/Selects/SyAutocomplete/accessibilite/Accessibility.mdx +7 -1
  94. package/src/components/Customs/Selects/SyAutocomplete/locales.ts +5 -0
  95. package/src/components/Customs/Selects/SyAutocomplete/tests/SyAutocomplete.a11y.spec.ts +96 -0
  96. package/src/components/Customs/Selects/SyAutocomplete/tests/SyAutocomplete.spec.ts +234 -9
  97. package/src/components/Customs/Selects/SyAutocomplete/utils/ariaManager.ts +13 -3
  98. package/src/components/Customs/Selects/SyAutocomplete/utils/useSelectionLogic.ts +9 -10
  99. package/src/components/Customs/Selects/SySelect/SySelect.vue +46 -3
  100. package/src/components/Customs/Selects/SySelect/locales.ts +1 -0
  101. package/src/components/Customs/SyIcon/SyIcon.vue +1 -1
  102. package/src/components/Customs/SyIcon/tests/SyIcon.a11y.spec.ts +20 -0
  103. package/src/components/Customs/SyIconButton/SyIconButton.mdx +46 -0
  104. package/src/components/Customs/SyIconButton/SyIconButton.stories.ts +184 -0
  105. package/src/components/Customs/SyIconButton/SyIconButton.vue +38 -0
  106. package/src/components/Customs/SyIconButton/accessibilite/Accessibility.mdx +64 -0
  107. package/src/components/Customs/SyIconButton/tests/SyIconButton.a11y.spec.ts +87 -0
  108. package/src/components/Customs/SyIconButton/tests/SyIconButton.spec.ts +152 -0
  109. package/src/components/Customs/SyIconButton/tests/__snapshots__/SyIconButton.spec.ts.snap +61 -0
  110. package/src/components/Customs/SyPagination/SyPagination.vue +5 -5
  111. package/src/components/Customs/SyTextField/SyTextField.vue +20 -2
  112. package/src/components/Customs/SyTextField/accessibilite/Accessibility.mdx +67 -9
  113. package/src/components/Customs/SyTextField/tests/SyTextField.a11y.spec.ts +15 -0
  114. package/src/components/Customs/SyTextField/tests/SyTextField.spec.ts +36 -0
  115. package/src/components/DataList/accessibilite/Accessibility.mdx +79 -11
  116. package/src/components/DataListGroup/accessibilite/Accessibility.mdx +80 -11
  117. package/src/components/DownloadBtn/tests/DownloadBtn.a11y.spec.ts +25 -0
  118. package/src/components/ErrorPage/ErrorPage.stories.ts +113 -19
  119. package/src/components/ErrorPage/ErrorPage.vue +17 -2
  120. package/src/components/ErrorPage/tests/ErrorPage.a11y.spec.ts +17 -0
  121. package/src/components/ErrorPage/tests/ErrorPage.spec.ts +21 -1
  122. package/src/components/ErrorPage/tests/__snapshots__/ErrorPage.spec.ts.snap +0 -1
  123. package/src/components/ExternalLinks/tests/ExternalLinks.a11y.spec.ts +23 -0
  124. package/src/components/FileList/FileList.stories.ts +51 -1
  125. package/src/components/FileList/UploadItem/UploadItem.vue +13 -6
  126. package/src/components/FileList/UploadItem/locales.ts +3 -12
  127. package/src/components/FileList/accessibilite/Accessibility.mdx +3 -0
  128. package/src/components/FileUpload/FileUpload.vue +2 -1
  129. package/src/components/FileUpload/FileUploadContent.vue +2 -1
  130. package/src/components/FileUpload/tests/FileUpload.spec.ts +47 -0
  131. package/src/components/FileUpload/validateFiles.ts +5 -2
  132. package/src/components/FranceConnectBtn/accessibilite/Accessibility.mdx +62 -9
  133. package/src/components/HeaderBar/HeaderBar.vue +2 -1
  134. package/src/components/HeaderBar/HeaderLogo/HeaderLogo.vue +2 -1
  135. package/src/components/HeaderNavigationBar/HeaderNavigationBar.vue +2 -1
  136. package/src/components/LunarCalendar/accessibilite/Accessibility.mdx +74 -8
  137. package/src/components/LunarCalendar/tests/LunarCalendar.a11y.spec.ts +163 -0
  138. package/src/components/MaintenancePage/MaintenancePage.vue +1 -1
  139. package/src/components/MaintenancePage/tests/MaintenancePage.spec.ts +4 -5
  140. package/src/components/MaintenancePage/tests/__snapshots__/MaintenancePage.spec.ts.snap +0 -1
  141. package/src/components/MonthPicker/MonthPicker.mdx +35 -0
  142. package/src/components/MonthPicker/MonthPicker.stories.ts +527 -0
  143. package/src/components/MonthPicker/MonthPicker.vue +79 -0
  144. package/src/components/MonthPicker/MonthPickerText/MonthPickerInput.vue +89 -0
  145. package/src/components/MonthPicker/MonthPickerText/useTextField.ts +27 -0
  146. package/src/components/MonthPicker/MonthPickerVisual/MonthPickerVisual.vue +154 -0
  147. package/src/components/MonthPicker/MonthPickerVisual/MonthPickerVisualProps.ts +13 -0
  148. package/src/components/MonthPicker/MonthPickerVisual/MonthSelector.vue +137 -0
  149. package/src/components/MonthPicker/MonthPickerVisual/VisualPickerFooter.vue +60 -0
  150. package/src/components/MonthPicker/MonthPickerVisual/VisualPickerHeader.vue +149 -0
  151. package/src/components/MonthPicker/MonthPickerVisual/YearSelector.vue +143 -0
  152. package/src/components/MonthPicker/MonthPickerVisual/useMonthGrid.ts +45 -0
  153. package/src/components/MonthPicker/MonthPickerVisual/useYearGrid.ts +45 -0
  154. package/src/components/MonthPicker/MonthPickerVisual/utils.ts +17 -0
  155. package/src/components/MonthPicker/accessibilite/Accessibility.mdx +59 -0
  156. package/src/components/MonthPicker/locales.ts +12 -0
  157. package/src/components/MonthPicker/tests/MonthPicker.a11y.spec.ts +71 -0
  158. package/src/components/MonthPicker/tests/MonthPicker.spec.ts +1248 -0
  159. package/src/components/MonthPicker/tests/__snapshots__/MonthPicker.spec.ts.snap +2545 -0
  160. package/src/components/MonthPicker/useMonthPickerValidation.ts +30 -0
  161. package/src/components/NirField/NirField.mdx +1 -2
  162. package/src/components/NirField/NirField.stories.ts +66 -6
  163. package/src/components/NotFoundPage/tests/NotFoundPage.spec.ts +2 -3
  164. package/src/components/NotFoundPage/tests/__snapshots__/NotFoundPage.spec.ts.snap +22 -14
  165. package/src/components/NotificationBar/Notification/Notification.vue +3 -1
  166. package/src/components/NotificationBar/NotificationBar.stories.ts +154 -0
  167. package/src/components/NotificationBar/tests/NotificationBar.a11y.spec.ts +26 -0
  168. package/src/components/NotificationBar/tests/NotificationBar.spec.ts +60 -0
  169. package/src/components/RangeField/accessibilite/Accessibility.mdx +79 -11
  170. package/src/components/SkipLink/tests/SkipLink.a11y.spec.ts +23 -0
  171. package/src/components/StatusPage/StatusPage.stories.ts +118 -0
  172. package/src/components/StatusPage/StatusPage.vue +5 -3
  173. package/src/components/StatusPage/tests/StatusPage.a11y.spec.ts +22 -0
  174. package/src/components/StatusPage/tests/StatusPage.spec.ts +22 -0
  175. package/src/components/StatusPage/tests/__snapshots__/StatusPage.spec.ts.snap +22 -14
  176. package/src/components/SubHeader/tests/SubHeader.a11y.spec.ts +20 -0
  177. package/src/components/SyAlert/SyAlert.vue +1 -0
  178. package/src/components/SyAlert/accessibilite/Accessibility.mdx +79 -9
  179. package/src/components/SyAlert/tests/SyAlert.a11y.spec.ts +23 -0
  180. package/src/components/SyHeading/SyHeading.a11y.test.ts +149 -0
  181. package/src/components/SyHeading/SyHeading.test.ts +115 -0
  182. package/src/components/SyHeading/SyHeading.vue +5 -3
  183. package/src/components/SyTextArea/accessibilite/Accessibility.mdx +80 -8
  184. package/src/components/SyTextArea/tests/SyTextArea.a11y.spec.ts +151 -0
  185. package/src/components/ToolbarContainer/tests/ToolbarContainer.a11y.spec.ts +126 -0
  186. package/src/components/UploadWorkflow/tests/__snapshots__/UploadWorkflow.spec.ts.snap +2 -2
  187. package/src/components/index.ts +1 -0
  188. package/src/composables/useFormFieldErrorHandling.ts +11 -2
  189. package/src/designTokens/tokens/cnam/cnamContextual.ts +6 -1
  190. package/src/main.ts +2 -0
@@ -199,6 +199,124 @@ export const CustomIllustration: Story = {
199
199
  }),
200
200
  }
201
201
 
202
+ export const SlotAction: Story = {
203
+ args: {
204
+ ...Default.args,
205
+ headingLevel: 1,
206
+ hideBtn: true,
207
+ },
208
+ decorators: [
209
+ () => ({ template: '<div style="padding: 20px; background: rgb(231, 236, 245)"><story /></div>' }),
210
+ ],
211
+ parameters: {
212
+ sourceCode: [
213
+ {
214
+ name: 'Template',
215
+ code: `
216
+ <template>
217
+ <div style="padding: 20px; background: rgb(231, 236, 245)">
218
+ <StatusPage
219
+ page-title="une erreur est survenue"
220
+ code="500"
221
+ message="Une erreur est survenue de notre côté, veuillez réessayer plus tard."
222
+ :hide-btn="true"
223
+ >
224
+ <template #action>
225
+ <div style="display: flex; gap: 8px; margin-top: 16px;">
226
+ <VBtn href="/" color="primary">Retour à l'accueil</VBtn>
227
+ <VBtn variant="outlined" color="primary">Déconnexion</VBtn>
228
+ </div>
229
+ </template>
230
+ </StatusPage>
231
+ </div>
232
+ </template>
233
+ `,
234
+ },
235
+ {
236
+ name: 'Script',
237
+ code: `
238
+ <script setup lang="ts">
239
+ import { StatusPage } from '@cnamts/synapse'
240
+ </script>
241
+ `,
242
+ },
243
+ ],
244
+ },
245
+ render: args => ({
246
+ components: { StatusPage },
247
+ setup() {
248
+ return { args }
249
+ },
250
+ template: `
251
+ <StatusPage v-bind="args">
252
+ <template #action>
253
+ <div style="display: flex; gap: 8px; margin-top: 16px;">
254
+ <VBtn href="/" color="primary">Retour à l'accueil</VBtn>
255
+ <VBtn variant="outlined" color="primary">Déconnexion</VBtn>
256
+ </div>
257
+ </template>
258
+ </StatusPage>
259
+ `,
260
+ }),
261
+ }
262
+
263
+ export const SlotAdditionalContent: Story = {
264
+ args: {
265
+ ...Default.args,
266
+ headingLevel: 1,
267
+ },
268
+ decorators: [
269
+ () => ({ template: '<div style="padding: 20px; background: rgb(231, 236, 245)"><story /></div>' }),
270
+ ],
271
+ parameters: {
272
+ sourceCode: [
273
+ {
274
+ name: 'Template',
275
+ code: `
276
+ <template>
277
+ <div style="padding: 20px; background: rgb(231, 236, 245)">
278
+ <StatusPage
279
+ page-title="une erreur est survenue"
280
+ code="500"
281
+ message="Une erreur est survenue de notre côté, veuillez réessayer plus tard."
282
+ >
283
+ <template #additional-content>
284
+ <p style="text-align: center; color: #555;">
285
+ Si le problème persiste, veuillez contacter le support technique.
286
+ </p>
287
+ </template>
288
+ </StatusPage>
289
+ </div>
290
+ </template>
291
+ `,
292
+ },
293
+ {
294
+ name: 'Script',
295
+ code: `
296
+ <script setup lang="ts">
297
+ import { StatusPage } from '@cnamts/synapse'
298
+ </script>
299
+ `,
300
+ },
301
+ ],
302
+ },
303
+ render: args => ({
304
+ components: { StatusPage },
305
+ setup() {
306
+ return { args }
307
+ },
308
+ template: `
309
+ <StatusPage v-bind="args">
310
+ <template #additional-content>
311
+ <p style="text-align: center; color: #555;">
312
+ Si le problème persiste, veuillez contacter le support technique.
313
+ </p>
314
+ </template>
315
+ </StatusPage>
316
+ `,
317
+ }),
318
+ }
319
+
202
320
  export const WithRole: Story = {
203
321
  args: {
204
322
  pageTitle: 'Une erreur est survenue',
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import type { RouteRecordRaw } from 'vue-router'
3
3
  import PageContainer from '../PageContainer/PageContainer.vue'
4
- import { useId } from 'vue'
4
+ import { computed, useId } from 'vue'
5
5
  import type { PageAriaRole } from '../types'
6
6
  import SyHeading from '../SyHeading/SyHeading.vue'
7
7
 
@@ -46,7 +46,7 @@
46
46
  return parts
47
47
  }
48
48
 
49
- withDefaults(defineProps<{
49
+ const props = withDefaults(defineProps<{
50
50
  pageTitle?: string
51
51
  message?: string
52
52
  code?: string
@@ -67,11 +67,13 @@
67
67
  btnLink: '/',
68
68
  btnHref: undefined,
69
69
  hideBtn: false,
70
- uniqueId: useId(),
70
+ uniqueId: undefined,
71
71
  role: undefined,
72
72
  headingLevel: 1,
73
73
  })
74
74
 
75
+ const uniqueId = computed(() => props.uniqueId ?? useId())
76
+
75
77
  const emit = defineEmits(['btn-click'])
76
78
  const emitClickEvent = (): void => {
77
79
  emit('btn-click')
@@ -27,4 +27,26 @@ describe('StatusPage – accessibility (axe)', () => {
27
27
  ignoreRules: ['region'],
28
28
  })
29
29
  })
30
+
31
+ it('has no obvious axe violations with #action slot', async () => {
32
+ const wrapper = mount(StatusPage, {
33
+ attachTo: document.body,
34
+ props: {
35
+ headingLevel: 1,
36
+ pageTitle: 'Une erreur est survenue',
37
+ message: 'Un problème technique est survenu.',
38
+ hideBtn: true,
39
+ },
40
+ slots: {
41
+ action: '<button>Retour à l\'accueil</button>',
42
+ },
43
+ })
44
+
45
+ const results = await axe(document.body)
46
+ assertNoA11yViolations(results, 'StatusPage – action slot', {
47
+ ignoreRules: ['region'],
48
+ })
49
+
50
+ wrapper.unmount()
51
+ })
30
52
  })
@@ -50,4 +50,26 @@ describe('StatusPage', () => {
50
50
  expect(link.attributes('href')).toBe('https://google.com')
51
51
  expect(link.attributes('to')).toBeUndefined()
52
52
  })
53
+
54
+ it('renders #action slot content', () => {
55
+ const wrapper = mount(StatusPage, {
56
+ props: { headingLevel: 1 },
57
+ slots: {
58
+ action: '<button>Retour à l\'accueil</button>',
59
+ },
60
+ })
61
+
62
+ expect(wrapper.html()).toContain('Retour à l\'accueil')
63
+ })
64
+
65
+ it('renders #additional-content slot content', () => {
66
+ const wrapper = mount(StatusPage, {
67
+ props: { headingLevel: 1 },
68
+ slots: {
69
+ 'additional-content': '<p>Contenu additionnel</p>',
70
+ },
71
+ })
72
+
73
+ expect(wrapper.html()).toContain('Contenu additionnel')
74
+ })
53
75
  })
@@ -1,19 +1,23 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
3
  exports[`StatusPage > renders correctly 1`] = `
4
- <div class="
5
- d-flex
6
- justify-center
7
- px-14
8
- py-10
9
- vd-page-container
10
- ">
4
+ <div
5
+ class="
6
+ d-flex
7
+ justify-center
8
+ px-14
9
+ py-10
10
+ vd-page-container
11
+ "
12
+ id="v-0-container"
13
+ >
11
14
  <div
12
15
  class="
13
16
  bg-transparent
14
17
  v-sheet
15
18
  v-theme--light
16
19
  "
20
+ id="v-0-content"
17
21
  style="width: 800px;"
18
22
  >
19
23
  <div class="
@@ -121,19 +125,23 @@ exports[`StatusPage > renders correctly 1`] = `
121
125
  `;
122
126
 
123
127
  exports[`StatusPage > renders correctly with undefined route 1`] = `
124
- <div class="
125
- d-flex
126
- justify-center
127
- px-14
128
- py-10
129
- vd-page-container
130
- ">
128
+ <div
129
+ class="
130
+ d-flex
131
+ justify-center
132
+ px-14
133
+ py-10
134
+ vd-page-container
135
+ "
136
+ id="v-0-container"
137
+ >
131
138
  <div
132
139
  class="
133
140
  bg-transparent
134
141
  v-sheet
135
142
  v-theme--light
136
143
  "
144
+ id="v-0-content"
137
145
  style="width: 800px;"
138
146
  >
139
147
  <div class="
@@ -0,0 +1,20 @@
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 SubHeader from '../SubHeader.vue'
8
+
9
+ describe('SubHeader – accessibility (axe)', () => {
10
+ it('has no obvious axe violations', async () => {
11
+ const wrapper = mount(SubHeader, {
12
+ slots: {
13
+ default: '<h1>Mon titre principal</h1>',
14
+ },
15
+ })
16
+
17
+ const results = await axe(wrapper.element as HTMLElement)
18
+ assertNoA11yViolations(results, 'SubHeader – default state')
19
+ })
20
+ })
@@ -10,6 +10,7 @@
10
10
  } from '@mdi/js'
11
11
  import type { VIcon } from 'vuetify/components'
12
12
  import SyIcon from '@/components/Customs/SyIcon/SyIcon.vue'
13
+ import { vRgaaSvgFix } from '@/directives/rgaaSvgFix'
13
14
 
14
15
  defineOptions({
15
16
  inheritAttrs: false,
@@ -1,12 +1,82 @@
1
- import { Meta, Story } from '@storybook/addon-docs';
2
- import * as SyAlertStorie from '../SyAlert.stories';
3
- import '@/stories/styles/shared.css';
1
+ import { Meta, Primary } from '@storybook/blocks';
2
+ import * as SyAlertStories from '../SyAlert.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';
4
12
 
5
- <Meta of={SyAlertStorie} />
13
+ <Meta of={SyAlertStories}/>
6
14
 
7
- <div className="header">
8
- <h1>Accessibilité</h1>
9
- </div>
15
+ <AccessibilityGuideLayout
16
+ componentName="SyAlert"
17
+ iconSrc={AccessibilityIcon}
18
+ apgHref="https://www.w3.org/WAI/ARIA/apg/patterns/alert/"
19
+ >
20
+ <div class="mt-8">
21
+ <p>Rapport d'audit manuel : <a href="/audits/SyAlert.xlsx" style={{ color:'#0C41BD' }}>Voir le rapport</a></p>
22
+ <p style={{ color: 'grey', fontSize: '14px', marginTop: '0px' }}>Correctifs associés (<a href="https://github.com/assurance-maladie-digital/design-system-v3/issues/4010" target="_blank" style={{color:'#0C41BD'}}>issue #4010</a>)</p>
23
+ </div>
10
24
 
11
- <p>Rapport d’audit manuel : <a href="/audits/SyAlert.xlsx" style={{ color:'#0C41BD' }}>Voir le rapport</a></p>
12
- <p style={{ color: 'grey', fontSize: '14px', margin: '0px' }}>Correctifs associés (<a href="https://github.com/assurance-maladie-digital/design-system-v3/issues/4010" target="_blank" style={{color:'#0C41BD'}}>issue #4010</a>)</p>
25
+ <CriteriaSection>
26
+ <CriteriaCard icon="🔍" title="Rôle ARIA et structure sémantique">
27
+ <ul>
28
+ <li><strong>Rôle alert</strong> : Le composant utilise <code>role="alert"</code> pour annoncer automatiquement le message aux lecteurs d'écran</li>
29
+ <li><strong>Types sémantiques</strong> : Quatre types disponibles (<code>success</code>, <code>info</code>, <code>warning</code>, <code>error</code>) avec icônes appropriées</li>
30
+ <li><strong>Gestion Vuetify</strong> : Le rôle <code>role="undefined"</code> sur VAlert évite les conflits de rôles avec le conteneur parent</li>
31
+ </ul>
32
+ </CriteriaCard>
33
+
34
+ <CriteriaCard icon="🎨" title="Icônes et éléments décoratifs">
35
+ <ul>
36
+ <li><strong>Rôle presentation</strong> : Les SVG des icônes reçoivent <code>role="presentation"</code> via <code>v-rgaa-svg-fix</code> pour éviter la lecture superflue</li>
37
+ <li><strong>Icône décorative</strong> : L'icône de fermeture utilise <code>decorative</code> pour être masquée aux lecteurs d'écran</li>
38
+ <li><strong>Texte visible</strong> : Le bouton de fermeture contient le texte "Fermer" pour une accessibilité complète</li>
39
+ </ul>
40
+ </CriteriaCard>
41
+
42
+ <CriteriaCard icon="⌨️" title="Interaction et fermeture">
43
+ <ul>
44
+ <li><strong>Bouton natif</strong> : Utilisation de <code>VBtn</code> pour la fermeture, garantissant un comportement clavier natif</li>
45
+ <li><strong>Focus visible</strong> : Style <code>:focus-visible</code> avec outline clair pour la navigation au clavier</li>
46
+ <li><strong>Contrôle modelValue</strong> : Fermeture gérée via <code>v-model</code> pour une cohérence réactive</li>
47
+ </ul>
48
+ </CriteriaCard>
49
+
50
+ <CriteriaCard icon="📱" title="Variantes et styles accessibles">
51
+ <ul>
52
+ <li><strong>Deux variantes</strong> : <code>tonal</code> (fond coloré) et <code>outlined</code> (contour) avec contrastes adaptés</li>
53
+ <li><strong>Thème sombre</strong> : Styles spécifiques pour le mode dark avec contrastes inversés</li>
54
+ <li><strong>Responsive</strong> : Adaptation mobile avec flexbox et espacement optimisé</li>
55
+ </ul>
56
+ </CriteriaCard>
57
+ </CriteriaSection>
58
+
59
+ <DemoSection componentName="SyAlert">
60
+ <Primary />
61
+ </DemoSection>
62
+
63
+ <BestPracticesSection>
64
+ <ul>
65
+ <li><strong>Type approprié</strong> : Choisissez <code>error</code> pour les erreurs bloquantes, <code>warning</code> pour les avertissements, <code>success</code> pour les confirmations, <code>info</code> pour les informations</li>
66
+ <li><strong>Fermeture conditionnelle</strong> : Utilisez <code>closable={true}</code> uniquement si l'utilisateur peut ignorer l'alerte en toute sécurité</li>
67
+ <li><strong>Messages concis</strong> : Gardez les textes clairs et directs pour une compréhension rapide</li>
68
+ <li><strong>Positionnement</strong> : Placez les alertes de manière visible mais non intrusive dans le flux de navigation</li>
69
+ <li><strong>Évitez les multiples</strong> : Ne cumulez pas plusieurs alertes simultanément pour éviter la surcharge cognitive</li>
70
+ </ul>
71
+ </BestPracticesSection>
72
+
73
+ <ResourcesSection>
74
+ <ul>
75
+ <li><a href="https://www.w3.org/WAI/ARIA/apg/patterns/alert/" target="_blank" rel="noopener noreferrer">Guide des pratiques WAI-ARIA : Alertes</a></li>
76
+ <li><a href="https://www.w3.org/WAI/WCAG21/quickref/" target="_blank" rel="noopener noreferrer">Référence rapide WCAG 2.1</a></li>
77
+ <li><a href="https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#10.6" target="_blank" rel="noopener noreferrer">RGAA Critère 10.6 : Messages d'erreur</a></li>
78
+ <li><a href="https://inclusive-components.design/notifications/" target="_blank" rel="noopener noreferrer">Inclusive Components: Notifications</a></li>
79
+ </ul>
80
+ </ResourcesSection>
81
+
82
+ </AccessibilityGuideLayout>
@@ -0,0 +1,23 @@
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 SyAlert from '../SyAlert.vue'
8
+
9
+ describe('SyAlert – accessibility (axe)', () => {
10
+ it('has no obvious axe violations', async () => {
11
+ const wrapper = mount(SyAlert, {
12
+ props: {
13
+ type: 'info',
14
+ },
15
+ slots: {
16
+ default: 'Ceci est un message d\'information.',
17
+ },
18
+ })
19
+
20
+ const results = await axe(wrapper.element as HTMLElement)
21
+ assertNoA11yViolations(results, 'SyAlert – default state')
22
+ })
23
+ })
@@ -0,0 +1,149 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { mount } from '@vue/test-utils'
3
+ import { axe } from 'vitest-axe'
4
+ import { assertNoA11yViolations } from '@tests/unit/accessibility/axeUtils'
5
+ import SyHeading from './SyHeading.vue'
6
+
7
+ describe('SyHeading - Accessibility', () => {
8
+ it('should not have any accessibility violations with default props', async () => {
9
+ const wrapper = mount(SyHeading, {
10
+ slots: {
11
+ default: 'Default heading',
12
+ },
13
+ })
14
+
15
+ const results = await axe(wrapper.element, {
16
+ rules: {
17
+ region: { enabled: false },
18
+ },
19
+ })
20
+ assertNoA11yViolations(results, 'SyHeading - default props')
21
+ })
22
+
23
+ it('should not have accessibility violations with all heading levels', async () => {
24
+ const levels = [1, 2, 3, 4, 5, 6] as const
25
+
26
+ for (const level of levels) {
27
+ const wrapper = mount(SyHeading, {
28
+ props: {
29
+ level,
30
+ },
31
+ slots: {
32
+ default: `Heading level ${level}`,
33
+ },
34
+ })
35
+
36
+ const results = await axe(wrapper.element, {
37
+ rules: {
38
+ region: { enabled: false },
39
+ },
40
+ })
41
+ assertNoA11yViolations(results, `SyHeading - level ${level}`)
42
+ }
43
+ })
44
+
45
+ it('should not have accessibility violations with complex content', async () => {
46
+ const wrapper = mount(SyHeading, {
47
+ props: {
48
+ level: 3,
49
+ },
50
+ slots: {
51
+ default: '<span>Heading with <em>emphasis</em> and <strong>strong text</strong></span>',
52
+ },
53
+ })
54
+
55
+ const results = await axe(wrapper.element, {
56
+ rules: {
57
+ region: { enabled: false },
58
+ },
59
+ })
60
+ assertNoA11yViolations(results, 'SyHeading - complex content')
61
+ })
62
+
63
+ it('should not have accessibility violations with very long content', async () => {
64
+ const longContent = 'This is a very long heading text that might wrap across multiple lines and should still be accessible to screen readers and other assistive technologies without any issues.'
65
+
66
+ const wrapper = mount(SyHeading, {
67
+ props: {
68
+ level: 2,
69
+ },
70
+ slots: {
71
+ default: longContent,
72
+ },
73
+ })
74
+
75
+ const results = await axe(wrapper.element, {
76
+ rules: {
77
+ region: { enabled: false },
78
+ },
79
+ })
80
+ assertNoA11yViolations(results, 'SyHeading - long content')
81
+ })
82
+
83
+ it('should not have accessibility violations with special characters', async () => {
84
+ const wrapper = mount(SyHeading, {
85
+ props: {
86
+ level: 1,
87
+ },
88
+ slots: {
89
+ default: 'Heading with special chars: éàüßñ & symbols @#$%',
90
+ },
91
+ })
92
+
93
+ const results = await axe(wrapper.element, {
94
+ rules: {
95
+ region: { enabled: false },
96
+ },
97
+ })
98
+ assertNoA11yViolations(results, 'SyHeading - special characters')
99
+ })
100
+
101
+ it('should use semantic heading elements correctly', async () => {
102
+ const levels = [1, 2, 3, 4, 5, 6] as const
103
+
104
+ for (const level of levels) {
105
+ const wrapper = mount(SyHeading, {
106
+ props: {
107
+ level,
108
+ },
109
+ slots: {
110
+ default: `Semantic heading level ${level}`,
111
+ },
112
+ })
113
+
114
+ // Verify the correct semantic heading element is used
115
+ expect(wrapper.find(`h${level}`).exists()).toBe(true)
116
+
117
+ // Verify no accessibility violations
118
+ const results = await axe(wrapper.element, {
119
+ rules: {
120
+ region: { enabled: false },
121
+ },
122
+ })
123
+ assertNoA11yViolations(results, `SyHeading - semantic level ${level}`)
124
+ }
125
+ })
126
+
127
+ it('should maintain heading hierarchy for screen readers', async () => {
128
+ const wrapper = mount(SyHeading, {
129
+ props: {
130
+ level: 2,
131
+ },
132
+ slots: {
133
+ default: 'Important section heading',
134
+ },
135
+ })
136
+
137
+ // Verify the heading is properly structured for screen readers
138
+ const heading = wrapper.find('h2')
139
+ expect(heading.exists()).toBe(true)
140
+ expect(heading.text()).toBe('Important section heading')
141
+
142
+ const results = await axe(wrapper.element, {
143
+ rules: {
144
+ region: { enabled: false },
145
+ },
146
+ })
147
+ assertNoA11yViolations(results, 'SyHeading - hierarchy')
148
+ })
149
+ })
@@ -0,0 +1,115 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { mount } from '@vue/test-utils'
3
+ import { axe } from 'vitest-axe'
4
+ import { assertNoA11yViolations } from '@tests/unit/accessibility/axeUtils'
5
+ import SyHeading from './SyHeading.vue'
6
+
7
+ describe('SyHeading', () => {
8
+ it('renders default heading level 2', () => {
9
+ const wrapper = mount(SyHeading, {
10
+ slots: {
11
+ default: 'Test heading',
12
+ },
13
+ })
14
+
15
+ expect(wrapper.find('h2').exists()).toBe(true)
16
+ expect(wrapper.text()).toBe('Test heading')
17
+ expect(wrapper.classes()).toContain('sy-heading')
18
+ })
19
+
20
+ it('renders custom heading levels', () => {
21
+ const levels = [1, 2, 3, 4, 5, 6] as const
22
+
23
+ levels.forEach((level) => {
24
+ const wrapper = mount(SyHeading, {
25
+ props: {
26
+ level,
27
+ },
28
+ slots: {
29
+ default: `Heading level ${level}`,
30
+ },
31
+ })
32
+
33
+ expect(wrapper.find(`h${level}`).exists()).toBe(true)
34
+ expect(wrapper.text()).toBe(`Heading level ${level}`)
35
+ })
36
+ })
37
+
38
+ it('applies correct CSS class', () => {
39
+ const wrapper = mount(SyHeading, {
40
+ slots: {
41
+ default: 'Test heading',
42
+ },
43
+ })
44
+
45
+ expect(wrapper.classes()).toContain('sy-heading')
46
+ })
47
+
48
+ it('renders complex content', () => {
49
+ const wrapper = mount(SyHeading, {
50
+ slots: {
51
+ default: '<span>Complex <strong>content</strong></span>',
52
+ },
53
+ })
54
+
55
+ expect(wrapper.text()).toBe('Complex content')
56
+ })
57
+
58
+ it('should not have any accessibility violations', async () => {
59
+ const wrapper = mount(SyHeading, {
60
+ props: {
61
+ level: 1,
62
+ },
63
+ slots: {
64
+ default: 'Main heading',
65
+ },
66
+ })
67
+
68
+ const results = await axe(wrapper.element, {
69
+ rules: {
70
+ region: { enabled: false },
71
+ },
72
+ })
73
+ assertNoA11yViolations(results, 'SyHeading - main heading')
74
+ })
75
+
76
+ it('should not have accessibility violations for all heading levels', async () => {
77
+ const levels = [1, 2, 3, 4, 5, 6] as const
78
+
79
+ for (const level of levels) {
80
+ const wrapper = mount(SyHeading, {
81
+ props: {
82
+ level,
83
+ },
84
+ slots: {
85
+ default: `Heading level ${level}`,
86
+ },
87
+ })
88
+
89
+ const results = await axe(wrapper.element, {
90
+ rules: {
91
+ region: { enabled: false },
92
+ },
93
+ })
94
+ assertNoA11yViolations(results, `SyHeading - level ${level}`)
95
+ }
96
+ })
97
+
98
+ it('should not have accessibility violations with complex content', async () => {
99
+ const wrapper = mount(SyHeading, {
100
+ props: {
101
+ level: 2,
102
+ },
103
+ slots: {
104
+ default: '<span>Heading with <em>emphasis</em> and <strong>strong text</strong></span>',
105
+ },
106
+ })
107
+
108
+ const results = await axe(wrapper.element, {
109
+ rules: {
110
+ region: { enabled: false },
111
+ },
112
+ })
113
+ assertNoA11yViolations(results, 'SyHeading - complex content')
114
+ })
115
+ })