@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.
- package/dist/{DateFilter-B5n-ZkLi.js → DateFilter-Dc-gSGwk.js} +1 -1
- package/dist/{NumberFilter-CtiZ9uj8.js → NumberFilter-vP38Wp6j.js} +1 -1
- package/dist/{PeriodFilter-DzqiMb-b.js → PeriodFilter-Ba1uYUnT.js} +1 -1
- package/dist/{SelectFilter-BOYlF7rX.js → SelectFilter-BioGT6Nn.js} +1 -1
- package/dist/{TextFilter-BOFRNfcX.js → TextFilter-B84dpnoq.js} +1 -1
- package/dist/components/Accordion/Accordion.d.ts +13 -2
- package/dist/components/Accordion/composables/useAccordionState.d.ts +2 -1
- package/dist/components/Amelipro/AmeliproAutoCompleteField/AmeliproAutoCompleteField.d.ts +7 -7
- package/dist/components/Amelipro/AmeliproCheckbox/AmeliproCheckbox.d.ts +1 -1
- package/dist/components/Amelipro/AmeliproCustomSelector/AmeliproCustomSelector.d.ts +1 -1
- package/dist/components/Amelipro/AmeliproPostalAddressField/AmeliproPostalAddressField.d.ts +1 -1
- package/dist/components/Amelipro/AmeliproSelect/AmeliproSelect.d.ts +7 -7
- package/dist/components/Amelipro/AmeliproTabs/AmeliproTabs.d.ts +16 -16
- package/dist/components/Amelipro/AmeliproTextArea/AmeliproTextArea.d.ts +1 -1
- package/dist/components/Amelipro/AmeliproTextField/AmeliproTextField.d.ts +1 -1
- package/dist/components/Customs/Selects/SyAutocomplete/SyAutocomplete.d.ts +22 -1
- package/dist/components/Customs/Selects/SyAutocomplete/locales.d.ts +5 -0
- package/dist/components/Customs/Selects/SyInputSelect/SyInputSelect.d.ts +1 -1
- package/dist/components/Customs/Selects/SySelect/SySelect.d.ts +1 -1
- package/dist/components/Customs/Selects/SySelect/locales.d.ts +1 -0
- package/dist/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.d.ts +1 -1
- package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +1 -1
- package/dist/components/Customs/SyRadioGroup/SyRadioGroup.d.ts +1 -1
- package/dist/components/Customs/SyTextField/SyTextField.d.ts +5 -2
- package/dist/components/DatePicker/CalendarMode/DatePicker.d.ts +13 -9
- package/dist/components/DatePicker/ComplexDatePicker/ComplexDatePicker.d.ts +7 -5
- package/dist/components/DatePicker/DateTextInput/DateTextInput.d.ts +2 -1
- package/dist/components/ErrorPage/ErrorPage.d.ts +3 -1
- package/dist/components/FileList/UploadItem/UploadItem.d.ts +6 -0
- package/dist/components/FileList/UploadItem/locales.d.ts +1 -4
- package/dist/components/FileUpload/FileUploadContent.d.ts +2 -0
- package/dist/components/FileUpload/validateFiles.d.ts +2 -1
- package/dist/components/HeaderBar/HeaderBar.d.ts +2 -1
- package/dist/components/HeaderBar/HeaderLogo/HeaderLogo.d.ts +2 -1
- package/dist/components/HeaderNavigationBar/HeaderNavigationBar.d.ts +2 -1
- package/dist/components/MonthPicker/MonthPicker.d.ts +1939 -0
- package/dist/components/MonthPicker/MonthPickerText/MonthPickerInput.d.ts +1899 -0
- package/dist/components/MonthPicker/MonthPickerText/useTextField.d.ts +21 -0
- package/dist/components/MonthPicker/MonthPickerVisual/MonthPickerVisual.d.ts +21 -0
- package/dist/components/MonthPicker/MonthPickerVisual/MonthPickerVisualProps.d.ts +12 -0
- package/dist/components/MonthPicker/MonthPickerVisual/MonthSelector.d.ts +11 -0
- package/dist/components/MonthPicker/MonthPickerVisual/VisualPickerFooter.d.ts +6 -0
- package/dist/components/MonthPicker/MonthPickerVisual/VisualPickerHeader.d.ts +14 -0
- package/dist/components/MonthPicker/MonthPickerVisual/YearSelector.d.ts +14 -0
- package/dist/components/MonthPicker/MonthPickerVisual/useMonthGrid.d.ts +9 -0
- package/dist/components/MonthPicker/MonthPickerVisual/useYearGrid.d.ts +8 -0
- package/dist/components/MonthPicker/MonthPickerVisual/utils.d.ts +8 -0
- package/dist/components/MonthPicker/locales.d.ts +12 -0
- package/dist/components/MonthPicker/useMonthPickerValidation.d.ts +25 -0
- package/dist/components/NirField/NirField.d.ts +3 -1
- package/dist/components/NotificationBar/Notification/Notification.d.ts +3 -0
- package/dist/components/PasswordField/PasswordField.d.ts +1 -1
- package/dist/components/PeriodField/PeriodField.d.ts +29 -21
- package/dist/components/PhoneField/PhoneField.d.ts +2 -1
- package/dist/components/SyBtnMenu/SyBtnMenu.d.ts +1 -1
- package/dist/components/SyHeading/SyHeading.a11y.test.d.ts +1 -0
- package/dist/components/SyHeading/SyHeading.d.ts +4 -2
- package/dist/components/SyHeading/SyHeading.test.d.ts +1 -0
- package/dist/components/SyTextArea/SyTextArea.d.ts +1 -1
- package/dist/components/Tables/SyServerTable/SyServerTable.d.ts +4 -4
- package/dist/components/Tables/SyTable/SyTable.d.ts +4 -4
- package/dist/components/Tables/common/SyTablePagination.d.ts +6 -6
- package/dist/components/index.d.ts +1 -0
- package/dist/design-system-v3.js +102 -99
- package/dist/design-system-v3.umd.cjs +126 -126
- package/dist/designTokens/tokens/cnam/cnamContextual.d.ts +5 -0
- package/dist/{main-CEl4J8_T.js → main-aLKwdMi1.js} +11167 -10522
- package/dist/main.d.ts +1 -0
- package/dist/style.css +1 -1
- package/package.json +10 -4
- package/src/assets/apTokens.scss +2 -2
- package/src/assets/overrides/_btns.scss +8 -0
- package/src/assets/overrides/_forms.scss +9 -0
- package/src/assets/overrides/_icons.scss +38 -9
- package/src/assets/overrides/_tables.scss +19 -0
- package/src/components/Accordion/Accordion.mdx +23 -9
- package/src/components/Accordion/Accordion.stories.ts +153 -3
- package/src/components/Accordion/Accordion.vue +7 -6
- package/src/components/Accordion/composables/__tests__/useAccordionState.spec.ts +40 -12
- package/src/components/Accordion/composables/useAccordionState.ts +3 -4
- package/src/components/Accordion/tests/accordion.spec.ts +131 -19
- package/src/components/Amelipro/AmeliproPagination/AmeliproPagination.mdx +3 -1
- package/src/components/Amelipro/AmeliproPagination/AmeliproPagination.stories.ts +8 -0
- package/src/components/BackBtn/accessibilite/Accessibility.mdx +62 -10
- package/src/components/BackToTopBtn/BackToTopBtn.stories.ts +9 -3
- package/src/components/BackToTopBtn/accessibilite/Accessibility.mdx +86 -6
- package/src/components/Captcha/tests/Captcha.spec.ts +0 -29
- package/src/components/Captcha/tests/__snapshots__/Captcha.spec.ts.snap +2 -110
- package/src/components/Customs/Selects/SelectBtnField/accessibilite/Accessibility.mdx +133 -10
- package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.stories.ts +379 -93
- package/src/components/Customs/Selects/SyAutocomplete/SyAutocomplete.vue +144 -83
- package/src/components/Customs/Selects/SyAutocomplete/accessibilite/Accessibilite.stories.ts +40 -1
- package/src/components/Customs/Selects/SyAutocomplete/accessibilite/Accessibility.mdx +7 -1
- package/src/components/Customs/Selects/SyAutocomplete/locales.ts +5 -0
- package/src/components/Customs/Selects/SyAutocomplete/tests/SyAutocomplete.a11y.spec.ts +96 -0
- package/src/components/Customs/Selects/SyAutocomplete/tests/SyAutocomplete.spec.ts +234 -9
- package/src/components/Customs/Selects/SyAutocomplete/utils/ariaManager.ts +13 -3
- package/src/components/Customs/Selects/SyAutocomplete/utils/useSelectionLogic.ts +9 -10
- package/src/components/Customs/Selects/SySelect/SySelect.vue +46 -3
- package/src/components/Customs/Selects/SySelect/locales.ts +1 -0
- package/src/components/Customs/SyIcon/SyIcon.vue +1 -1
- package/src/components/Customs/SyIcon/tests/SyIcon.a11y.spec.ts +20 -0
- package/src/components/Customs/SyIconButton/SyIconButton.mdx +46 -0
- package/src/components/Customs/SyIconButton/SyIconButton.stories.ts +184 -0
- package/src/components/Customs/SyIconButton/SyIconButton.vue +38 -0
- package/src/components/Customs/SyIconButton/accessibilite/Accessibility.mdx +64 -0
- package/src/components/Customs/SyIconButton/tests/SyIconButton.a11y.spec.ts +87 -0
- package/src/components/Customs/SyIconButton/tests/SyIconButton.spec.ts +152 -0
- package/src/components/Customs/SyIconButton/tests/__snapshots__/SyIconButton.spec.ts.snap +61 -0
- package/src/components/Customs/SyPagination/SyPagination.vue +5 -5
- package/src/components/Customs/SyTextField/SyTextField.vue +20 -2
- package/src/components/Customs/SyTextField/accessibilite/Accessibility.mdx +67 -9
- package/src/components/Customs/SyTextField/tests/SyTextField.a11y.spec.ts +15 -0
- package/src/components/Customs/SyTextField/tests/SyTextField.spec.ts +36 -0
- package/src/components/DataList/accessibilite/Accessibility.mdx +79 -11
- package/src/components/DataListGroup/accessibilite/Accessibility.mdx +80 -11
- package/src/components/DownloadBtn/tests/DownloadBtn.a11y.spec.ts +25 -0
- package/src/components/ErrorPage/ErrorPage.stories.ts +113 -19
- package/src/components/ErrorPage/ErrorPage.vue +17 -2
- package/src/components/ErrorPage/tests/ErrorPage.a11y.spec.ts +17 -0
- package/src/components/ErrorPage/tests/ErrorPage.spec.ts +21 -1
- package/src/components/ErrorPage/tests/__snapshots__/ErrorPage.spec.ts.snap +0 -1
- package/src/components/ExternalLinks/tests/ExternalLinks.a11y.spec.ts +23 -0
- package/src/components/FileList/FileList.stories.ts +51 -1
- package/src/components/FileList/UploadItem/UploadItem.vue +13 -6
- package/src/components/FileList/UploadItem/locales.ts +3 -12
- package/src/components/FileList/accessibilite/Accessibility.mdx +3 -0
- package/src/components/FileUpload/FileUpload.vue +2 -1
- package/src/components/FileUpload/FileUploadContent.vue +2 -1
- package/src/components/FileUpload/tests/FileUpload.spec.ts +47 -0
- package/src/components/FileUpload/validateFiles.ts +5 -2
- package/src/components/FranceConnectBtn/accessibilite/Accessibility.mdx +62 -9
- package/src/components/HeaderBar/HeaderBar.vue +2 -1
- package/src/components/HeaderBar/HeaderLogo/HeaderLogo.vue +2 -1
- package/src/components/HeaderNavigationBar/HeaderNavigationBar.vue +2 -1
- package/src/components/LunarCalendar/accessibilite/Accessibility.mdx +74 -8
- package/src/components/LunarCalendar/tests/LunarCalendar.a11y.spec.ts +163 -0
- package/src/components/MaintenancePage/MaintenancePage.vue +1 -1
- package/src/components/MaintenancePage/tests/MaintenancePage.spec.ts +4 -5
- package/src/components/MaintenancePage/tests/__snapshots__/MaintenancePage.spec.ts.snap +0 -1
- package/src/components/MonthPicker/MonthPicker.mdx +35 -0
- package/src/components/MonthPicker/MonthPicker.stories.ts +527 -0
- package/src/components/MonthPicker/MonthPicker.vue +79 -0
- package/src/components/MonthPicker/MonthPickerText/MonthPickerInput.vue +89 -0
- package/src/components/MonthPicker/MonthPickerText/useTextField.ts +27 -0
- package/src/components/MonthPicker/MonthPickerVisual/MonthPickerVisual.vue +154 -0
- package/src/components/MonthPicker/MonthPickerVisual/MonthPickerVisualProps.ts +13 -0
- package/src/components/MonthPicker/MonthPickerVisual/MonthSelector.vue +137 -0
- package/src/components/MonthPicker/MonthPickerVisual/VisualPickerFooter.vue +60 -0
- package/src/components/MonthPicker/MonthPickerVisual/VisualPickerHeader.vue +149 -0
- package/src/components/MonthPicker/MonthPickerVisual/YearSelector.vue +143 -0
- package/src/components/MonthPicker/MonthPickerVisual/useMonthGrid.ts +45 -0
- package/src/components/MonthPicker/MonthPickerVisual/useYearGrid.ts +45 -0
- package/src/components/MonthPicker/MonthPickerVisual/utils.ts +17 -0
- package/src/components/MonthPicker/accessibilite/Accessibility.mdx +59 -0
- package/src/components/MonthPicker/locales.ts +12 -0
- package/src/components/MonthPicker/tests/MonthPicker.a11y.spec.ts +71 -0
- package/src/components/MonthPicker/tests/MonthPicker.spec.ts +1248 -0
- package/src/components/MonthPicker/tests/__snapshots__/MonthPicker.spec.ts.snap +2545 -0
- package/src/components/MonthPicker/useMonthPickerValidation.ts +30 -0
- package/src/components/NirField/NirField.mdx +1 -2
- package/src/components/NirField/NirField.stories.ts +66 -6
- package/src/components/NotFoundPage/tests/NotFoundPage.spec.ts +2 -3
- package/src/components/NotFoundPage/tests/__snapshots__/NotFoundPage.spec.ts.snap +22 -14
- package/src/components/NotificationBar/Notification/Notification.vue +3 -1
- package/src/components/NotificationBar/NotificationBar.stories.ts +154 -0
- package/src/components/NotificationBar/tests/NotificationBar.a11y.spec.ts +26 -0
- package/src/components/NotificationBar/tests/NotificationBar.spec.ts +60 -0
- package/src/components/RangeField/accessibilite/Accessibility.mdx +79 -11
- package/src/components/SkipLink/tests/SkipLink.a11y.spec.ts +23 -0
- package/src/components/StatusPage/StatusPage.stories.ts +118 -0
- package/src/components/StatusPage/StatusPage.vue +5 -3
- package/src/components/StatusPage/tests/StatusPage.a11y.spec.ts +22 -0
- package/src/components/StatusPage/tests/StatusPage.spec.ts +22 -0
- package/src/components/StatusPage/tests/__snapshots__/StatusPage.spec.ts.snap +22 -14
- package/src/components/SubHeader/tests/SubHeader.a11y.spec.ts +20 -0
- package/src/components/SyAlert/SyAlert.vue +1 -0
- package/src/components/SyAlert/accessibilite/Accessibility.mdx +79 -9
- package/src/components/SyAlert/tests/SyAlert.a11y.spec.ts +23 -0
- package/src/components/SyHeading/SyHeading.a11y.test.ts +149 -0
- package/src/components/SyHeading/SyHeading.test.ts +115 -0
- package/src/components/SyHeading/SyHeading.vue +5 -3
- package/src/components/SyTextArea/accessibilite/Accessibility.mdx +80 -8
- package/src/components/SyTextArea/tests/SyTextArea.a11y.spec.ts +151 -0
- package/src/components/ToolbarContainer/tests/ToolbarContainer.a11y.spec.ts +126 -0
- package/src/components/UploadWorkflow/tests/__snapshots__/UploadWorkflow.spec.ts.snap +2 -2
- package/src/components/index.ts +1 -0
- package/src/composables/useFormFieldErrorHandling.ts +11 -2
- package/src/designTokens/tokens/cnam/cnamContextual.ts +6 -1
- package/src/main.ts +2 -0
|
@@ -1,15 +1,73 @@
|
|
|
1
|
-
import { Meta,
|
|
1
|
+
import { Meta, Primary } from '@storybook/blocks';
|
|
2
2
|
import * as Stories from '../SyTextField.stories.ts';
|
|
3
|
-
import '@/
|
|
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
13
|
<Meta of={Stories} />
|
|
6
14
|
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
<div class="mt-
|
|
13
|
-
<p>Rapport d’audit manuel : <a href="/audits/SyTextField.xlsx" style={{ color:'#0C41BD' }}>Voir le rapport</a></p>
|
|
15
|
+
<AccessibilityGuideLayout
|
|
16
|
+
componentName="SyTextField"
|
|
17
|
+
iconSrc={AccessibilityIcon}
|
|
18
|
+
apgHref="https://www.w3.org/WAI/ARIA/apg/patterns/textinput/"
|
|
19
|
+
>
|
|
20
|
+
<div class="mt-8">
|
|
21
|
+
<p>Rapport d’audit manuel : <a href="/audits/SyTextField.xlsx" style={{ color:'#0C41BD' }}>Voir le rapport</a></p>
|
|
14
22
|
<p style={{ color: 'grey', fontSize: '14px', marginTop: '0px' }}>Correctifs associés (<a href="https://github.com/assurance-maladie-digital/design-system-v3/issues/935" target="_blank" style={{color:'#0C41BD'}}>issue #935</a>), (<a href="https://github.com/assurance-maladie-digital/design-system/issues/4028" target="_blank" style={{color:'#0C41BD'}}>issue #4028</a>)</p>
|
|
15
23
|
</div>
|
|
24
|
+
|
|
25
|
+
<CriteriaSection>
|
|
26
|
+
<CriteriaCard icon="🔍" title="Structure sémantique et attributs">
|
|
27
|
+
<ul>
|
|
28
|
+
<li><strong>Élément input natif</strong> : Utilisation de <code><input></code> via VTextField pour une sémantique correcte.</li>
|
|
29
|
+
<li><strong>Labels explicites</strong> : Gestion automatique du <code>aria-label</code> combinant label, préfixe et suffixe. L'attribut <code>aria-required</code> est ajouté si le champ est requis.</li>
|
|
30
|
+
<li><strong>Association avec les messages</strong> : Implémentation dynamique de <code>aria-describedby</code> pour lier le champ à ses messages d'erreur, d'avertissement ou de succès.</li>
|
|
31
|
+
<li><strong>Icônes décoratives</strong> : Les icônes de validation (erreur, avertissement, succès) sont masquées aux lecteurs d'écran (<code>role="presentation"</code>) pour éviter la redondance avec les messages textuels.</li>
|
|
32
|
+
</ul>
|
|
33
|
+
</CriteriaCard>
|
|
34
|
+
|
|
35
|
+
<CriteriaCard icon="⌨️" title="Navigation et interaction clavier">
|
|
36
|
+
<ul>
|
|
37
|
+
<li><strong>Focus natif</strong> : Le champ est naturellement focusable via <kbd>Tab</kbd>.</li>
|
|
38
|
+
<li><strong>Boutons accessibles</strong> : Les icônes interactives (prepend/append) sont des boutons focusables avec des labels descriptifs et gèrent les événements <kbd>Entrée</kbd> et <kbd>Espace</kbd>.</li>
|
|
39
|
+
<li><strong>Bouton de vidage</strong> : Le bouton "clear" possède un <code>aria-label</code> descriptif ("Vider [label]") et est accessible au clavier.</li>
|
|
40
|
+
<li><strong>Indicateur de focus</strong> : Styles de focus visibles sur le champ et les icônes interactives.</li>
|
|
41
|
+
</ul>
|
|
42
|
+
</CriteriaCard>
|
|
43
|
+
|
|
44
|
+
<CriteriaCard icon="🎨" title="Styles et états visuels">
|
|
45
|
+
<ul>
|
|
46
|
+
<li><strong>Contrastes garantis</strong> : Couleurs distinctes pour les états erreur (rouge), avertissement (orange) et succès (vert) respectant les critères WCAG.</li>
|
|
47
|
+
<li><strong>États cohérents</strong> : Changements visuels clairs entre les états normal, erreur, avertissement et succès.</li>
|
|
48
|
+
<li><strong>Astérisque optionnel</strong> : Possibilité d'afficher un astérisque visuel pour les champs requis via la prop <code>display-asterisk</code>.</li>
|
|
49
|
+
</ul>
|
|
50
|
+
</CriteriaCard>
|
|
51
|
+
</CriteriaSection>
|
|
52
|
+
|
|
53
|
+
<DemoSection componentName="SyTextField">
|
|
54
|
+
<Primary />
|
|
55
|
+
</DemoSection>
|
|
56
|
+
|
|
57
|
+
<BestPracticesSection>
|
|
58
|
+
<ul>
|
|
59
|
+
<li><strong>Labels descriptifs</strong> : Utilisez toujours un <code>label</code> clair et concis. Évitez les placeholders comme seuls indicateurs de champ.</li>
|
|
60
|
+
<li><strong>Messages d'erreur utiles</strong> : Fournissez des messages d'erreur spécifiques qui aident l'utilisateur à corriger sa saisie.</li>
|
|
61
|
+
<li><strong>Validation appropriée</strong> : Utilisez la validation au blur (<code>isValidateOnBlur</code>) pour ne pas surcharger l'utilisateur pendant la saisie.</li>
|
|
62
|
+
<li><strong>Évitez les changements de contexte automatiques</strong> : Ne soumettez pas automatiquement le formulaire ou ne changez pas de page lors de la saisie.</li>
|
|
63
|
+
<li><strong>Préfixes et suffixes accessibles</strong> : Le composant ajoute automatiquement des spans screen-reader-only pour le contenu textuel des préfixes/suffixes.</li>
|
|
64
|
+
</ul>
|
|
65
|
+
</BestPracticesSection>
|
|
66
|
+
|
|
67
|
+
<ResourcesSection>
|
|
68
|
+
<ul>
|
|
69
|
+
<li><a href="https://www.w3.org/WAI/ARIA/apg/patterns/textinput/" target="_blank" rel="noopener noreferrer">Guide des pratiques WAI-ARIA : Champs de texte</a></li>
|
|
70
|
+
<li><a href="https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#11.9" target="_blank" rel="noopener noreferrer">RGAA : Champs de formulaire</a></li>
|
|
71
|
+
</ul>
|
|
72
|
+
</ResourcesSection>
|
|
73
|
+
</AccessibilityGuideLayout>
|
|
@@ -24,4 +24,19 @@ describe('SyTextField – accessibility (axe)', () => {
|
|
|
24
24
|
ignoreRules: ['region'],
|
|
25
25
|
})
|
|
26
26
|
})
|
|
27
|
+
|
|
28
|
+
it('has no obvious axe violations when loading is true', async () => {
|
|
29
|
+
const wrapper = mount(SyTextField, {
|
|
30
|
+
props: {
|
|
31
|
+
label: 'Nom',
|
|
32
|
+
modelValue: '',
|
|
33
|
+
loading: true,
|
|
34
|
+
},
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
const results = await axe(wrapper.element as HTMLElement)
|
|
38
|
+
assertNoA11yViolations(results, 'SyTextField – loading state', {
|
|
39
|
+
ignoreRules: ['region'],
|
|
40
|
+
})
|
|
41
|
+
})
|
|
27
42
|
})
|
|
@@ -209,6 +209,42 @@ describe('SyTextField', () => {
|
|
|
209
209
|
expect(messages.text()).toContain('Attention : Test Field peut contenir une erreur')
|
|
210
210
|
})
|
|
211
211
|
|
|
212
|
+
describe('loading', () => {
|
|
213
|
+
it('shows progress bar when loading is true', async () => {
|
|
214
|
+
wrapper = mount(SyTextField, {
|
|
215
|
+
props: { loading: true, label: 'Nom' },
|
|
216
|
+
})
|
|
217
|
+
await wrapper.vm.$nextTick()
|
|
218
|
+
expect(wrapper.find('.v-progress-linear').exists()).toBe(true)
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
it('does not show progress bar when loading is false', async () => {
|
|
222
|
+
wrapper = mount(SyTextField, {
|
|
223
|
+
props: { loading: false, label: 'Nom' },
|
|
224
|
+
})
|
|
225
|
+
await wrapper.vm.$nextTick()
|
|
226
|
+
expect(wrapper.find('.v-progress-linear').exists()).toBe(false)
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
it('sets aria-label with field label when loading', async () => {
|
|
230
|
+
wrapper = mount(SyTextField, {
|
|
231
|
+
props: { loading: true, label: 'Nom' },
|
|
232
|
+
})
|
|
233
|
+
await wrapper.vm.$nextTick()
|
|
234
|
+
const bar = wrapper.find('.v-progress-linear')
|
|
235
|
+
expect(bar.attributes('aria-label')).toBe('Chargement de Nom')
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
it('sets generic aria-label when no label and loading', async () => {
|
|
239
|
+
wrapper = mount(SyTextField, {
|
|
240
|
+
props: { loading: true },
|
|
241
|
+
})
|
|
242
|
+
await wrapper.vm.$nextTick()
|
|
243
|
+
const bar = wrapper.find('.v-progress-linear')
|
|
244
|
+
expect(bar.attributes('aria-label')).toBe('Chargement en cours')
|
|
245
|
+
})
|
|
246
|
+
})
|
|
247
|
+
|
|
212
248
|
it('maintains input value without validation rules', async () => {
|
|
213
249
|
wrapper = mount(SyTextField)
|
|
214
250
|
const input = wrapper.find('input')
|
|
@@ -1,15 +1,83 @@
|
|
|
1
|
-
import { Meta,
|
|
2
|
-
import * as
|
|
3
|
-
import '@/
|
|
1
|
+
import { Meta, Primary } from '@storybook/blocks';
|
|
2
|
+
import * as DataListStories from '../DataList.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={
|
|
13
|
+
<Meta of={DataListStories}/>
|
|
6
14
|
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
15
|
+
<AccessibilityGuideLayout
|
|
16
|
+
componentName="DataList"
|
|
17
|
+
iconSrc={AccessibilityIcon}
|
|
18
|
+
apgHref="https://www.w3.org/WAI/ARIA/apg/patterns/listbox/"
|
|
19
|
+
>
|
|
20
|
+
<div class="mt-8">
|
|
21
|
+
<p>Rapport d'audit manuel : <a href="/audits/DataList.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/4030" target="_blank" style={{color:'#0C41BD'}}>issue #4030</a>)</p>
|
|
23
|
+
</div>
|
|
10
24
|
|
|
25
|
+
<CriteriaSection>
|
|
26
|
+
<CriteriaCard icon="🔍" title="Structure sémantique des listes">
|
|
27
|
+
<ul>
|
|
28
|
+
<li><strong>Élément dl/dt/dd</strong> : Utilisation native des balises de liste de définitions pour une sémantique correcte</li>
|
|
29
|
+
<li><strong>Section avec titre</strong> : Conteneur <code><section></code> avec <code>aria-labelledby</code> lorsque <code>listTitle</code> est fourni</li>
|
|
30
|
+
<li><strong>Titre personnalisable</strong> : Tag de titre configurable (<code>titleTag</code>) avec ID unique pour l'association ARIA</li>
|
|
31
|
+
</ul>
|
|
32
|
+
</CriteriaCard>
|
|
11
33
|
|
|
12
|
-
<
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
|
|
34
|
+
<CriteriaCard icon="⌨️" title="Navigation et interaction">
|
|
35
|
+
<ul>
|
|
36
|
+
<li><strong>Boutons d'action</strong> : Utilisation de <code>VBtn</code> natif pour les actions avec focus clavier correct</li>
|
|
37
|
+
<li><strong>Focus visible</strong> : Style <code>:focus-visible::after</code> pour une indication claire de navigation</li>
|
|
38
|
+
<li><strong>Événements accessibles</strong> : Émission d'événements <code>click:item-action</code> pour les interactions</li>
|
|
39
|
+
</ul>
|
|
40
|
+
</CriteriaCard>
|
|
41
|
+
|
|
42
|
+
<CriteriaCard icon="🎨" title="Icônes et éléments visuels">
|
|
43
|
+
<ul>
|
|
44
|
+
<li><strong>Icônes décoratives</strong> : Icônes avec <code>decorative="true"</code> pour masquer aux lecteurs d'écran</li>
|
|
45
|
+
<li><strong>Contrastes adaptatifs</strong> : Couleurs de label adaptées au thème clair/sombre</li>
|
|
46
|
+
<li><strong>Chips accessibles</strong> : Utilisation de <code>VChip</code> pour les valeurs avec contraste approprié</li>
|
|
47
|
+
</ul>
|
|
48
|
+
</CriteriaCard>
|
|
49
|
+
|
|
50
|
+
<CriteriaCard icon="📱" title="Flexibilité et responsive">
|
|
51
|
+
<ul>
|
|
52
|
+
<li><strong>Layout adaptable</strong> : Mode <code>row</code> pour les affichages horizontaux avec flexbox</li>
|
|
53
|
+
<li><strong>Widthable</strong> : Gestion des dimensions via <code>useWidthable</code> pour le responsive</li>
|
|
54
|
+
<li><strong>Slots personnalisables</strong> : Slots <code>value</code>, <code>action</code>, <code>icon</code> pour une flexibilité maximale</li>
|
|
55
|
+
</ul>
|
|
56
|
+
</CriteriaCard>
|
|
57
|
+
</CriteriaSection>
|
|
58
|
+
|
|
59
|
+
<DemoSection componentName="DataList">
|
|
60
|
+
<Primary />
|
|
61
|
+
</DemoSection>
|
|
62
|
+
|
|
63
|
+
<BestPracticesSection>
|
|
64
|
+
<ul>
|
|
65
|
+
<li><strong>Titres descriptifs</strong> : Utilisez toujours <code>listTitle</code> pour fournir un contexte aux listes importantes</li>
|
|
66
|
+
<li><strong>Labels clairs</strong> : Assurez-vous que les <code>key</code> (labels) sont concis et descriptifs</li>
|
|
67
|
+
<li><strong>Actions explicites</strong> : Utilisez des verbes d'action clairs pour les boutons ("Modifier", "Supprimer", "Voir")</li>
|
|
68
|
+
<li><strong>Ordre logique</strong> : Maintenez un ordre cohérent des paires label/valeur dans toute l'application</li>
|
|
69
|
+
<li><strong>Slots sécurisés</strong> : Préférez le slot <code>value</code> à <code>renderHtmlValue</code> pour le contenu HTML</li>
|
|
70
|
+
<li><strong>États de chargement</strong> : Utilisez <code>loading</code> avec <code>DataListLoading</code> pour les données asynchrones</li>
|
|
71
|
+
</ul>
|
|
72
|
+
</BestPracticesSection>
|
|
73
|
+
|
|
74
|
+
<ResourcesSection>
|
|
75
|
+
<ul>
|
|
76
|
+
<li><a href="https://www.w3.org/WAI/ARIA/apg/patterns/listbox/" target="_blank" rel="noopener noreferrer">Guide des pratiques WAI-ARIA : Listbox</a></li>
|
|
77
|
+
<li><a href="https://www.w3.org/WAI/WCAG21/quickref/" target="_blank" rel="noopener noreferrer">Référence rapide WCAG 2.1</a></li>
|
|
78
|
+
<li><a href="https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#11.10" target="_blank" rel="noopener noreferrer">RGAA Critère 11.10 : Listes de définitions</a></li>
|
|
79
|
+
<li><a href="https://developer.mozilla.org/fr/docs/Web/HTML/Element/dl" target="_blank" rel="noopener noreferrer">MDN : Élément dl - Liste de définitions</a></li>
|
|
80
|
+
</ul>
|
|
81
|
+
</ResourcesSection>
|
|
82
|
+
|
|
83
|
+
</AccessibilityGuideLayout>
|
|
@@ -1,14 +1,83 @@
|
|
|
1
|
-
import { Meta,
|
|
2
|
-
import * as
|
|
3
|
-
import '@/
|
|
1
|
+
import { Meta, Primary } from '@storybook/blocks';
|
|
2
|
+
import * as DataListGroupStories from '../DataListGroup.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={
|
|
13
|
+
<Meta of={DataListGroupStories}/>
|
|
6
14
|
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
<
|
|
15
|
+
<AccessibilityGuideLayout
|
|
16
|
+
componentName="DataListGroup"
|
|
17
|
+
iconSrc={AccessibilityIcon}
|
|
18
|
+
apgHref="https://www.w3.org/WAI/ARIA/apg/patterns/listbox/"
|
|
19
|
+
>
|
|
20
|
+
<div class="mt-8">
|
|
21
|
+
<p>Rapport d'audit manuel : <a href="/audits/DataListGroup.xlsx" style={{ color:'#0C41BD' }}>Voir le rapport</a></p>
|
|
13
22
|
<p style={{ color: 'grey', fontSize: '14px', marginTop: '0px' }}>Correctifs associés (<a href="https://github.com/assurance-maladie-digital/design-system-v3/issues/651" target="_blank" style={{color:'#0C41BD'}}>issue #651</a>)</p>
|
|
14
|
-
</div>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<CriteriaSection>
|
|
26
|
+
<CriteriaCard icon="🔍" title="Structure sémantique des groupes">
|
|
27
|
+
<ul>
|
|
28
|
+
<li><strong>Élément ul/li</strong> : Utilisation native de liste non ordonnée pour regrouper les DataList</li>
|
|
29
|
+
<li><strong>Composition sémantique</strong> : Chaque élément contient un DataList avec structure dl/dt/dd héritée</li>
|
|
30
|
+
<li><strong>Titres hiérarchiques</strong> : Tags de titre configurables (<code>titlesTag</code>) pour chaque sous-liste</li>
|
|
31
|
+
</ul>
|
|
32
|
+
</CriteriaCard>
|
|
33
|
+
|
|
34
|
+
<CriteriaCard icon="⌨️" title="Navigation et interactions">
|
|
35
|
+
<ul>
|
|
36
|
+
<li><strong>Focus séquentiel</strong> : Navigation logique entre les différents groupes et leurs éléments</li>
|
|
37
|
+
<li><strong>Actions contextualisées</strong> : Événements <code>click:list-item</code> avec indices doubles (dataListIndex, itemIndex)</li>
|
|
38
|
+
<li><strong>Boutons accessibles</strong> : Actions héritées des DataList avec focus clavier correct</li>
|
|
39
|
+
</ul>
|
|
40
|
+
</CriteriaCard>
|
|
41
|
+
|
|
42
|
+
<CriteriaCard icon="🎨" title="Mise en page et responsive">
|
|
43
|
+
<ul>
|
|
44
|
+
<li><strong>Layout flexbox</strong> : Utilisation de <code>d-flex</code> pour l'affichage horizontal des groupes</li>
|
|
45
|
+
<li><strong>Largeurs configurables</strong> : <code>itemWidth</code> pour contrôler la taille de chaque groupe</li>
|
|
46
|
+
<li><strong>Marges négatives</strong> : <code>ma-n4</code> sur le conteneur avec <code>ma-4</code> sur les éléments pour un espacement optimal</li>
|
|
47
|
+
</ul>
|
|
48
|
+
</CriteriaCard>
|
|
49
|
+
|
|
50
|
+
<CriteriaCard icon="📱" title="États et chargement">
|
|
51
|
+
<ul>
|
|
52
|
+
<li><strong>États de chargement</strong> : Propagation de <code>loading</code> à tous les DataList enfants</li>
|
|
53
|
+
<li><strong>Slots avancés</strong> : Slot <code>item</code> avec contexte enrichi (dataListIndex inclus)</li>
|
|
54
|
+
<li><strong>Gestion HTML</strong> : Support de <code>renderHtmlValue</code> avec avertissement de dépréciation</li>
|
|
55
|
+
</ul>
|
|
56
|
+
</CriteriaCard>
|
|
57
|
+
</CriteriaSection>
|
|
58
|
+
|
|
59
|
+
<DemoSection componentName="DataListGroup">
|
|
60
|
+
<Primary />
|
|
61
|
+
</DemoSection>
|
|
62
|
+
|
|
63
|
+
<BestPracticesSection>
|
|
64
|
+
<ul>
|
|
65
|
+
<li><strong>Groupes cohérents</strong> : Organisez les DataList par thématiques logiques (informations personnelles, coordonnées, etc.)</li>
|
|
66
|
+
<li><strong>Titres distinctifs</strong> : Utilisez des <code>title</code> uniques et descriptifs pour chaque groupe</li>
|
|
67
|
+
<li><strong>Largeurs adaptées</strong> : Choisissez <code>itemWidth</code> en fonction du contenu (plus large pour les textes longs)</li>
|
|
68
|
+
<li><strong>Actions groupées</strong> : Maintenez la cohérence des actions entre les différents groupes</li>
|
|
69
|
+
<li><strong>États synchronisés</strong> : Utilisez <code>loading</code> au niveau du groupe pour des chargements coordonnés</li>
|
|
70
|
+
<li><strong>Slots contextuels</strong> : Exploitez le <code>data-list-index</code> dans les slots pour des personnalisations avancées</li>
|
|
71
|
+
</ul>
|
|
72
|
+
</BestPracticesSection>
|
|
73
|
+
|
|
74
|
+
<ResourcesSection>
|
|
75
|
+
<ul>
|
|
76
|
+
<li><a href="https://www.w3.org/WAI/ARIA/apg/patterns/listbox/" target="_blank" rel="noopener noreferrer">Guide des pratiques WAI-ARIA : Listbox</a></li>
|
|
77
|
+
<li><a href="https://www.w3.org/WAI/WCAG21/quickref/" target="_blank" rel="noopener noreferrer">Référence rapide WCAG 2.1</a></li>
|
|
78
|
+
<li><a href="https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#11.10" target="_blank" rel="noopener noreferrer">RGAA Critère 11.10 : Listes de définitions</a></li>
|
|
79
|
+
<li><a href="https://developer.mozilla.org/fr/docs/Web/HTML/Element/ul" target="_blank" rel="noopener noreferrer">MDN : Élément ul - Liste non ordonnée</a></li>
|
|
80
|
+
</ul>
|
|
81
|
+
</ResourcesSection>
|
|
82
|
+
|
|
83
|
+
</AccessibilityGuideLayout>
|
|
@@ -0,0 +1,25 @@
|
|
|
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 DownloadBtn from '../DownloadBtn.vue'
|
|
8
|
+
|
|
9
|
+
describe('DownloadBtn – accessibility (axe)', () => {
|
|
10
|
+
it('has no obvious axe violations', async () => {
|
|
11
|
+
const wrapper = mount(DownloadBtn, {
|
|
12
|
+
props: {
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- deso
|
|
14
|
+
filePromise: () => Promise.resolve({ data: new Blob(), status: 200, statusText: 'OK', headers: {}, config: {} as any }),
|
|
15
|
+
fallbackFilename: 'file.pdf',
|
|
16
|
+
},
|
|
17
|
+
slots: {
|
|
18
|
+
default: 'Télécharger',
|
|
19
|
+
},
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
const results = await axe(wrapper.element as HTMLElement)
|
|
23
|
+
assertNoA11yViolations(results, 'DownloadBtn – default state')
|
|
24
|
+
})
|
|
25
|
+
})
|
|
@@ -75,12 +75,53 @@ export const WithLink: Story = {
|
|
|
75
75
|
},
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
export const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
export const CustomIllustration: Story = {
|
|
79
|
+
decorators: [
|
|
80
|
+
() => ({ template: '<div style="padding: 20px; background: rgb(231, 236, 245)"><story /></div>' }),
|
|
81
|
+
],
|
|
82
|
+
parameters: {
|
|
83
|
+
sourceCode: [
|
|
84
|
+
{
|
|
85
|
+
name: 'Template',
|
|
86
|
+
code: `
|
|
87
|
+
<template>
|
|
88
|
+
<div style="padding: 20px; background: rgb(231, 236, 245)">
|
|
89
|
+
<ErrorPage>
|
|
90
|
+
<template #illustration>
|
|
91
|
+
<div style="width: 260px; height: 200px; display: grid; place-items: center; border-radius: 12px; background: white; border: 2px dashed #0D419A;">
|
|
92
|
+
<span style="font-weight: 700; color: #0D419A;">Illustration</span>
|
|
93
|
+
</div>
|
|
94
|
+
</template>
|
|
95
|
+
</ErrorPage>
|
|
96
|
+
</div>
|
|
97
|
+
</template>
|
|
98
|
+
`,
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: 'Script',
|
|
102
|
+
code: `
|
|
103
|
+
<script setup lang="ts">
|
|
104
|
+
import { ErrorPage } from '@cnamts/synapse'
|
|
105
|
+
</script>
|
|
106
|
+
`,
|
|
107
|
+
},
|
|
108
|
+
],
|
|
83
109
|
},
|
|
110
|
+
render: () => ({
|
|
111
|
+
components: { ErrorPage },
|
|
112
|
+
template: `
|
|
113
|
+
<ErrorPage>
|
|
114
|
+
<template #illustration>
|
|
115
|
+
<div style="width: 260px; height: 200px; display: grid; place-items: center; border-radius: 12px; background: white; border: 2px dashed #0D419A;">
|
|
116
|
+
<span style="font-weight: 700; color: #0D419A;">Illustration</span>
|
|
117
|
+
</div>
|
|
118
|
+
</template>
|
|
119
|
+
</ErrorPage>
|
|
120
|
+
`,
|
|
121
|
+
}),
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export const SlotAction: Story = {
|
|
84
125
|
decorators: [
|
|
85
126
|
() => ({ template: '<div style="padding: 20px; background: rgb(231, 236, 245)"><story /></div>' }),
|
|
86
127
|
],
|
|
@@ -91,14 +132,19 @@ export const WithRole: Story = {
|
|
|
91
132
|
code: `
|
|
92
133
|
<template>
|
|
93
134
|
<div style="padding: 20px; background: rgb(231, 236, 245)">
|
|
94
|
-
<ErrorPage
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
135
|
+
<ErrorPage :hide-btn="true">
|
|
136
|
+
<template #action>
|
|
137
|
+
<div style="display: flex; gap: 8px; margin-top: 16px;">
|
|
138
|
+
<VBtn href="/" color="primary">Retour à l'accueil</VBtn>
|
|
139
|
+
<VBtn variant="outlined" color="primary">Déconnexion</VBtn>
|
|
140
|
+
</div>
|
|
141
|
+
</template>
|
|
142
|
+
</ErrorPage>
|
|
98
143
|
</div>
|
|
99
144
|
</template>
|
|
100
145
|
`,
|
|
101
|
-
},
|
|
146
|
+
},
|
|
147
|
+
{
|
|
102
148
|
name: 'Script',
|
|
103
149
|
code: `
|
|
104
150
|
<script setup lang="ts">
|
|
@@ -108,9 +154,22 @@ export const WithRole: Story = {
|
|
|
108
154
|
},
|
|
109
155
|
],
|
|
110
156
|
},
|
|
157
|
+
render: () => ({
|
|
158
|
+
components: { ErrorPage },
|
|
159
|
+
template: `
|
|
160
|
+
<ErrorPage :hide-btn="true">
|
|
161
|
+
<template #action>
|
|
162
|
+
<div style="display: flex; gap: 8px; margin-top: 16px;">
|
|
163
|
+
<VBtn href="/" color="primary">Retour à l'accueil</VBtn>
|
|
164
|
+
<VBtn variant="outlined" color="primary">Déconnexion</VBtn>
|
|
165
|
+
</div>
|
|
166
|
+
</template>
|
|
167
|
+
</ErrorPage>
|
|
168
|
+
`,
|
|
169
|
+
}),
|
|
111
170
|
}
|
|
112
171
|
|
|
113
|
-
export const
|
|
172
|
+
export const SlotAdditionalContent: Story = {
|
|
114
173
|
decorators: [
|
|
115
174
|
() => ({ template: '<div style="padding: 20px; background: rgb(231, 236, 245)"><story /></div>' }),
|
|
116
175
|
],
|
|
@@ -122,10 +181,10 @@ export const CustomIllustration: Story = {
|
|
|
122
181
|
<template>
|
|
123
182
|
<div style="padding: 20px; background: rgb(231, 236, 245)">
|
|
124
183
|
<ErrorPage>
|
|
125
|
-
<template #
|
|
126
|
-
<
|
|
127
|
-
|
|
128
|
-
</
|
|
184
|
+
<template #additional-content>
|
|
185
|
+
<p style="text-align: center; color: #555;">
|
|
186
|
+
Si le problème persiste, veuillez contacter le support technique.
|
|
187
|
+
</p>
|
|
129
188
|
</template>
|
|
130
189
|
</ErrorPage>
|
|
131
190
|
</div>
|
|
@@ -146,12 +205,47 @@ export const CustomIllustration: Story = {
|
|
|
146
205
|
components: { ErrorPage },
|
|
147
206
|
template: `
|
|
148
207
|
<ErrorPage>
|
|
149
|
-
<template #
|
|
150
|
-
<
|
|
151
|
-
|
|
152
|
-
</
|
|
208
|
+
<template #additional-content>
|
|
209
|
+
<p style="text-align: center; color: #555;">
|
|
210
|
+
Si le problème persiste, veuillez contacter le support technique.
|
|
211
|
+
</p>
|
|
153
212
|
</template>
|
|
154
213
|
</ErrorPage>
|
|
155
214
|
`,
|
|
156
215
|
}),
|
|
157
216
|
}
|
|
217
|
+
|
|
218
|
+
export const WithRole: Story = {
|
|
219
|
+
args: {
|
|
220
|
+
...Default.args,
|
|
221
|
+
role: 'region',
|
|
222
|
+
uniqueId: 'error-page-region',
|
|
223
|
+
},
|
|
224
|
+
decorators: [
|
|
225
|
+
() => ({ template: '<div style="padding: 20px; background: rgb(231, 236, 245)"><story /></div>' }),
|
|
226
|
+
],
|
|
227
|
+
parameters: {
|
|
228
|
+
sourceCode: [
|
|
229
|
+
{
|
|
230
|
+
name: 'Template',
|
|
231
|
+
code: `
|
|
232
|
+
<template>
|
|
233
|
+
<div style="padding: 20px; background: rgb(231, 236, 245)">
|
|
234
|
+
<ErrorPage
|
|
235
|
+
role="region"
|
|
236
|
+
unique-id="error-page-region"
|
|
237
|
+
/>
|
|
238
|
+
</div>
|
|
239
|
+
</template>
|
|
240
|
+
`,
|
|
241
|
+
}, {
|
|
242
|
+
name: 'Script',
|
|
243
|
+
code: `
|
|
244
|
+
<script setup lang="ts">
|
|
245
|
+
import { ErrorPage } from '@cnamts/synapse'
|
|
246
|
+
</script>
|
|
247
|
+
`,
|
|
248
|
+
},
|
|
249
|
+
],
|
|
250
|
+
},
|
|
251
|
+
}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
btnHref?: string
|
|
16
16
|
btnLink?: RouteRecordRaw | string
|
|
17
17
|
hideBtn?: boolean
|
|
18
|
-
headingLevel
|
|
18
|
+
headingLevel?: 1 | 2 | 3 | 4 | 5 | 6
|
|
19
19
|
uniqueId?: string
|
|
20
20
|
role?: PageAriaRole
|
|
21
21
|
}>()
|
|
@@ -39,7 +39,8 @@
|
|
|
39
39
|
:btn-href="props.btnHref"
|
|
40
40
|
:btn-link="props.btnLink"
|
|
41
41
|
:hide-btn="props.hideBtn"
|
|
42
|
-
:unique-id="props.uniqueId"
|
|
42
|
+
:unique-id="props.uniqueId ?? undefined"
|
|
43
|
+
:heading-level="props.headingLevel"
|
|
43
44
|
:role="props.role"
|
|
44
45
|
>
|
|
45
46
|
<template
|
|
@@ -55,6 +56,20 @@
|
|
|
55
56
|
>
|
|
56
57
|
</slot>
|
|
57
58
|
</template>
|
|
59
|
+
|
|
60
|
+
<template
|
|
61
|
+
v-if="$slots.action"
|
|
62
|
+
#action
|
|
63
|
+
>
|
|
64
|
+
<slot name="action" />
|
|
65
|
+
</template>
|
|
66
|
+
|
|
67
|
+
<template
|
|
68
|
+
v-if="$slots['additional-content']"
|
|
69
|
+
#additional-content
|
|
70
|
+
>
|
|
71
|
+
<slot name="additional-content" />
|
|
72
|
+
</template>
|
|
58
73
|
</StatusPage>
|
|
59
74
|
</template>
|
|
60
75
|
|
|
@@ -18,4 +18,21 @@ describe('ErrorPage – accessibility (axe)', () => {
|
|
|
18
18
|
ignoreRules: ['region'],
|
|
19
19
|
})
|
|
20
20
|
})
|
|
21
|
+
|
|
22
|
+
it('has no obvious axe violations with #action slot', async () => {
|
|
23
|
+
const wrapper = mount(ErrorPage, {
|
|
24
|
+
attachTo: document.body,
|
|
25
|
+
props: { headingLevel: 1, hideBtn: true },
|
|
26
|
+
slots: {
|
|
27
|
+
action: '<button>Retour à l\'accueil</button>',
|
|
28
|
+
},
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const results = await axe(document.body)
|
|
32
|
+
assertNoA11yViolations(results, 'ErrorPage – action slot', {
|
|
33
|
+
ignoreRules: ['region'],
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
wrapper.unmount()
|
|
37
|
+
})
|
|
21
38
|
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest'
|
|
2
|
-
import { shallowMount } from '@vue/test-utils'
|
|
2
|
+
import { mount, shallowMount } from '@vue/test-utils'
|
|
3
3
|
import ErrorPage from '../ErrorPage.vue'
|
|
4
4
|
|
|
5
5
|
describe('ErrorPage', () => {
|
|
@@ -8,4 +8,24 @@ describe('ErrorPage', () => {
|
|
|
8
8
|
|
|
9
9
|
expect(wrapper.html()).toMatchSnapshot()
|
|
10
10
|
})
|
|
11
|
+
|
|
12
|
+
it('renders #action slot content', () => {
|
|
13
|
+
const wrapper = mount(ErrorPage, {
|
|
14
|
+
slots: {
|
|
15
|
+
action: '<button>Retour à l\'accueil</button>',
|
|
16
|
+
},
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
expect(wrapper.html()).toContain('Retour à l\'accueil')
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it('renders #additional-content slot content', () => {
|
|
23
|
+
const wrapper = mount(ErrorPage, {
|
|
24
|
+
slots: {
|
|
25
|
+
'additional-content': '<p>Contenu additionnel</p>',
|
|
26
|
+
},
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
expect(wrapper.html()).toContain('Contenu additionnel')
|
|
30
|
+
})
|
|
11
31
|
})
|