@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.
Files changed (135) hide show
  1. package/dist/{DateFilter-XURUmpMl.js → DateFilter-uN8OURoP.js} +1 -1
  2. package/dist/{NumberFilter-BZc0O8wV.js → NumberFilter-sm1dQNQi.js} +1 -1
  3. package/dist/{PeriodFilter-ZNdXcl3p.js → PeriodFilter-Cklsxnh9.js} +1 -1
  4. package/dist/{SelectFilter-DshYU5OK.js → SelectFilter-CWefj27Z.js} +1 -1
  5. package/dist/{TextFilter-D_c5dRPl.js → TextFilter-Ddyj885L.js} +1 -1
  6. package/dist/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.d.ts +160 -0
  7. package/dist/components/Customs/SyCheckBoxGroup/locales.d.ts +3 -0
  8. package/dist/components/Customs/SyCheckBoxGroup/types.d.ts +10 -0
  9. package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +1545 -2
  10. package/dist/components/Customs/SyRadioGroup/SyRadioGroup.d.ts +1495 -2
  11. package/dist/components/DeclarationAccessibilityPage/DeclarationAccessibilityPage.d.ts +60 -0
  12. package/dist/components/ErrorPage/ErrorPage.d.ts +1 -12
  13. package/dist/components/ErrorPage/locales.d.ts +18 -3
  14. package/dist/components/FileUpload/FileUpload.d.ts +2 -0
  15. package/dist/components/MaintenancePage/locales.d.ts +18 -2
  16. package/dist/components/NotFoundPage/locales.d.ts +20 -4
  17. package/dist/components/StatusPage/StatusPage.d.ts +39 -0
  18. package/dist/components/UploadWorkflow/UploadWorkflow.d.ts +13 -3
  19. package/dist/components/index.d.ts +3 -0
  20. package/dist/design-system-v3.js +126 -123
  21. package/dist/design-system-v3.umd.cjs +163 -163
  22. package/dist/{main-CuI6xaPq.js → main-CWniLr0s.js} +15191 -14668
  23. package/dist/style.css +1 -1
  24. package/dist/utils/theme/index.d.ts +6 -0
  25. package/package.json +7 -4
  26. package/src/components/ContextualMenu/ContextualMenu.stories.ts +0 -3
  27. package/src/components/ContextualMenu/accessibilite/Accessibility.mdx +67 -11
  28. package/src/components/CookieBanner/CookieBanner.stories.ts +11 -20
  29. package/src/components/CookieBanner/CookieBanner.vue +20 -5
  30. package/src/components/CookieBanner/accessibilite/Accessibility.mdx +67 -11
  31. package/src/components/CookieBanner/tests/CookieBanner.spec.ts +48 -4
  32. package/src/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.mdx +32 -0
  33. package/src/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.stories.ts +856 -0
  34. package/src/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.vue +334 -0
  35. package/src/components/Customs/SyCheckBoxGroup/accessibilite/Accessibility.mdx +243 -0
  36. package/src/components/Customs/SyCheckBoxGroup/locales.ts +3 -0
  37. package/src/components/Customs/SyCheckBoxGroup/tests/SyCheckBoxGroup.a11y.spec.ts +30 -0
  38. package/src/components/Customs/SyCheckBoxGroup/tests/SyCheckBoxGroup.spec.ts +152 -0
  39. package/src/components/Customs/SyCheckBoxGroup/types.ts +10 -0
  40. package/src/components/Customs/SyCheckbox/SyCheckbox.vue +16 -27
  41. package/src/components/Customs/SyCheckbox/accessibilite/Accessibility.mdx +1 -1
  42. package/src/components/Customs/SyForm/SyForm.a11y.spec.ts +1 -1
  43. package/src/components/Customs/SyRadioGroup/SyRadioGroup.vue +16 -43
  44. package/src/components/DatePicker/CalendarMode/DatePicker.vue +35 -11
  45. package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.stories.ts +43 -2
  46. package/src/components/DatePicker/DateTextInput/DateTextInput.vue +48 -21
  47. package/src/components/DatePicker/DateTextInput/NoCalendar.stories.ts +98 -0
  48. package/src/components/DeclarationAccessibilityPage/DeclarationAccessibilityPage.mdx +83 -0
  49. package/src/components/DeclarationAccessibilityPage/DeclarationAccessibilityPage.stories.ts +502 -0
  50. package/src/components/DeclarationAccessibilityPage/DeclarationAccessibilityPage.vue +428 -0
  51. package/src/components/DeclarationAccessibilityPage/accessibilite/Accessibility.mdx +75 -0
  52. package/src/components/DeclarationAccessibilityPage/tests/DeclarationAccessibilityPage.a11y.spec.ts +53 -0
  53. package/src/components/DeclarationAccessibilityPage/tests/DeclarationAccessibilityPage.spec.ts +59 -0
  54. package/src/components/DiacriticPicker/DiacriticPicker.vue +20 -1
  55. package/src/components/ErrorPage/ErrorPage.mdx +6 -16
  56. package/src/components/ErrorPage/ErrorPage.stories.ts +16 -87
  57. package/src/components/ErrorPage/ErrorPage.vue +38 -125
  58. package/src/components/ErrorPage/accessibilite/Accessibility.mdx +68 -6
  59. package/src/components/ErrorPage/assets/error-ap.svg +1774 -0
  60. package/src/components/ErrorPage/locales.ts +21 -3
  61. package/src/components/ErrorPage/tests/ErrorPage.a11y.spec.ts +5 -13
  62. package/src/components/ErrorPage/tests/ErrorPage.spec.ts +2 -41
  63. package/src/components/ErrorPage/tests/__snapshots__/ErrorPage.spec.ts.snap +8 -266
  64. package/src/components/FileUpload/FileUpload.vue +5 -0
  65. package/src/components/FooterBar/FooterBar.stories.ts +18 -14
  66. package/src/components/FooterBar/defaultSocialMediaLinks.ts +6 -4
  67. package/src/components/MaintenancePage/MaintenancePage.mdx +1 -1
  68. package/src/components/MaintenancePage/MaintenancePage.vue +15 -7
  69. package/src/components/MaintenancePage/accessibilite/Accessibility.mdx +61 -6
  70. package/src/components/MaintenancePage/assets/maintenance-ap.svg +1718 -0
  71. package/src/components/MaintenancePage/locales.ts +24 -3
  72. package/src/components/MaintenancePage/tests/MaintenancePage.a11y.spec.ts +75 -3
  73. package/src/components/MaintenancePage/tests/MaintenancePage.spec.ts +42 -2
  74. package/src/components/MaintenancePage/tests/__snapshots__/MaintenancePage.spec.ts.snap +3 -2
  75. package/src/components/NotFoundPage/NotFoundPage.mdx +1 -1
  76. package/src/components/NotFoundPage/NotFoundPage.stories.ts +3 -3
  77. package/src/components/NotFoundPage/NotFoundPage.vue +16 -11
  78. package/src/components/NotFoundPage/accessibilite/Accessibility.mdx +78 -6
  79. package/src/components/NotFoundPage/assets/not-found-ap.svg +2061 -0
  80. package/src/components/NotFoundPage/locales.ts +24 -4
  81. package/src/components/NotFoundPage/tests/NotFoundPage.a11y.spec.ts +168 -4
  82. package/src/components/NotFoundPage/tests/NotFoundPage.spec.ts +100 -12
  83. package/src/components/NotFoundPage/tests/__snapshots__/NotFoundPage.spec.ts.snap +2 -2
  84. package/src/components/NotificationBar/NotificationBar.mdx +2 -2
  85. package/src/components/NotificationBar/accessibilite/Accessibility.mdx +68 -8
  86. package/src/components/PageContainer/tests/PageContainer.a11y.spec.ts +14 -7
  87. package/src/components/PhoneField/PhoneField.stories.ts +46 -38
  88. package/src/components/SocialMediaLinks/DefaultSocialMediaLinks.ts +6 -4
  89. package/src/components/SocialMediaLinks/SocialMediaLinks.mdx +7 -5
  90. package/src/components/SocialMediaLinks/SocialMediaLinks.stories.ts +17 -13
  91. package/src/components/SocialMediaLinks/SocialMediaLinks.vue +9 -1
  92. package/src/components/SocialMediaLinks/accessibilite/Accessibility.mdx +63 -11
  93. package/src/components/SocialMediaLinks/tests/DefaultSocialMediaLinks.spec.ts +5 -5
  94. package/src/components/SocialMediaLinks/tests/SocialMediaLinks.a11y.spec.ts +59 -0
  95. package/src/components/SocialMediaLinks/tests/SocialMediaLinks.spec.ts +9 -7
  96. package/src/components/StatusPage/StatusPage.mdx +22 -0
  97. package/src/components/StatusPage/StatusPage.stories.ts +193 -0
  98. package/src/components/StatusPage/StatusPage.vue +145 -0
  99. package/src/components/StatusPage/accessibilite/Accessibility.mdx +81 -0
  100. package/src/components/StatusPage/tests/StatusPage.a11y.spec.ts +29 -0
  101. package/src/components/StatusPage/tests/StatusPage.spec.ts +50 -0
  102. package/src/components/StatusPage/tests/__snapshots__/StatusPage.spec.ts.snap +270 -0
  103. package/src/components/TableToolbar/TableToolbar.stories.ts +6 -6
  104. package/src/components/TableToolbar/TableToolbar.vue +1 -1
  105. package/src/components/TableToolbar/tests/__snapshots__/TableToolbar.spec.ts.snap +0 -5
  106. package/src/components/UploadWorkflow/UploadWorkflow.mdx +11 -1
  107. package/src/components/UploadWorkflow/UploadWorkflow.stories.ts +107 -3
  108. package/src/components/UploadWorkflow/UploadWorkflow.vue +35 -24
  109. package/src/components/UploadWorkflow/tests/UploadWorkflow.spec.ts +48 -0
  110. package/src/components/UploadWorkflow/tests/__snapshots__/UploadWorkflow.spec.ts.snap +9 -5
  111. package/src/components/UploadWorkflow/useFileList.ts +7 -0
  112. package/src/components/index.ts +3 -0
  113. package/src/composables/rules/tests/useFieldValidation.spec.ts +39 -3
  114. package/src/composables/rules/useFieldValidation.ts +24 -9
  115. package/src/stories/Accessibilite/KitDePreAudit/Preaudit.mdx +7 -0
  116. package/src/utils/theme/index.ts +19 -0
  117. package/src/utils/theme/tests/useThemeLocales.spec.ts +245 -0
  118. package/dist/components/MaintenancePage/index.d.ts +0 -2
  119. package/src/components/Customs/SyPagination/tests/SyPagination.a11y.spec.ts +0 -27
  120. package/src/components/Customs/SyTabs/tests/SyTabs.a11y.spec.ts +0 -51
  121. package/src/components/DataListItem/tests/DataListItem.a11y.spec.ts +0 -31
  122. package/src/components/DatePicker/CalendarMode/tests/DatePicker.a11y.spec.ts +0 -27
  123. package/src/components/DatePicker/ComplexDatePicker/tests/ComplexDatePicker.a11y.spec.ts +0 -26
  124. package/src/components/DatePicker/DateTextInput/tests/DateTextInput.a11y.spec.ts +0 -27
  125. package/src/components/DownloadBtn/tests/DownloadBtn.a11y.spec.ts +0 -26
  126. package/src/components/ExternalLinks/tests/ExternalLinks.a11y.spec.ts +0 -39
  127. package/src/components/HeaderNavigationBar/tests/HeaderNavigationBar.a11y.spec.ts +0 -45
  128. package/src/components/HeaderToolbar/tests/HeaderToolbar.a11y.spec.ts +0 -25
  129. package/src/components/LunarCalendar/tests/LunarCalendar.a11y.spec.ts +0 -31
  130. package/src/components/MaintenancePage/index.ts +0 -3
  131. package/src/components/PageContainer/Accessibilite/AccessibilityGuide.mdx +0 -0
  132. package/src/components/PaginatedTable/tests/PaginatedTable.a11y.spec.ts +0 -43
  133. package/src/components/PhoneField/tests/PhoneField.a11y.spec.ts +0 -34
  134. /package/src/components/NotFoundPage/assets/{not-found.svg → not-found-cnam.svg} +0 -0
  135. /package/src/components/PageContainer/{Accessibilite → accessibilite}/Accessibility.mdx +0 -0
