@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
|
@@ -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 ExternalLinks from '../ExternalLinks.vue'
|
|
8
|
+
|
|
9
|
+
describe('ExternalLinks – accessibility (axe)', () => {
|
|
10
|
+
it('has no obvious axe violations', async () => {
|
|
11
|
+
const wrapper = mount(ExternalLinks, {
|
|
12
|
+
props: {
|
|
13
|
+
items: [
|
|
14
|
+
{ text: 'ameli.fr', href: 'https://ameli.fr' },
|
|
15
|
+
{ text: 'Legifrance', href: 'https://legifrance.gouv.fr' },
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
const results = await axe(wrapper.element as HTMLElement)
|
|
21
|
+
assertNoA11yViolations(results, 'ExternalLinks – default state')
|
|
22
|
+
})
|
|
23
|
+
})
|
|
@@ -161,6 +161,44 @@ const meta = {
|
|
|
161
161
|
},
|
|
162
162
|
},
|
|
163
163
|
},
|
|
164
|
+
'seeLabel': {
|
|
165
|
+
description: 'Label du bouton de prévisualisation',
|
|
166
|
+
control: 'text',
|
|
167
|
+
table: {
|
|
168
|
+
category: 'props',
|
|
169
|
+
type: {
|
|
170
|
+
summary: 'string',
|
|
171
|
+
},
|
|
172
|
+
defaultValue: {
|
|
173
|
+
summary: 'Voir le fichier',
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
'deleteLabel': {
|
|
178
|
+
description: 'Label du bouton de suppression',
|
|
179
|
+
control: 'text',
|
|
180
|
+
table: {
|
|
181
|
+
category: 'props',
|
|
182
|
+
type: { summary: 'string',
|
|
183
|
+
},
|
|
184
|
+
defaultValue: {
|
|
185
|
+
summary: 'Supprimer le fichier',
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
'importLabel': {
|
|
190
|
+
description: 'Label du bouton d\'upload',
|
|
191
|
+
control: 'text',
|
|
192
|
+
table: {
|
|
193
|
+
category: 'props',
|
|
194
|
+
type: {
|
|
195
|
+
summary: 'string',
|
|
196
|
+
},
|
|
197
|
+
defaultValue: {
|
|
198
|
+
summary: 'Importer le fichier',
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
},
|
|
164
202
|
},
|
|
165
203
|
parameters: {
|
|
166
204
|
controls: {
|
|
@@ -197,6 +235,9 @@ export const Default: Story = {
|
|
|
197
235
|
onPreview: fn(),
|
|
198
236
|
},
|
|
199
237
|
parameters: {
|
|
238
|
+
a11y: {
|
|
239
|
+
disable: false,
|
|
240
|
+
},
|
|
200
241
|
sourceCode: [
|
|
201
242
|
{
|
|
202
243
|
name: 'Template',
|
|
@@ -267,7 +308,7 @@ export const States: Story = {
|
|
|
267
308
|
},
|
|
268
309
|
parameters: {
|
|
269
310
|
a11y: {
|
|
270
|
-
disable:
|
|
311
|
+
disable: false,
|
|
271
312
|
},
|
|
272
313
|
sourceCode: [
|
|
273
314
|
{
|
|
@@ -339,6 +380,9 @@ export const OptionalDocument: Story = {
|
|
|
339
380
|
onPreview: fn(),
|
|
340
381
|
},
|
|
341
382
|
parameters: {
|
|
383
|
+
a11y: {
|
|
384
|
+
disable: false,
|
|
385
|
+
},
|
|
342
386
|
sourceCode: [
|
|
343
387
|
{
|
|
344
388
|
name: 'Template',
|
|
@@ -415,6 +459,9 @@ export const Actions: Story = {
|
|
|
415
459
|
onPreview: fn(),
|
|
416
460
|
},
|
|
417
461
|
parameters: {
|
|
462
|
+
a11y: {
|
|
463
|
+
disable: false,
|
|
464
|
+
},
|
|
418
465
|
sourceCode: [
|
|
419
466
|
{
|
|
420
467
|
name: 'Template',
|
|
@@ -512,6 +559,9 @@ export const Customization: Story = {
|
|
|
512
559
|
`,
|
|
513
560
|
}),
|
|
514
561
|
parameters: {
|
|
562
|
+
a11y: {
|
|
563
|
+
disable: false,
|
|
564
|
+
},
|
|
515
565
|
sourceCode: [
|
|
516
566
|
{
|
|
517
567
|
name: 'Template',
|
|
@@ -32,6 +32,9 @@
|
|
|
32
32
|
showPreviewBtn?: boolean
|
|
33
33
|
tag?: string
|
|
34
34
|
locales?: typeof defaultLocales
|
|
35
|
+
seeLabel?: string
|
|
36
|
+
deleteLabel?: string
|
|
37
|
+
importLabel?: string
|
|
35
38
|
}>(), {
|
|
36
39
|
fileName: undefined,
|
|
37
40
|
message: undefined,
|
|
@@ -43,6 +46,9 @@
|
|
|
43
46
|
showPreviewBtn: false,
|
|
44
47
|
tag: 'div',
|
|
45
48
|
locales: () => defaultLocales,
|
|
49
|
+
seeLabel: defaultLocales.see,
|
|
50
|
+
deleteLabel: defaultLocales.delete,
|
|
51
|
+
importLabel: defaultLocales.import,
|
|
46
52
|
})
|
|
47
53
|
|
|
48
54
|
defineSlots<{
|
|
@@ -132,10 +138,10 @@
|
|
|
132
138
|
v-if="(state === 'initial' || state == 'error') && showUploadBtn"
|
|
133
139
|
class="file-item__action file-item__action-upload text-primary"
|
|
134
140
|
variant="text"
|
|
135
|
-
:aria-label="locales.
|
|
141
|
+
:aria-label="`${locales.import} ${title}`"
|
|
136
142
|
@click="$emit('upload', itemId)"
|
|
137
143
|
>
|
|
138
|
-
<span>{{
|
|
144
|
+
<span>{{ importLabel }}</span>
|
|
139
145
|
<template #prepend>
|
|
140
146
|
<SyIcon
|
|
141
147
|
color="primary"
|
|
@@ -148,10 +154,10 @@
|
|
|
148
154
|
v-if="state === 'success' && showPreviewBtn"
|
|
149
155
|
class="file-item__action file-item__action-preview text-primary"
|
|
150
156
|
variant="text"
|
|
151
|
-
:aria-label="locales.
|
|
157
|
+
:aria-label="`${locales.see} ${fileName}`"
|
|
152
158
|
@click="$emit('preview', itemId)"
|
|
153
159
|
>
|
|
154
|
-
<span>{{
|
|
160
|
+
<span>{{ seeLabel }}</span>
|
|
155
161
|
<template #prepend>
|
|
156
162
|
<SyIcon
|
|
157
163
|
color="primary"
|
|
@@ -164,10 +170,10 @@
|
|
|
164
170
|
v-if="state === 'success' && showDeleteBtn"
|
|
165
171
|
class="file-item__action file-item__action-delete text-error"
|
|
166
172
|
variant="text"
|
|
167
|
-
:aria-label="locales.
|
|
173
|
+
:aria-label="`${locales.delete} ${fileName}`"
|
|
168
174
|
@click="$emit('delete', itemId)"
|
|
169
175
|
>
|
|
170
|
-
<span>{{
|
|
176
|
+
<span>{{ deleteLabel }}</span>
|
|
171
177
|
<template #prepend>
|
|
172
178
|
<SyIcon
|
|
173
179
|
color="error"
|
|
@@ -193,6 +199,7 @@
|
|
|
193
199
|
height="7"
|
|
194
200
|
color="primary"
|
|
195
201
|
rounded="true"
|
|
202
|
+
:aria-label="title ? `Chargement de ${title}` : 'Chargement en cours'"
|
|
196
203
|
/>
|
|
197
204
|
</div>
|
|
198
205
|
</component>
|
|
@@ -1,17 +1,8 @@
|
|
|
1
1
|
export const locales = {
|
|
2
2
|
optionalDocument: 'Document facultatif',
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
importLabel(title: string) {
|
|
7
|
-
return `Importer le fichier ${title}`
|
|
8
|
-
},
|
|
9
|
-
seeLabel(title: string) {
|
|
10
|
-
return `Voir le fichier ${title}`
|
|
11
|
-
},
|
|
12
|
-
deleteLabel(title: string) {
|
|
13
|
-
return `Supprimer le fichier ${title}`
|
|
14
|
-
},
|
|
3
|
+
see: 'Voir le fichier',
|
|
4
|
+
delete: 'Supprimer le fichier',
|
|
5
|
+
import: 'Importer le fichier',
|
|
15
6
|
uploading: 'En cours',
|
|
16
7
|
success: 'Téléchargé',
|
|
17
8
|
error: 'Erreur',
|
|
@@ -21,6 +21,9 @@ import {
|
|
|
21
21
|
<ul>
|
|
22
22
|
<li><strong>Formattage sous forme de liste </strong> : Utilisation de balises HTML sémantiques pour structurer les éléments de la liste de fichiers.</li>
|
|
23
23
|
<li><strong>Boutons</strong> : Utilisation de <code><button></code> pour les actions associées à chaque fichier, avec des étiquettes claires qui reprennent l'action et le nom du fichier.</li>
|
|
24
|
+
<li><strong>Aria-label</strong>: On utilise les méthodes <code>importAriaLabel()</code> pour générer les etiquettes ARIA des champs avec le titre et <code>seeAriaLabel()</code> et <code>deleteAriaLabel()</code> pour les étiquettes ARIA avec le nom du fichier.</li>
|
|
25
|
+
<li><strong>SeeLabel, ImportLabel, DeleteLabel </strong> : Utilisation de ces propriétés pour fournir des étiquettes claires et descriptives pour les actions associées à chaque fichier.</li>
|
|
26
|
+
|
|
24
27
|
</ul>
|
|
25
28
|
</CriteriaCard>
|
|
26
29
|
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
files = files.slice(0, 1)
|
|
75
75
|
}
|
|
76
76
|
const { errors, validFiles } = validateFiles(
|
|
77
|
-
files, props.fileSizeMax, props.allowedExtensions, props.fileSizeUnits,
|
|
77
|
+
files, props.fileSizeMax, props.allowedExtensions, props.fileSizeUnits, props.locales,
|
|
78
78
|
)
|
|
79
79
|
|
|
80
80
|
if (errors.length) {
|
|
@@ -149,6 +149,7 @@
|
|
|
149
149
|
:multiple="multiple"
|
|
150
150
|
:file-size-max="fileSizeMax"
|
|
151
151
|
:file-size-units="fileSizeUnits"
|
|
152
|
+
:locales="locales"
|
|
152
153
|
>
|
|
153
154
|
<template
|
|
154
155
|
v-for="(_, slotName) in $slots"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { calcHumanFileSize } from '@/utils/calcHumanFileSize'
|
|
3
|
-
import { locales } from './locales'
|
|
3
|
+
import { locales as defaultLocales } from './locales'
|
|
4
4
|
import { mdiCloudUpload } from '@mdi/js'
|
|
5
5
|
import { computed } from 'vue'
|
|
6
6
|
import SyIcon from '@/components/Customs/SyIcon/SyIcon.vue'
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
fileSizeUnits: Array<string>
|
|
11
11
|
fileSizeMax: number
|
|
12
12
|
multiple: boolean
|
|
13
|
+
locales: typeof defaultLocales
|
|
13
14
|
}>()
|
|
14
15
|
|
|
15
16
|
export interface FileUploadContentSlots {
|
|
@@ -268,6 +268,53 @@ describe('FileUpload', () => {
|
|
|
268
268
|
expect(wrapper.emitted('error')).toBeFalsy()
|
|
269
269
|
})
|
|
270
270
|
|
|
271
|
+
it('accepts a file whose extension is uppercase (case-insensitive check)', async () => {
|
|
272
|
+
const wrapper = mount(FileUpload, {
|
|
273
|
+
props: {
|
|
274
|
+
modelValue: [],
|
|
275
|
+
allowedExtensions: ['png'],
|
|
276
|
+
},
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
const file: File = new File([''], 'image.PNG', { type: 'image/png' })
|
|
280
|
+
|
|
281
|
+
await wrapper.find('.sy-file-upload').trigger('drop', {
|
|
282
|
+
dataTransfer: { files: [file] },
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
expect(wrapper.emitted('error')).toBeFalsy()
|
|
286
|
+
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([[file]])
|
|
287
|
+
})
|
|
288
|
+
|
|
289
|
+
it('uses custom locales error message when provided', async () => {
|
|
290
|
+
const customLocales = {
|
|
291
|
+
or: 'Ou',
|
|
292
|
+
chooseFile: (multiple: boolean) => multiple ? 'Choisir des fichiers' : 'Choisir un fichier',
|
|
293
|
+
infoText: (max: string, ext: string[]) => `Taille max. : ${max}. Formats : ${ext.join(', ')}`,
|
|
294
|
+
fileSizeUnits: ['o', 'Ko', 'Mo', 'Go', 'To'],
|
|
295
|
+
dropFilesHere: (multiple: boolean) => multiple ? 'Déposer vos fichiers ici' : 'Déposer votre fichier ici',
|
|
296
|
+
errorSize: (fileName: string, max: string) => `Fichier ${fileName} trop lourd. Max : ${max}`,
|
|
297
|
+
errorExtension: () => `Message erreur custom !`,
|
|
298
|
+
fileUploadTitle: '',
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const wrapper = mount(FileUpload, {
|
|
302
|
+
props: {
|
|
303
|
+
modelValue: [],
|
|
304
|
+
allowedExtensions: ['pdf'],
|
|
305
|
+
locales: customLocales,
|
|
306
|
+
},
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
const file: File = new File([''], 'image.PNG', { type: 'image/png' })
|
|
310
|
+
|
|
311
|
+
await wrapper.find('.sy-file-upload').trigger('drop', {
|
|
312
|
+
dataTransfer: { files: [file] },
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
expect(wrapper.emitted('error')?.[0]).toEqual([['Message erreur custom !']])
|
|
316
|
+
})
|
|
317
|
+
|
|
271
318
|
it('add the new files to the existing ones when the input changes in multiple mode', async () => {
|
|
272
319
|
const file1 = new File([''], 'filename1.jpg', { type: 'image/jpeg' })
|
|
273
320
|
const file2 = new File([''], 'filename2.jpg', { type: 'image/jpeg' })
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { calcHumanFileSize } from '@/utils/calcHumanFileSize'
|
|
2
|
-
import { locales } from './locales'
|
|
2
|
+
import { locales as defaultLocales } from './locales'
|
|
3
3
|
|
|
4
4
|
export default function validateFiles(
|
|
5
5
|
files: File[],
|
|
6
6
|
maxFileSize: number,
|
|
7
7
|
allowedExtensions: string[],
|
|
8
8
|
fileSizeUnits: string[],
|
|
9
|
+
locales: typeof defaultLocales = defaultLocales,
|
|
9
10
|
) {
|
|
10
11
|
const errors: string[] = []
|
|
11
12
|
const validFiles: File[] = []
|
|
13
|
+
const normalizedExtensions = allowedExtensions.map(ext => ext.toLowerCase())
|
|
12
14
|
for (const file of files) {
|
|
13
15
|
let isValid = true
|
|
14
16
|
if (file.size > maxFileSize) {
|
|
@@ -18,8 +20,9 @@ export default function validateFiles(
|
|
|
18
20
|
isValid = false
|
|
19
21
|
}
|
|
20
22
|
|
|
23
|
+
const fileExt = (file.name.split('.').pop() || '').toLowerCase()
|
|
21
24
|
if (
|
|
22
|
-
!
|
|
25
|
+
!normalizedExtensions.includes(fileExt)
|
|
23
26
|
&& allowedExtensions.length > 0
|
|
24
27
|
) {
|
|
25
28
|
errors.push(
|
|
@@ -1,15 +1,68 @@
|
|
|
1
|
-
import { Meta,
|
|
1
|
+
import { Meta, Primary } from '@storybook/blocks';
|
|
2
2
|
import * as Stories from '../FranceConnectBtn.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/FranceConnectBtn.xlsx" style={{ color:'#0C41BD' }}>Voir le rapport</a></p>
|
|
15
|
+
<AccessibilityGuideLayout
|
|
16
|
+
componentName="FranceConnectBtn"
|
|
17
|
+
iconSrc={AccessibilityIcon}
|
|
18
|
+
apgHref="https://www.w3.org/WAI/ARIA/apg/patterns/button/"
|
|
19
|
+
>
|
|
20
|
+
<div class="mt-8">
|
|
21
|
+
<p>Rapport d’audit manuel : <a href="/audits/FranceConnectBtn.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/4005" target="_blank" style={{color:'#0C41BD'}}>issue #4005</a>)</p>
|
|
15
23
|
</div>
|
|
24
|
+
|
|
25
|
+
<CriteriaSection>
|
|
26
|
+
<CriteriaCard icon="🔍" title="Structure sémantique et attributs">
|
|
27
|
+
<ul>
|
|
28
|
+
<li><strong>Liens natifs</strong> : Utilisation de balises <code><a></code> pour le bouton principal et le lien d'information, garantissant une sémantique correcte.</li>
|
|
29
|
+
<li><strong>Labels explicites</strong> : Utilisation de l'attribut <code>aria-label</code> sur les liens pour fournir une description claire aux lecteurs d'écran (ex: "S'identifier avec FranceConnect" ou "S'identifier avec FranceConnect+").</li>
|
|
30
|
+
<li><strong>SVG masqué</strong> : Le logo SVG complexe est masqué aux technologies d'assistance avec <code>aria-hidden="true"</code> et <code>role="presentation"</code> car l'information est déjà portée par l'attribut <code>aria-label</code> du lien parent.</li>
|
|
31
|
+
<li><strong>Ouverture de fenêtre</strong> : Le lien externe informe l'utilisateur de l'ouverture d'un nouvel onglet, avec une icône explicitement masquée (<code>decorative=true</code>).</li>
|
|
32
|
+
</ul>
|
|
33
|
+
</CriteriaCard>
|
|
34
|
+
|
|
35
|
+
<CriteriaCard icon="⌨️" title="Navigation et interaction clavier">
|
|
36
|
+
<ul>
|
|
37
|
+
<li><strong>Focus natif</strong> : Les liens sont naturellement accessibles via la touche <kbd>Tab</kbd>.</li>
|
|
38
|
+
<li><strong>Indicateur de focus</strong> : Un style de focus clair, visible et avec un décalage (<code>outline-offset</code>) est implémenté pour garantir une bonne visibilité lors de la navigation au clavier.</li>
|
|
39
|
+
</ul>
|
|
40
|
+
</CriteriaCard>
|
|
41
|
+
|
|
42
|
+
<CriteriaCard icon="🎨" title="Styles et contrastes">
|
|
43
|
+
<ul>
|
|
44
|
+
<li><strong>Couleurs institutionnelles</strong> : Respect strict des couleurs et contrastes de la charte FranceConnect (Bleu France), garantissant un ratio de contraste suffisant.</li>
|
|
45
|
+
<li><strong>Adaptation au thème sombre</strong> : Ajustement des couleurs de fond (ex: <code>#8585f6</code>) et de texte en mode sombre pour maintenir la lisibilité et l'accessibilité visuelle.</li>
|
|
46
|
+
</ul>
|
|
47
|
+
</CriteriaCard>
|
|
48
|
+
</CriteriaSection>
|
|
49
|
+
|
|
50
|
+
<DemoSection componentName="FranceConnectBtn">
|
|
51
|
+
<Primary />
|
|
52
|
+
</DemoSection>
|
|
53
|
+
|
|
54
|
+
<BestPracticesSection>
|
|
55
|
+
<ul>
|
|
56
|
+
<li><strong>Positionnement</strong> : Placez toujours ce bouton dans un contexte de connexion ou d'authentification.</li>
|
|
57
|
+
<li><strong>Respect de la charte</strong> : Ne modifiez pas les proportions, les couleurs (en dehors du mode sombre) ou les libellés de ce bouton, car ils sont soumis aux règles strictes de la direction interministérielle du numérique (DINUM).</li>
|
|
58
|
+
<li>Assurez-vous que le lien <code>href</code> fourni pointe vers la véritable interface de redirection d'authentification.</li>
|
|
59
|
+
</ul>
|
|
60
|
+
</BestPracticesSection>
|
|
61
|
+
|
|
62
|
+
<ResourcesSection>
|
|
63
|
+
<ul>
|
|
64
|
+
<li><a href="https://franceconnect.gouv.fr/partenaires" target="_blank" rel="noopener noreferrer">Documentation et charte FranceConnect</a></li>
|
|
65
|
+
<li><a href="https://accessibilite.numerique.gouv.fr/methode/criteres-et-tests/#6.1" target="_blank" rel="noopener noreferrer">RGAA : Liens et navigation</a></li>
|
|
66
|
+
</ul>
|
|
67
|
+
</ResourcesSection>
|
|
68
|
+
</AccessibilityGuideLayout>
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
to?: RouteLocationRaw
|
|
24
24
|
href?: string
|
|
25
25
|
}
|
|
26
|
-
headingLevelTitle
|
|
26
|
+
headingLevelTitle?: 1 | 2 | 3 | 4 | 5 | 6
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
defineSlots<{
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
serviceSubtitle: undefined,
|
|
59
59
|
homeLink: undefined,
|
|
60
60
|
width: '1712px',
|
|
61
|
+
headingLevelTitle: 1,
|
|
61
62
|
})
|
|
62
63
|
|
|
63
64
|
function registerHeaderMenu(childMenuStatus: DeepReadonly<Ref<boolean>>) {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
to?: RouteLocationRaw
|
|
18
18
|
href?: string
|
|
19
19
|
}
|
|
20
|
-
headingLevelTitle
|
|
20
|
+
headingLevelTitle?: 1 | 2 | 3 | 4 | 5 | 6
|
|
21
21
|
}>(), {
|
|
22
22
|
ariaLabel: locales.ariaLabel,
|
|
23
23
|
serviceTitle: undefined,
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
homeLink: () => ({
|
|
26
26
|
href: '/',
|
|
27
27
|
}),
|
|
28
|
+
headingLevelTitle: 1,
|
|
28
29
|
})
|
|
29
30
|
|
|
30
31
|
defineSlots<{
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
confirmationMessage?: boolean
|
|
42
42
|
/** Largeur interne */
|
|
43
43
|
width?: string
|
|
44
|
-
headingLevelTitle
|
|
44
|
+
headingLevelTitle?: 1 | 2 | 3 | 4 | 5 | 6
|
|
45
45
|
}>(),
|
|
46
46
|
{
|
|
47
47
|
// Confirmation related defaults
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
maxHorizontalMenuItems: 6,
|
|
58
58
|
items: undefined,
|
|
59
59
|
width: '1712px',
|
|
60
|
+
headingLevelTitle: 1,
|
|
60
61
|
})
|
|
61
62
|
|
|
62
63
|
// Définition des événements émis
|
|
@@ -1,10 +1,76 @@
|
|
|
1
|
-
import { Meta,
|
|
2
|
-
import * as
|
|
3
|
-
import '@/
|
|
1
|
+
import { Meta, Primary } from '@storybook/blocks';
|
|
2
|
+
import * as Stories from '../LunarCalendar.stories';
|
|
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={Stories}/>
|
|
6
14
|
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
15
|
+
<AccessibilityGuideLayout
|
|
16
|
+
componentName="LunarCalendar"
|
|
17
|
+
iconSrc={AccessibilityIcon}
|
|
18
|
+
apgHref="https://www.w3.org/WAI/ARIA/apg/patterns/textfield/"
|
|
19
|
+
>
|
|
20
|
+
|
|
21
|
+
<CriteriaSection>
|
|
22
|
+
|
|
23
|
+
<CriteriaCard title="Structure sémantique">
|
|
24
|
+
- **Champ de saisie natif** : Utilise un élément `input` de type texte avec masque de formatage
|
|
25
|
+
- **Label associé** : Le label est correctement associé au champ via le composant SyTextField
|
|
26
|
+
- **Masque de saisie** : Le format `JJ/MM/AAAA` est appliqué via la directive `v-maska`
|
|
27
|
+
- **Icônes décoratives** : Les icônes calendrier sont marquées comme décoratives
|
|
28
|
+
</CriteriaCard>
|
|
29
|
+
|
|
30
|
+
<CriteriaCard title="États et feedback">
|
|
31
|
+
- **Messages d'erreur** : Les erreurs de validation sont annoncées via `aria-describedby`
|
|
32
|
+
- **Messages de succès** : Les confirmations sont également annoncées aux lecteurs d'écran
|
|
33
|
+
- **Champ requis** : L'attribut `required` est correctement appliqué quand nécessaire
|
|
34
|
+
- **Contraintes de dates** : Validation des années min/max avec feedback approprié
|
|
35
|
+
</CriteriaCard>
|
|
36
|
+
|
|
37
|
+
<CriteriaCard title="Navigation au clavier">
|
|
38
|
+
- **Tabulation** : Navigation au clavier standard via le composant SyTextField
|
|
39
|
+
- **Saisie guidée** : Le masque facilite la saisie en indiquant le format attendu
|
|
40
|
+
- **Effacement** : Support du bouton d'effacement quand `isClearable` est activé
|
|
41
|
+
- **Focus visible** : Indication claire du focus pour les utilisateurs clavier
|
|
42
|
+
</CriteriaCard>
|
|
43
|
+
|
|
44
|
+
</CriteriaSection>
|
|
45
|
+
|
|
46
|
+
<DemoSection componentName="LunarCalendar">
|
|
47
|
+
<Primary />
|
|
48
|
+
</DemoSection>
|
|
49
|
+
|
|
50
|
+
## Bonnes pratiques
|
|
51
|
+
|
|
52
|
+
<BestPracticesSection>
|
|
53
|
+
<ul>
|
|
54
|
+
<li><strong>Label descriptif</strong> : Utiliser un label qui explique clairement qu'il s'agit d'une date lunaire et indiquer le format attendu JJ/MM/AAAA.</li>
|
|
55
|
+
<li><strong>Messages clairs</strong> : Fournir des messages d'erreur qui expliquent le format attendu et les contraintes de validité.</li>
|
|
56
|
+
<li><strong>Contraintes pertinentes</strong> : Définir des plages d'années logiques pour le contexte d'utilisation.</li>
|
|
57
|
+
<li><strong>Feedback immédiat</strong> : Valider dès la perte du focus pour guider l'utilisateur dans sa saisie.</li>
|
|
58
|
+
<li><strong>Placeholder utile</strong> : Utiliser JJ/MM/AAAA comme placeholder pour renforcer le format attendu.</li>
|
|
59
|
+
<li><strong>Icônes appropriées</strong> : Les icônes calendrier aident à identifier visuellement le type de saisie attendue.</li>
|
|
60
|
+
<li><strong>Effacement facilité</strong> : Activer isClearable pour permettre aux utilisateurs de corriger facilement leur saisie.</li>
|
|
61
|
+
</ul>
|
|
62
|
+
</BestPracticesSection>
|
|
63
|
+
|
|
64
|
+
## Ressources
|
|
65
|
+
|
|
66
|
+
<ResourcesSection>
|
|
67
|
+
<ul>
|
|
68
|
+
<li><a href="https://www.w3.org/WAI/ARIA/apg/patterns/textfield/" target="_blank" rel="noopener noreferrer">WAI-ARIA Authoring Practices - Text Input</a></li>
|
|
69
|
+
<li><a href="https://developer.mozilla.org/fr/docs/Web/HTML/Element/input" target="_blank" rel="noopener noreferrer">MDN Web Docs - input element</a></li>
|
|
70
|
+
<li><a href="https://developer.mozilla.org/fr/docs/Web/Accessibility/ARIA/Roles/textbox_role" target="_blank" rel="noopener noreferrer">MDN Web Docs - ARIA: textbox role</a></li>
|
|
71
|
+
<li><a href="https://www.numerique.gouv.fr/publications/rgaa-accessibilite/#critere-118-champs-de-saisie" target="_blank" rel="noopener noreferrer">RGAA - Critère 11.8 - Champs de saisie</a></li>
|
|
72
|
+
<li><a href="/docs/components-customs-sytextfield--docs" target="_blank" rel="noopener noreferrer">Documentation SyTextField</a></li>
|
|
73
|
+
</ul>
|
|
74
|
+
</ResourcesSection>
|
|
75
|
+
|
|
76
|
+
</AccessibilityGuideLayout>
|