@@ -0,0 +1,6 @@
1
+ import { ComputedRef } from 'vue';
2
+ export declare function useThemeLocales<T extends Record<string, unknown> & {
3
+ default: unknown;
4
+ }>(locales: T): {
5
+ themeLocales: ComputedRef<T[keyof T]>;
6
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cnamts/synapse",
3
- "version": "1.0.20",
3
+ "version": "1.0.21",
4
4
  "private": false,
5
5
  "description": "CNAM DS v3",
6
6
  "type": "module",
@@ -30,6 +30,7 @@
30
30
  "lint:fix": "eslint \"src/**/*.{ts,vue}\" --fix && stylelint \"src/**/*.{css,scss,vue}\" --fix",
31
31
  "test:unit": "vitest run --exclude='**/*.a11y.spec.ts'",
32
32
  "test:a11y": "pnpm vitest run a11y.spec.ts",
33
+ "a11y:report": "node ./scripts/a11y-report.mjs",
33
34
  "prepare": "husky",
34
35
  "generate:changelog": "auto-changelog -o CHANGELOG-TEMP.md -p --starting-date 2024-10-10"
35
36
  },
@@ -99,7 +100,7 @@
99
100
  "typescript": "~5.9.3",
100
101
  "typescript-eslint": "^8.11.0",
101
102
  "vite": "^5.3.5",
102
- "vite-plugin-dts": "^4.0.1",
103
+ "vite-plugin-dts": "^4.5.4",
103
104
  "vite-plugin-vuetify": "^2.1.1",
104
105
  "vitest": "^3.2.4",
105
106
  "vitest-axe": "^0.1.0",
@@ -129,7 +130,8 @@
129
130
  "esbuild": "^0.25.0",
130
131
  "parse5": "7.1.2",
131
132
  "npm": "^11.8.1",
132
- "undici": "^6.21.0"
133
+ "undici": "^6.21.0",
134
+ "rollup": "^4.59.0"
133
135
  },
134
136
  "pnpm": {
135
137
  "overrides": {
@@ -138,7 +140,8 @@
138
140
  "glob": ">=10.5.0",
139
141
  "js-yaml": ">=4.1.1",
140
142
  "parse5": "7.1.2",
141
- "npm": "^11.8.1"
143
+ "npm": "^11.8.1",
144
+ "minimatch": ">=10.2.3"
142
145
  }
143
146
  }
144
147
  }
@@ -223,9 +223,6 @@ export const WithAnchors: Story = {
223
223
  }
224
224
  },
225
225
  parameters: {
226
- a11y: {
227
- disable: true,
228
- },
229
226
  sourceCode: [
230
227
  {
231
228
  name: 'Template',
@@ -1,15 +1,71 @@
1
- import { Meta, Story } from '@storybook/addon-docs';
2
- import * as Stories from '../ContextualMenu.stories.ts';
3
- import '@/stories/styles/shared.css';
1
+ import { Meta, Primary } from '@storybook/blocks';
2
+ import * as ContextualMenuStories from '../ContextualMenu.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
+ AuditSection,
12
+ } from '@/stories/accessibility/AccessibilityGuideLayout.mdx';
4
13
 
5
- <Meta of={Stories} />
14
+ <Meta of={ContextualMenuStories} />
6
15
 
7
- <div className="header">
8
- <h1>Accessibilité</h1>
9
- </div>
16
+ <AccessibilityGuideLayout
17
+ componentName="ContextualMenu"
18
+ iconSrc={AccessibilityIcon}
19
+ >
20
+ <AuditSection>
21
+ <p>Rapport d’audit manuel : <a href="/audits/ContextualMenu.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/658" target="_blank" style={{color:'#0C41BD'}}>issue #658</a>)</p>
23
+ </AuditSection>
24
+
25
+ <CriteriaSection>
26
+ <CriteriaCard icon="🏷️" title="Structure sémantique claire">
27
+ <ul>
28
+ <li>Landmark <code>&lt;nav&gt;</code> avec <code>aria-label</code> obligatoire pour annoncer la zone.</li>
29
+ <li>Hiérarchie native <code>ul &gt; li &gt; a</code> pour les niveaux imbriqués, sans rôles ARIA détournés.</li>
30
+ <li>Utilisation de <code>aria-current</code> sur le lien actif pour signaler la section courante.</li>
31
+ </ul>
32
+ </CriteriaCard>
10
33
 
34
+ <CriteriaCard icon="⌨️" title="Navigation clavier native">
35
+ <ul>
36
+ <li>Parcours par <kbd>Tab</kbd>/<kbd>Maj+Tab</kbd> sur des liens standards, activation par <kbd>Entrée</kbd>.</li>
37
+ <li>Styles de focus visibles fournis par la feuille de style partagée et conservés sur tous les niveaux.</li>
38
+ <li>Activation via clic clavier ou souris met à jour le hash et synchronise l'état actif.</li>
39
+ </ul>
40
+ </CriteriaCard>
11
41
 
12
- <div class="mt-2">
13
- <p>Rapport d’audit manuel : <a href="/audits/ContextualMenu.xlsx" style={{ color:'#0C41BD' }}>Voir le rapport</a></p>
14
- <p style={{ color: 'grey', fontSize: '14px', marginTop: '0px' }}>Correctifs associés (<a href="https://github.com/assurance-maladie-digital/design-system-v3/issues/658" target="_blank" style={{color:'#0C41BD'}}>issue #658</a>)</p>
15
- </div>
42
+ <CriteriaCard icon="🧭" title="Repères et correspondance contenu">
43
+ <ul>
44
+ <li>Chaque élément pointe vers une ancre <code>hash</code>; les sections ciblées doivent avoir des <code>id</code> uniques et, idéalement, <code>tabindex="-1"</code> pour recevoir le focus programmatique.</li>
45
+ <li>Gestion du hash : changement d'URL et état contrôlé via <code>v-model</code> pour refléter l'élément actif.</li>
46
+ <li>Support multi-niveaux via la propriété optionnelle <code>level</code> (1 à 6) générant des listes imbriquées.</li>
47
+ </ul>
48
+ </CriteriaCard>
49
+ </CriteriaSection>
50
+
51
+ <DemoSection componentName="ContextualMenu">
52
+ <Primary />
53
+ </DemoSection>
54
+
55
+ <BestPracticesSection>
56
+ <ul>
57
+ <li>Fournissez systématiquement un <code>ariaLabel</code> descriptif (ex. « Plan de page »).</li>
58
+ <li>Assurez-vous que chaque <code>hash</code> correspond à un <code>id</code> existant dans la page, avec un titre associé via <code>aria-labelledby</code>.</li>
59
+ <li>Respectez l'ordre logique du contenu et les niveaux <code>level</code> pour refléter la structure réelle du document.</li>
60
+ <li>Évitez de placer des éléments interactifs non liens à l'intérieur des entrées du menu.</li>
61
+ </ul>
62
+ </BestPracticesSection>
63
+
64
+ <ResourcesSection>
65
+ <ul>
66
+ <li><a href="https://www.w3.org/TR/WCAG22/#navigation-mechanisms" target="_blank" rel="noopener noreferrer">WCAG – Mécanismes de navigation</a></li>
67
+ <li><a href="https://www.w3.org/TR/WCAG22/#link-purpose-in-context" target="_blank" rel="noopener noreferrer">WCAG – Objet du lien</a></li>
68
+ <li><a href="https://www.w3.org/WAI/tutorials/page-structure/sections/" target="_blank" rel="noopener noreferrer">WAI – Structuration des pages et sections</a></li>
69
+ </ul>
70
+ </ResourcesSection>
71
+ </AccessibilityGuideLayout>
@@ -49,7 +49,7 @@ const meta = {
49
49
  description: 'Événement émis lors de l\'acceptation des cookies',
50
50
  table: {
51
51
  category: 'Events',
52
- type: { summary: '' },
52
+ type: { summary: 'Partial<{ functional: boolean; analytics: boolean }>' },
53
53
  },
54
54
  },
55
55
  'onReject': {
@@ -57,7 +57,7 @@ const meta = {
57
57
  description: 'Événement émis lors du refus des cookies',
58
58
  table: {
59
59
  category: 'Events',
60
- type: { summary: '' },
60
+ type: { summary: 'Partial<{ functional: boolean; analytics: boolean }>' },
61
61
  },
62
62
  },
63
63
  'onCustomize': {
@@ -68,6 +68,14 @@ const meta = {
68
68
  type: { summary: '' },
69
69
  },
70
70
  },
71
+ 'onSubmit': {
72
+ action: 'submit',
73
+ description: 'Événement émis lors de la sauvegarde des préférences personnalisées',
74
+ table: {
75
+ category: 'Events',
76
+ type: { summary: 'Partial<Preferences>' },
77
+ },
78
+ },
71
79
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
72
80
  // @ts-ignore- Object literal may only specify known properties
73
81
  'onUpdate:modelValue': {
@@ -226,12 +234,10 @@ export const Default: Story = {
226
234
  onAccept: { action: 'accept' },
227
235
  onReject: { action: 'reject' },
228
236
  onCustomize: { action: 'customize' },
237
+ onSubmit: { action: 'submit' },
229
238
  },
230
239
  args: {
231
240
  items,
232
- onAccept: fn(),
233
- onReject: fn(),
234
- onCustomize: fn(),
235
241
  },
236
242
 
237
243
  render: (args) => {
@@ -258,9 +264,6 @@ export const Default: Story = {
258
264
  },
259
265
 
260
266
  parameters: {
261
- a11y: {
262
- disable: true,
263
- },
264
267
  sourceCode: [
265
268
  {
266
269
  name: 'Template',
@@ -356,9 +359,6 @@ export const WithoutCookiesItems: Story = {
356
359
  }
357
360
  },
358
361
  parameters: {
359
- a11y: {
360
- disable: true,
361
- },
362
362
  sourceCode: [
363
363
  {
364
364
  name: 'Template',
@@ -411,9 +411,6 @@ export const BannerDescriptionSlot: Story = {
411
411
  }
412
412
  },
413
413
  parameters: {
414
- a11y: {
415
- disable: true,
416
- },
417
414
  sourceCode: [
418
415
  {
419
416
  name: 'Template',
@@ -520,9 +517,6 @@ export const CookiesDescriptionSlots: Story = {
520
517
  }
521
518
  },
522
519
  parameters: {
523
- a11y: {
524
- disable: true,
525
- },
526
520
  sourceCode: [
527
521
  {
528
522
  name: 'Template',
@@ -619,9 +613,6 @@ export const Customization: Story = {
619
613
  }
620
614
  },
621
615
  parameters: {
622
- a11y: {
623
- disable: true,
624
- },
625
616
  sourceCode: [
626
617
  {
627
618
  name: 'Template',
@@ -34,14 +34,29 @@
34
34
  return display.smAndDown.value ? '100%' : 'auto'
35
35
  })
36
36
 
37
+ const itemKeys = computed(() => Object.keys(props.items ?? {}) as (keyof CookiesItems)[])
38
+
39
+ type ConsentPayload = Partial<Record<keyof CookiesItems, boolean>>
40
+
41
+ function buildConsentPayload(value: boolean): ConsentPayload {
42
+ if (!props.items) {
43
+ return {}
44
+ }
45
+
46
+ return itemKeys.value.reduce<ConsentPayload>((payload, key) => {
47
+ payload[key] = value
48
+ return payload
49
+ }, {})
50
+ }
51
+
37
52
  function reject(): void {
38
53
  active.value = false
39
- emits('reject')
54
+ emits('reject', buildConsentPayload(false))
40
55
  }
41
56
 
42
57
  function accept(): void {
43
58
  active.value = false
44
- emits('accept')
59
+ emits('accept', buildConsentPayload(true))
45
60
  }
46
61
 
47
62
  function customize(): void {
@@ -51,7 +66,7 @@
51
66
  emits('customize')
52
67
  }
53
68
 
54
- function personalizeCookies(e: Record<string, unknown>) {
69
+ function personalizeCookies(e: ConsentPayload) {
55
70
  emits('submit', e)
56
71
  showCookiesSelection.value = false
57
72
  active.value = false
@@ -167,13 +182,13 @@
167
182
  <VSheet
168
183
  ref="vsheetRef"
169
184
  v-bind="options.banner"
170
- :aria-label="locales.label"
171
185
  class="vd-cookie-banner"
172
186
  >
173
187
  <div
174
188
  ref="bannerRef"
175
189
  class="vd-cookie-banner__inner"
176
190
  role="dialog"
191
+ :aria-label="locales.label"
177
192
  >
178
193
  <div class="d-flex align-start flex-nowrap pa-0 mb-6">
179
194
  <h2
@@ -214,7 +229,7 @@
214
229
  <Transition name="height">
215
230
  <div v-if="showCookiesSelection && items">
216
231
  <CookiesSelection
217
- :items
232
+ :items="items"
218
233
  @submit="personalizeCookies"
219
234
  >
220
235
  <template
@@ -1,15 +1,71 @@
1
- import { Meta, Story } from '@storybook/addon-docs';
2
- import * as CookiesStories from '../CookieBanner.stories.ts';
3
- import '@/stories/styles/shared.css';
1
+ import { Meta, Primary } from '@storybook/blocks';
2
+ import * as CookieBannerStories from '../CookieBanner.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={CookiesStories} />
13
+ <Meta of={CookieBannerStories}/>
6
14
 
7
- <div className="header">
8
- <h1>Accessibilité</h1>
9
- </div>
15
+ <AccessibilityGuideLayout
16
+ componentName="CookieBanner"
17
+ iconSrc={AccessibilityIcon}
18
+ apgHref="https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog/"
19
+ >
20
+ <div class="mt-6">
21
+ <p>Rapport d’audit manuel : <a href="/audits/Cookies.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/806" target="_blank" style={{color:'#0C41BD'}}>issue #806</a>)</p>
23
+ </div>
24
+ <CriteriaSection>
25
+ <CriteriaCard icon="🧭" title="Structure et nom accessible">
26
+ <ul>
27
+ <li><strong>Rôle</strong> : <code>role="dialog"</code> sur le conteneur principal de la bannière.</li>
28
+ <li><strong>Nom accessible</strong> : <code>aria-label="Gestion des cookies"</code> (ou <code>aria-labelledby</code> pointant vers le titre).</li>
29
+ <li><strong>Hiérarchie</strong> : le titre est exposé (<code>h2</code>) et peut être référencé par <code>aria-labelledby</code> si besoin.</li>
30
+ </ul>
31
+ </CriteriaCard>
10
32
 
33
+ <CriteriaCard icon="⌨️" title="Navigation clavier">
34
+ <ul>
35
+ <li>Gestion de la touche <kbd>Tab</kbd> pour boucler le focus dans la bannière.</li>
36
+ <li>Échappe (<kbd>Esc</kbd>) ferme la bannière ou revient depuis la personnalisation.</li>
37
+ <li>Focus initial sur le bouton de fermeture à l’ouverture.</li>
38
+ </ul>
39
+ </CriteriaCard>
11
40
 
12
- <div class="mt-2">
13
- <p>Rapport d’audit manuel : <a href="/audits/Cookies.xlsx" style={{ color:'#0C41BD' }}>Voir le rapport</a></p>
14
- <p style={{ color: 'grey', fontSize: '14px', marginTop: '0px' }}>Correctifs associés (<a href="https://github.com/assurance-maladie-digital/design-system-v3/issues/806" target="_blank" style={{color:'#0C41BD'}}>issue #806</a>)</p>
15
- </div>
41
+ <CriteriaCard icon="🦻" title="Événements et consentement">
42
+ <ul>
43
+ <li><strong>accept/reject</strong> : émettent les catégories configurables (via les items) et toujours <code>essentials: true</code> si fournis.</li>
44
+ <li><strong>submit</strong> : renvoie les préférences personnalisées + <code>essentials: true</code> le cas échéant.</li>
45
+ <li>Pas de chargement de cookies non essentiels avant l’<code>accept</code> ou <code>submit</code>.</li>
46
+ </ul>
47
+ </CriteriaCard>
48
+ </CriteriaSection>
49
+
50
+ <DemoSection componentName="CookieBanner">
51
+ <Primary />
52
+ </DemoSection>
53
+
54
+ <BestPracticesSection>
55
+ <ul>
56
+ <li>Ne surchargez pas la description : un paragraphe clair et concis.</li>
57
+ <li>Assurez un contraste suffisant des boutons et du fond de bannière.</li>
58
+ <li>Proposez un lien « En savoir plus » vers votre politique cookies.</li>
59
+ <li>Chargez les cookies non essentiels uniquement après <code>accept</code> ou <code>submit</code>.</li>
60
+ <li>Conservez la possibilité de rouvrir la bannière ou de modifier le choix ailleurs dans l’interface.</li>
61
+ </ul>
62
+ </BestPracticesSection>
63
+
64
+ <ResourcesSection>
65
+ <ul>
66
+ <li><a href="https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog/" target="_blank" rel="noopener noreferrer">APG : Alert dialog</a></li>
67
+ <li><a href="https://www.cnil.fr/fr/cookies-traceurs-que-dit-la-loi" target="_blank" rel="noopener noreferrer">CNIL : Cookies et traceurs</a></li>
68
+ <li><a href="https://www.w3.org/WAI/WCAG21/quickref/" target="_blank" rel="noopener noreferrer">Référence rapide WCAG 2.1</a></li>
69
+ </ul>
70
+ </ResourcesSection>
71
+ </AccessibilityGuideLayout>
@@ -24,8 +24,14 @@ describe('CookieBanner', () => {
24
24
  expect(wrapper.find('[data-test-id="customize"]').attributes('style')).toContain('100%')
25
25
  })
26
26
 
27
- it('emit a reject event when the reject btn is clicked', async () => {
27
+ it('emit a reject event with payload built from provided items', async () => {
28
28
  const wrapper = mount(CookieBanner, {
29
+ props: {
30
+ items: {
31
+ enessentials: [],
32
+ functional: [],
33
+ },
34
+ },
29
35
  global: {
30
36
  stubs: {
31
37
  Teleport: true,
@@ -35,11 +41,20 @@ describe('CookieBanner', () => {
35
41
 
36
42
  await wrapper.find('[data-test-id="reject"]').trigger('click')
37
43
 
38
- expect(wrapper.emitted()).toHaveProperty('reject')
44
+ expect(wrapper.emitted('reject')?.[0]?.[0]).toEqual({
45
+ enessentials: false,
46
+ functional: false,
47
+ })
39
48
  })
40
49
 
41
- it('emit a accept event when the accept btn is clicked', async () => {
50
+ it('emit an accept event with payload built from provided items', async () => {
42
51
  const wrapper = mount(CookieBanner, {
52
+ props: {
53
+ items: {
54
+ functional: [],
55
+ analytics: [],
56
+ },
57
+ },
43
58
  global: {
44
59
  stubs: {
45
60
  Teleport: true,
@@ -49,7 +64,10 @@ describe('CookieBanner', () => {
49
64
 
50
65
  await wrapper.find('[data-test-id="accept"]').trigger('click')
51
66
 
52
- expect(wrapper.emitted()).toHaveProperty('accept')
67
+ expect(wrapper.emitted('accept')?.[0]?.[0]).toEqual({
68
+ functional: true,
69
+ analytics: true,
70
+ })
53
71
  })
54
72
 
55
73
  it('does not close the dialog when the customize button is clicked and do not show the cookie form', async () => {
@@ -116,4 +134,30 @@ describe('CookieBanner', () => {
116
134
  expect(wrapper.find('.vd-cookies-card').html()).toMatchSnapshot()
117
135
  expect(wrapper.emitted()).toHaveProperty('customize')
118
136
  })
137
+
138
+ it('emits submit payload coming from CookiesSelection without altering categories', async () => {
139
+ const wrapper = mount(CookieBanner, {
140
+ props: {
141
+ items: {
142
+ functional: [],
143
+ analytics: [],
144
+ },
145
+ },
146
+ global: {
147
+ stubs: {
148
+ Teleport: true,
149
+ },
150
+ },
151
+ })
152
+
153
+ await wrapper.find('[data-test-id="customize"]').trigger('click')
154
+ await wrapper.vm.$nextTick()
155
+
156
+ const selection = wrapper.findComponent({ name: 'CookiesSelection' })
157
+ selection.vm.$emit('submit', { functional: true })
158
+
159
+ expect(wrapper.emitted('submit')?.[0]?.[0]).toEqual({
160
+ functional: true,
161
+ })
162
+ })
119
163
  })
@@ -0,0 +1,32 @@
1
+ import { Meta, Canvas, Controls } from '@storybook/blocks';
2
+ import '../../../stories/styles/shared.css';
3
+ import * as SyCheckBoxGroupStories from './SyCheckBoxGroup.stories';
4
+
5
+ <Meta of={SyCheckBoxGroupStories} />
6
+
7
+ <div className="header">
8
+ <h1>SyCheckBoxGroup</h1>
9
+ <p>Le composant `SyCheckBoxGroup` est un groupe de cases à cocher basé sur `SyCheckbox`, conforme au style du Design System et qui respecte les règles d'accessibilité <abbr title="Référentiel Général d'Amélioration de l'Accessibilité">RGAA</abbr>.</p>
10
+ </div>
11
+
12
+ Il étend les fonctionnalités de base avec :
13
+
14
+ - La gestion d’un groupe d’options via la prop `options`
15
+ - Un mode **sélection unique** (par défaut) ou **multiple** (`multiple`)
16
+ - Un système de validation avancé (erreur, avertissement, succès)
17
+
18
+ <Canvas of={SyCheckBoxGroupStories.Default} />
19
+
20
+ # API
21
+
22
+ <Controls of={SyCheckBoxGroupStories.Default} />
23
+
24
+ ## Validation
25
+
26
+ Le composant supporte trois types de validation :
27
+
28
+ - Règles d'erreur standard (`customRules`)
29
+ - Règles d'avertissement (`customWarningRules`)
30
+ - Règles de succès (`customSuccessRules`)
31
+
32
+ <a href="/?path=/docs/guide-du-dev-guide-de-validation-des-formulaires--docs" className="action-link">Pour plus d'informations sur la validation, consultez le guide de validation des formulaires.</a>