@cnamts/synapse 1.1.0 → 1.1.1

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 (202) hide show
  1. package/dist/{AutocompleteFilter-DXd4szWO.js → AutocompleteFilter-CGF33skz.js} +1 -1
  2. package/dist/{DateFilter-BD59Kgwf.js → DateFilter-D7-MsKtx.js} +1 -1
  3. package/dist/{NumberFilter-BSMZE7uw.js → NumberFilter-bjQPPfsj.js} +1 -1
  4. package/dist/{PeriodFilter-keUdSSk0.js → PeriodFilter-B3wJpK8-.js} +1 -1
  5. package/dist/{SelectFilter-Dhvvwazl.js → SelectFilter-BN6DbKAV.js} +1 -1
  6. package/dist/{TextFilter-CU8FpXz0.js → TextFilter-BffP0J2f.js} +1 -1
  7. package/dist/{apLightTheme2026-DbS7BPUf.js → apLightTheme2026-C4ygwMHC.js} +11 -11
  8. package/dist/components/Amelipro/AmeliproAutoCompleteField/AmeliproAutoCompleteField.d.ts +6 -6
  9. package/dist/components/Amelipro/AmeliproSelect/AmeliproSelect.d.ts +6 -6
  10. package/dist/components/Amelipro/AmeliproTabs/AmeliproTabs.d.ts +6 -6
  11. package/dist/components/Captcha/Captcha.d.ts +27 -16
  12. package/dist/components/Captcha/CaptchaForm.d.ts +29 -3
  13. package/dist/components/Captcha/types.d.ts +14 -0
  14. package/dist/components/Captcha/useCaptchaValidation.d.ts +37 -0
  15. package/dist/components/Customs/Selects/SelectBtnField/SelectBtnField.d.ts +33 -13
  16. package/dist/components/Customs/Selects/SelectBtnField/composables/useSelectBtnFieldValidation.d.ts +23 -0
  17. package/dist/components/Customs/Selects/SyAutocomplete/composables/useSyAutocompleteValidation.d.ts +2 -2
  18. package/dist/components/Customs/Selects/SySelect/composables/useSySelectValidation.d.ts +2 -2
  19. package/dist/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.d.ts +17 -48
  20. package/dist/components/Customs/SyCheckBoxGroup/composables/useSyCheckBoxGroupValidation.d.ts +29 -0
  21. package/dist/components/Customs/SyCheckBoxGroup/types.d.ts +46 -0
  22. package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +16 -51
  23. package/dist/components/Customs/SyCheckbox/composables/useSyCheckboxValidation.d.ts +27 -0
  24. package/dist/components/Customs/SyCheckbox/types.d.ts +49 -0
  25. package/dist/components/Customs/SyTextField/FieldState.d.ts +5 -0
  26. package/dist/components/Customs/SyTextField/useSyTextFieldValidation.d.ts +3 -3
  27. package/dist/components/DialogBox/DialogBox.d.ts +2 -0
  28. package/dist/components/DialogBox/locales.d.ts +1 -0
  29. package/dist/components/FilterSideBar/FilterSideBar.d.ts +4 -0
  30. package/dist/components/LunarCalendar/LunarCalendar.d.ts +43 -14
  31. package/dist/components/LunarCalendar/types.d.ts +35 -0
  32. package/dist/components/LunarCalendar/useLunarCalendarValidation.d.ts +11 -12
  33. package/dist/components/MonthPicker/MonthPicker.d.ts +72 -1747
  34. package/dist/components/MonthPicker/MonthPickerText/MonthPickerInput.d.ts +21 -1733
  35. package/dist/components/MonthPicker/MonthPickerText/useTextField.d.ts +5 -0
  36. package/dist/components/MonthPicker/locales.d.ts +1 -0
  37. package/dist/components/MonthPicker/types.d.ts +11 -0
  38. package/dist/components/MonthPicker/useMonthPickerValidation.d.ts +37 -24
  39. package/dist/components/NirField/NirField.d.ts +6 -4
  40. package/dist/components/NirField/useNirValidation.d.ts +7 -5
  41. package/dist/components/PageContainer/PageContainer.d.ts +8 -0
  42. package/dist/components/PasswordField/PasswordField.d.ts +2 -2
  43. package/dist/components/PasswordField/usePasswordFieldValidation.d.ts +2 -2
  44. package/dist/components/PhoneField/PhoneField.d.ts +960 -1938
  45. package/dist/components/PhoneField/indicatifs.d.ts +715 -8
  46. package/dist/components/PhoneField/locales.d.ts +7 -0
  47. package/dist/components/PhoneField/types.d.ts +29 -0
  48. package/dist/components/PhoneField/usePhoneFieldValidation.d.ts +45 -0
  49. package/dist/components/PhoneField/usePhoneIndicatifs.d.ts +947 -0
  50. package/dist/components/SyTextArea/composables/useSyTextAreaValidation.d.ts +2 -2
  51. package/dist/composables/unifyValidation/documentationValidationProps.d.ts +1 -1
  52. package/dist/composables/unifyValidation/useValidation.d.ts +4 -5
  53. package/dist/design-system-v3.js +2 -2
  54. package/dist/designTokens/tokens/amelipro/apLightTheme.d.ts +10 -10
  55. package/dist/designTokens/tokens/baseTokens.d.ts +18 -18
  56. package/dist/designTokens/tokens/cnam/cnamLightTheme.d.ts +10 -10
  57. package/dist/designTokens/tokens/pa/paLightTheme.d.ts +10 -10
  58. package/dist/designTokens/tokens/semanticTokens.d.ts +14 -14
  59. package/dist/{main-D8ryUoS5.js → main-C4wAktOs.js} +13718 -12991
  60. package/dist/synapse.css +1 -1
  61. package/dist/vuetifyConfig.js +1 -1
  62. package/package.json +7 -7
  63. package/src/assets/compat/_legacy-tokens.scss +91 -0
  64. package/src/assets/overrides/_utilities.scss +23 -0
  65. package/src/components/Accordion/Accordion.stories.ts +121 -1
  66. package/src/components/BackBtn/BackBtn.mdx +1 -1
  67. package/src/components/BackToTopBtn/BackToTopBtn.mdx +0 -1
  68. package/src/components/Captcha/Captcha.stories.ts +134 -31
  69. package/src/components/Captcha/Captcha.vue +95 -28
  70. package/src/components/Captcha/CaptchaForm.vue +51 -22
  71. package/src/components/Captcha/tests/Captcha.focus.spec.ts +214 -0
  72. package/src/components/Captcha/tests/Captcha.spec.ts +233 -24
  73. package/src/components/Captcha/tests/CaptchaForm.spec.ts +82 -0
  74. package/src/components/Captcha/tests/__snapshots__/Captcha.spec.ts.snap +16 -42
  75. package/src/components/Captcha/types.ts +15 -0
  76. package/src/components/Captcha/useCaptchaValidation.ts +87 -0
  77. package/src/components/Captcha/validation/validation.stories.ts +1194 -0
  78. package/src/components/ChipList/ChipList.mdx +0 -1
  79. package/src/components/CollapsibleList/CollapsibleList.mdx +0 -1
  80. package/src/components/CookieBanner/CookieBanner.mdx +0 -1
  81. package/src/components/CopyBtn/CopyBtn.mdx +0 -1
  82. package/src/components/Customs/Selects/SelectBtnField/SelectBtnField.stories.ts +123 -439
  83. package/src/components/Customs/Selects/SelectBtnField/SelectBtnField.vue +147 -41
  84. package/src/components/Customs/Selects/SelectBtnField/Validation/Validation.stories.ts +600 -0
  85. package/src/components/Customs/Selects/SelectBtnField/composables/useSelectBtnFieldValidation.ts +87 -0
  86. package/src/components/Customs/Selects/SelectBtnField/tests/SelectBtnField.spec.ts +402 -33
  87. package/src/components/Customs/Selects/SelectBtnField/tests/__snapshots__/SelectBtnField.spec.ts.snap +52 -38
  88. package/src/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.stories.ts +342 -162
  89. package/src/components/Customs/SyCheckBoxGroup/SyCheckBoxGroup.vue +77 -129
  90. package/src/components/Customs/SyCheckBoxGroup/Validation/Validation.stories.ts +1008 -0
  91. package/src/components/Customs/SyCheckBoxGroup/composables/useSyCheckBoxGroupValidation.ts +107 -0
  92. package/src/components/Customs/SyCheckBoxGroup/tests/SyCheckBoxGroup.spec.ts +180 -7
  93. package/src/components/Customs/SyCheckBoxGroup/types.ts +49 -0
  94. package/src/components/Customs/SyCheckbox/SyCheckbox.stories.ts +41 -161
  95. package/src/components/Customs/SyCheckbox/SyCheckbox.vue +71 -148
  96. package/src/components/Customs/SyCheckbox/Validation/Validation.stories.ts +654 -0
  97. package/src/components/Customs/SyCheckbox/composables/useSyCheckboxValidation.ts +105 -0
  98. package/src/components/Customs/SyCheckbox/tests/SyCheckbox.spec.ts +106 -0
  99. package/src/components/Customs/SyCheckbox/tests/useSyCheckboxValidation.spec.ts +98 -0
  100. package/src/components/Customs/SyCheckbox/types.ts +51 -0
  101. package/src/components/Customs/SyTextField/FieldState.vue +50 -0
  102. package/src/components/Customs/SyTextField/SyTextField.vue +12 -9
  103. package/src/components/Customs/SyTextField/useSyTextFieldValidation.ts +2 -11
  104. package/src/components/DataList/DataList.mdx +0 -1
  105. package/src/components/DataListGroup/DataListGroup.mdx +0 -1
  106. package/src/components/DiacriticPicker/DiacriticPicker.mdx +0 -1
  107. package/src/components/DialogBox/DialogBox.mdx +0 -1
  108. package/src/components/DialogBox/DialogBox.stories.ts +399 -4
  109. package/src/components/DialogBox/DialogBox.vue +20 -0
  110. package/src/components/DialogBox/locales.ts +1 -0
  111. package/src/components/DialogBox/tests/DialogBox.spec.ts +73 -0
  112. package/src/components/DialogBox/tests/DialogBox.visual.cy.ts +24 -0
  113. package/src/components/ErrorPage/ErrorPage.mdx +1 -1
  114. package/src/components/ExternalLinks/ExternalLinks.mdx +0 -1
  115. package/src/components/FileList/FileList.mdx +0 -1
  116. package/src/components/FilterInline/FilterInline.mdx +0 -1
  117. package/src/components/FilterSideBar/FilterSideBar.mdx +8 -1
  118. package/src/components/FilterSideBar/FilterSideBar.stories.ts +133 -1
  119. package/src/components/FilterSideBar/FilterSideBar.vue +19 -2
  120. package/src/components/FilterSideBar/tests/FilterSideBar.spec.ts +55 -0
  121. package/src/components/FooterBar/FooterBar.mdx +0 -1
  122. package/src/components/FranceConnectBtn/FranceConnectBtn.mdx +0 -1
  123. package/src/components/HeaderBar/HeaderBar.mdx +0 -1
  124. package/src/components/HeaderLoading/HeaderLoading.mdx +0 -1
  125. package/src/components/LangBtn/LangBtn.mdx +0 -1
  126. package/src/components/Logo/Logo.mdx +1 -1
  127. package/src/components/LunarCalendar/LunarCalendar.mdx +6 -9
  128. package/src/components/LunarCalendar/LunarCalendar.stories.ts +243 -46
  129. package/src/components/LunarCalendar/LunarCalendar.vue +61 -26
  130. package/src/components/LunarCalendar/Validation/Validation.stories.ts +717 -0
  131. package/src/components/LunarCalendar/tests/LunarCalendar.a11y.spec.ts +1 -1
  132. package/src/components/LunarCalendar/tests/LunarCalendar.spec.ts +197 -6
  133. package/src/components/LunarCalendar/tests/useLunarCalendarValidation.spec.ts +287 -0
  134. package/src/components/LunarCalendar/types.ts +39 -0
  135. package/src/components/LunarCalendar/useLunarCalendarValidation.ts +115 -39
  136. package/src/components/MonthPicker/MonthPicker.stories.ts +38 -281
  137. package/src/components/MonthPicker/MonthPicker.vue +66 -17
  138. package/src/components/MonthPicker/MonthPickerText/MonthPickerInput.vue +44 -20
  139. package/src/components/MonthPicker/MonthPickerText/useTextField.ts +5 -0
  140. package/src/components/MonthPicker/Validation/Validation.stories.ts +1117 -0
  141. package/src/components/MonthPicker/locales.ts +1 -0
  142. package/src/components/MonthPicker/tests/MonthPicker.spec.ts +353 -2
  143. package/src/components/MonthPicker/tests/__snapshots__/MonthPicker.spec.ts.snap +12 -8
  144. package/src/components/MonthPicker/types.ts +16 -0
  145. package/src/components/MonthPicker/useMonthPickerValidation.ts +64 -27
  146. package/src/components/NirField/NirField.mdx +120 -66
  147. package/src/components/NirField/NirField.stories.ts +216 -0
  148. package/src/components/NirField/useNirValidation.ts +16 -17
  149. package/src/components/NotFoundPage/tests/__snapshots__/NotFoundPage.spec.ts.snap +263 -245
  150. package/src/components/NotificationBar/NotificationBar.mdx +0 -1
  151. package/src/components/PageContainer/PageContainer.mdx +0 -1
  152. package/src/components/PageContainer/PageContainer.stories.ts +170 -2
  153. package/src/components/PageContainer/PageContainer.vue +63 -8
  154. package/src/components/PageContainer/tests/__snapshots__/PageContainer.spec.ts.snap +19 -11
  155. package/src/components/PaginatedTable/PaginatedTable.mdx +0 -1
  156. package/src/components/PeriodField/PeriodField.mdx +0 -1
  157. package/src/components/PhoneField/PhoneField.mdx +2 -3
  158. package/src/components/PhoneField/PhoneField.stories.ts +227 -410
  159. package/src/components/PhoneField/PhoneField.vue +204 -438
  160. package/src/components/PhoneField/indicatifs.ts +1 -1
  161. package/src/components/PhoneField/locales.ts +7 -0
  162. package/src/components/PhoneField/tests/PhoneField.a11y.spec.ts +0 -1
  163. package/src/components/PhoneField/tests/PhoneField.spec.ts +517 -220
  164. package/src/components/PhoneField/types.ts +30 -0
  165. package/src/components/PhoneField/usePhoneFieldValidation.ts +119 -0
  166. package/src/components/PhoneField/usePhoneIndicatifs.ts +89 -0
  167. package/src/components/PhoneField/validation/validation.stories.ts +717 -0
  168. package/src/components/RangeField/RangeField.mdx +0 -1
  169. package/src/components/RatingPicker/RatingPicker.mdx +0 -1
  170. package/src/components/SocialMediaLinks/SocialMediaLinks.mdx +0 -1
  171. package/src/components/StatusPage/StatusPage.vue +1 -0
  172. package/src/components/StatusPage/tests/__snapshots__/StatusPage.spec.ts.snap +248 -230
  173. package/src/components/SubHeader/SubHeader.mdx +5 -6
  174. package/src/components/Tables/common/tests/SyTableFilter.spec.ts +11 -12
  175. package/src/components/UploadWorkflow/UploadWorkflow.mdx +0 -1
  176. package/src/components/UserMenuBtn/UserMenuBtn.mdx +0 -1
  177. package/src/components/UserMenuBtn/UserMenuBtn.stories.ts +177 -0
  178. package/src/composables/unifyValidation/documentationValidationProps.ts +1 -1
  179. package/src/composables/unifyValidation/tests/useValidation.spec.ts +13 -1
  180. package/src/composables/unifyValidation/useValidation.ts +37 -33
  181. package/src/composantsVuetify/VCard/VCard.mdx +4 -0
  182. package/src/composantsVuetify/VCard/v-card.stories.ts +93 -1
  183. package/src/composantsVuetify/VCarousel/VCarousel.mdx +74 -0
  184. package/src/composantsVuetify/VCarousel/v-carousel.stories.ts +531 -0
  185. package/src/composantsVuetify/VNavigationDrawer/VNavgationDrawer.mdx +53 -0
  186. package/src/composantsVuetify/VNavigationDrawer/v-navigation-drawer.stories.ts +310 -0
  187. package/src/composantsVuetify/VSlideGroup/VSlideGroup.mdx +105 -0
  188. package/src/composantsVuetify/VSlideGroup/v-slide-group.stories.ts +463 -0
  189. package/src/designTokens/tokens/baseColors.ts +1 -1
  190. package/src/designTokens/tokens/baseTokens.ts +18 -18
  191. package/src/stories/Components/Components.stories.ts +34 -1
  192. package/src/stories/Demarrer/Releases.stories.ts +16 -2
  193. package/src/stories/DesignTokens/Arrondis.mdx +1 -1
  194. package/src/stories/DesignTokens/Correspondances.mdx +219 -0
  195. package/src/stories/DesignTokens/UtiliserLesTokens.mdx +235 -0
  196. package/src/stories/DesignTokens/colors.stories.ts +569 -569
  197. package/src/stories/GuideDuDev/Amelipro.stories.ts +335 -267
  198. package/dist/components/LunarCalendar/useLunarCalendarRules.d.ts +0 -5
  199. package/dist/components/PhoneField/tests/types.d.ts +0 -18
  200. package/src/components/LunarCalendar/tests/useLunarCalendarRules.spec.ts +0 -184
  201. package/src/components/LunarCalendar/useLunarCalendarRules.ts +0 -96
  202. package/src/components/PhoneField/tests/types.d.ts +0 -19
@@ -2,7 +2,7 @@ import { type Meta, type StoryObj } from '@storybook/vue3'
2
2
  import { VBtn } from 'vuetify/components'
3
3
  import DialogBox from './DialogBox.vue'
4
4
  import { fn } from '@storybook/test'
5
- import { computed } from 'vue'
5
+ import { computed, ref } from 'vue'
6
6
 
7
7
  const meta: Meta<typeof DialogBox> = {
8
8
  title: 'Composants/Feedback/DialogBox',
@@ -199,6 +199,18 @@ const meta: Meta<typeof DialogBox> = {
199
199
  category: 'events',
200
200
  },
201
201
  },
202
+ 'scrollable': {
203
+ control: 'boolean',
204
+ description: 'Rendre le contenu de la boîte de dialogue scrollable',
205
+ table: {
206
+ type: {
207
+ summary: 'boolean',
208
+ },
209
+ defaultValue: {
210
+ summary: 'false',
211
+ },
212
+ },
213
+ },
202
214
  },
203
215
  } satisfies Meta<typeof DialogBox>
204
216
 
@@ -609,9 +621,6 @@ export const TitleSlot: Story = {
609
621
  }
610
622
  },
611
623
  parameters: {
612
- a11y: {
613
- disable: true,
614
- },
615
624
  sourceCode: [
616
625
  {
617
626
  name: 'Template',
@@ -839,6 +848,101 @@ export const VuetifyOptions: Story = {
839
848
  },
840
849
  }
841
850
 
851
+ export const Scrollable: Story = {
852
+ parameters: {
853
+ sourceCode: [
854
+ {
855
+ name: 'Template',
856
+ code: `
857
+ <template>
858
+ <VBtn
859
+ color="primary"
860
+ @click="dialogOpen = !dialogOpen"
861
+ >
862
+ Ouvrir la DialogBox scrollable
863
+ </VBtn>
864
+
865
+ <DialogBox
866
+ v-model="dialogOpen"
867
+ title="DialogBox scrollable"
868
+ scrollable
869
+ width="600px"
870
+ @confirm="dialogOpen = false"
871
+ @cancel="dialogOpen = false"
872
+ >
873
+ <p
874
+ v-for="index in 20"
875
+ :key="index"
876
+ class="mb-4"
877
+ >
878
+ Ligne de contenu numéro {{ index }}.
879
+ Ce contenu permet de vérifier que seule la zone centrale
880
+ de la boîte de dialogue est scrollable, tandis que les boutons
881
+ d’action restent visibles en bas.
882
+ </p>
883
+ </DialogBox>
884
+ </template>
885
+ `,
886
+ },
887
+ {
888
+ name: 'Script',
889
+ code: `
890
+ <script setup lang="ts">
891
+ import { DialogBox } from '@cnamts/synapse'
892
+ import { ref } from 'vue'
893
+
894
+ const dialogOpen = ref(false)
895
+ </script>
896
+ `,
897
+ },
898
+ ],
899
+ },
900
+ args: {
901
+ 'headingLevel': 2,
902
+ 'modelValue': false,
903
+ 'title': 'DialogBox scrollable',
904
+ 'scrollable': true,
905
+ 'width': '600px',
906
+ 'onCancel': fn(),
907
+ 'onConfirm': fn(),
908
+ 'onUpdate:modelValue': fn(),
909
+ },
910
+ render: args => ({
911
+ components: { DialogBox, VBtn },
912
+ setup() {
913
+ return { args }
914
+ },
915
+ template: `
916
+ <div class="pa-4">
917
+ <VBtn
918
+ color="primary"
919
+ @click="args.modelValue = !args.modelValue"
920
+ >
921
+ Ouvrir la DialogBox scrollable
922
+ </VBtn>
923
+
924
+ <DialogBox
925
+ v-bind="args"
926
+ @update:modelValue="args.modelValue = $event"
927
+ @confirm="args.modelValue = false"
928
+ @cancel="args.modelValue = false"
929
+ >
930
+ <p
931
+ v-for="index in 20"
932
+ :key="index"
933
+ class="mb-4"
934
+ >
935
+ Ligne de contenu numéro {{ index }}.
936
+ Ce contenu permet de vérifier que seule la zone centrale
937
+ de la boîte de dialogue est scrollable, tandis que les boutons
938
+ d’action restent visibles en bas.
939
+ </p>
940
+ </DialogBox>
941
+ </div>
942
+ `,
943
+ }),
944
+ }
945
+
842
946
  export const Draggable: Story = {
843
947
  args: {
844
948
  'headingLevel': 2,
@@ -910,3 +1014,294 @@ export const Draggable: Story = {
910
1014
  ],
911
1015
  },
912
1016
  }
1017
+
1018
+ export const Tutoriel: Story = {
1019
+ args: {
1020
+ 'headingLevel': 2,
1021
+ 'modelValue': false,
1022
+ 'title': 'Tutoriel',
1023
+ 'hideActions': true,
1024
+ 'width': '800px',
1025
+ 'onCancel': fn(),
1026
+ 'onConfirm': fn(),
1027
+ 'onUpdate:modelValue': fn(),
1028
+ },
1029
+ render: (args) => {
1030
+ return {
1031
+ components: { DialogBox, VBtn },
1032
+ setup() {
1033
+ const dialogOpen = ref(false)
1034
+ const currentStep = ref(0)
1035
+ const steps = [
1036
+ {
1037
+ title: 'Étape 1 : Bienvenue',
1038
+ content: 'Dans cet espace, vous allez pouvoir découvrir les fonctionnalités principales de l\'application. Suivez ce tutoriel pour apprendre à utiliser tous les outils disponibles.',
1039
+ img: 'https://picsum.photos/400/300?random=1',
1040
+ },
1041
+ {
1042
+ title: 'Étape 2 : Navigation',
1043
+ content: 'Utilisez le menu de navigation pour accéder aux différentes sections. Vous pouvez également utiliser les raccourcis clavier pour une navigation plus rapide.',
1044
+ img: 'https://picsum.photos/400/300?random=2',
1045
+ },
1046
+ {
1047
+ title: 'Étape 3 : Terminé',
1048
+ content: 'Vous êtes maintenant prêt à utiliser l\'application ! N\'hésitez pas à consulter la documentation pour plus d\'informations.',
1049
+ img: 'https://picsum.photos/400/300?random=3',
1050
+ },
1051
+ ]
1052
+
1053
+ const handleNextOrFinish = () => {
1054
+ if (currentStep.value < steps.length - 1) {
1055
+ currentStep.value++
1056
+ }
1057
+ else {
1058
+ args.onConfirm?.()
1059
+ closeDialog()
1060
+ }
1061
+ }
1062
+
1063
+ const closeDialog = () => {
1064
+ dialogOpen.value = false
1065
+ setTimeout(() => {
1066
+ currentStep.value = 0
1067
+ }, 300)
1068
+ }
1069
+
1070
+ const skipTutorial = () => {
1071
+ args.onCancel?.()
1072
+ closeDialog()
1073
+ }
1074
+
1075
+ const handleUpdateModelValue = (value: boolean) => {
1076
+ dialogOpen.value = value
1077
+ args['onUpdate:modelValue']?.(value)
1078
+ }
1079
+
1080
+ const rest = computed(() => {
1081
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1082
+ const { modelValue, 'onUpdate:modelValue': _, 'onCancel': __, 'onConfirm': ___, ...rest } = args
1083
+ return rest
1084
+ })
1085
+
1086
+ return { args, rest, dialogOpen, currentStep, steps, handleNextOrFinish, skipTutorial, handleUpdateModelValue }
1087
+ },
1088
+ template: `
1089
+ <div class="pa-4">
1090
+ <VBtn
1091
+ @click="dialogOpen = !dialogOpen"
1092
+ color="primary"
1093
+ >Ouvrir le tutoriel</VBtn>
1094
+
1095
+ <DialogBox
1096
+ v-bind="rest"
1097
+ v-model="dialogOpen"
1098
+ @update:modelValue="handleUpdateModelValue"
1099
+ >
1100
+ <div class="d-flex flex-column">
1101
+ <!-- Image -->
1102
+ <img
1103
+ :src="steps[currentStep].img"
1104
+ :alt="steps[currentStep].title"
1105
+ class="mb-4 mx-auto"
1106
+ style="max-width: 100%; height: auto; max-height: 300px;"
1107
+ >
1108
+
1109
+ <!-- Title -->
1110
+ <h3 class="text-h5 font-weight-bold mb-4">
1111
+ {{ steps[currentStep].title }}
1112
+ </h3>
1113
+
1114
+ <!-- Content -->
1115
+ <p class="mb-6">
1116
+ {{ steps[currentStep].content }}
1117
+ </p>
1118
+
1119
+ <!-- Actions -->
1120
+ <div
1121
+ class="align-center mt-auto"
1122
+ style="display: grid; grid-template-columns: 1fr auto 1fr;"
1123
+ >
1124
+ <VBtn
1125
+ variant="text"
1126
+ color="primary"
1127
+ style="justify-self: start;"
1128
+ @click="skipTutorial"
1129
+ >
1130
+ Passer
1131
+ </VBtn>
1132
+
1133
+ <!-- Progress dots -->
1134
+ <div class="d-flex align-center justify-center">
1135
+ <span
1136
+ v-for="(step, index) in steps"
1137
+ :key="index"
1138
+ class="mx-1"
1139
+ role="button"
1140
+ :aria-label="'Aller à l\\'étape ' + (index + 1)"
1141
+ :aria-current="currentStep === index"
1142
+ @click="currentStep = index"
1143
+ :style="{
1144
+ width: '14px',
1145
+ height: '14px',
1146
+ borderRadius: '50%',
1147
+ border: '2px solid rgb(var(--v-theme-primary))',
1148
+ backgroundColor: currentStep === index ? 'rgb(var(--v-theme-primary))' : 'rgb(var(--v-theme-surface))',
1149
+ cursor: 'pointer'
1150
+ }"
1151
+ />
1152
+ <span class="ml-2">{{ currentStep + 1 }}/{{ steps.length }}</span>
1153
+ </div>
1154
+
1155
+ <VBtn
1156
+ color="primary"
1157
+ style="justify-self: end;"
1158
+ @click="handleNextOrFinish"
1159
+ >
1160
+ {{ currentStep < steps.length - 1 ? 'Suivant' : 'Commencer' }}
1161
+ </VBtn>
1162
+ </div>
1163
+ </div>
1164
+ </DialogBox>
1165
+ </div>
1166
+ `,
1167
+ }
1168
+ },
1169
+ parameters: {
1170
+ sourceCode: [
1171
+ {
1172
+ name: 'Template',
1173
+ code: `<template>
1174
+ <VBtn
1175
+ color="primary"
1176
+ @click="dialogOpen = !dialogOpen"
1177
+ >
1178
+ Ouvrir le tutoriel
1179
+ </VBtn>
1180
+
1181
+ <DialogBox
1182
+ v-model="dialogOpen"
1183
+ title="Tutoriel"
1184
+ hide-actions
1185
+ width="800px"
1186
+ >
1187
+ <div class="d-flex flex-column">
1188
+ <!-- Image -->
1189
+ <img
1190
+ :src="steps[currentStep].img"
1191
+ :alt="steps[currentStep].title"
1192
+ class="mb-4 mx-auto"
1193
+ style="max-width: 100%; height: auto; max-height: 300px;"
1194
+ >
1195
+
1196
+ <!-- Title -->
1197
+ <h3 class="text-h5 font-weight-bold mb-4">
1198
+ {{ steps[currentStep].title }}
1199
+ </h3>
1200
+
1201
+ <!-- Content -->
1202
+ <p class="mb-6">
1203
+ {{ steps[currentStep].content }}
1204
+ </p>
1205
+
1206
+ <!-- Actions -->
1207
+ <div
1208
+ class="align-center mt-auto"
1209
+ style="display: grid; grid-template-columns: 1fr auto 1fr;"
1210
+ >
1211
+ <VBtn
1212
+ variant="text"
1213
+ color="primary"
1214
+ style="justify-self: start;"
1215
+ @click="skipTutorial"
1216
+ >
1217
+ Passer
1218
+ </VBtn>
1219
+
1220
+ <!-- Progress dots -->
1221
+ <div class="d-flex align-center justify-center">
1222
+ <span
1223
+ v-for="(step, index) in steps"
1224
+ :key="index"
1225
+ class="mx-1"
1226
+ role="button"
1227
+ :aria-label="'Aller à l\\'étape ' + (index + 1)"
1228
+ :aria-current="currentStep === index"
1229
+ @click="currentStep = index"
1230
+ :style="{
1231
+ width: '14px',
1232
+ height: '14px',
1233
+ borderRadius: '50%',
1234
+ border: '2px solid rgb(var(--v-theme-primary))',
1235
+ backgroundColor: currentStep === index ? 'rgb(var(--v-theme-primary))' : 'rgb(var(--v-theme-surface))',
1236
+ cursor: 'pointer'
1237
+ }"
1238
+ />
1239
+ <span class="ml-2">{{ currentStep + 1 }}/{{ steps.length }}</span>
1240
+ </div>
1241
+
1242
+ <VBtn
1243
+ color="primary"
1244
+ style="justify-self: end;"
1245
+ @click="handleNextOrFinish"
1246
+ >
1247
+ {{ currentStep < steps.length - 1 ? 'Suivant' : 'Commencer' }}
1248
+ </VBtn>
1249
+ </div>
1250
+ </div>
1251
+ </DialogBox>
1252
+ </template>
1253
+ `,
1254
+ },
1255
+ {
1256
+ name: 'Script',
1257
+ code: `<script setup lang="ts">
1258
+ import { DialogBox } from '@cnamts/synapse'
1259
+ import { VBtn } from 'vuetify/components'
1260
+ import { ref, computed } from 'vue'
1261
+
1262
+ const dialogOpen = ref(false)
1263
+ const currentStep = ref(0)
1264
+
1265
+ const steps = [
1266
+ {
1267
+ title: 'Étape 1 : Bienvenue',
1268
+ content: 'Dans cet espace, vous allez pouvoir découvrir les fonctionnalités principales de l\\'application. Suivez ce tutoriel pour apprendre à utiliser tous les outils disponibles.',
1269
+ img: 'https://picsum.photos/400/300?random=1',
1270
+ },
1271
+ {
1272
+ title: 'Étape 2 : Navigation',
1273
+ content: 'Utilisez le menu de navigation pour accéder aux différentes sections. Vous pouvez également utiliser les raccourcis clavier pour une navigation plus rapide.',
1274
+ img: 'https://picsum.photos/400/300?random=2',
1275
+ },
1276
+ {
1277
+ title: 'Étape 3 : Terminé',
1278
+ content: 'Vous êtes maintenant prêt à utiliser l\\'application ! N\\'hésitez pas à consulter la documentation pour plus d\\'informations.',
1279
+ img: 'https://picsum.photos/400/300?random=3',
1280
+ },
1281
+ ]
1282
+
1283
+ const handleNextOrFinish = () => {
1284
+ if (currentStep.value < steps.length - 1) {
1285
+ currentStep.value++
1286
+ }
1287
+ else {
1288
+ closeDialog()
1289
+ }
1290
+ }
1291
+
1292
+ const closeDialog = () => {
1293
+ dialogOpen.value = false
1294
+ setTimeout(() => {
1295
+ currentStep.value = 0
1296
+ }, 300)
1297
+ }
1298
+
1299
+ const skipTutorial = () => {
1300
+ closeDialog()
1301
+ }
1302
+ </script>
1303
+ `,
1304
+ },
1305
+ ],
1306
+ },
1307
+ }
@@ -20,6 +20,7 @@
20
20
  autofocusValidateBtn?: boolean
21
21
  draggable?: boolean
22
22
  headingLevel?: 1 | 2 | 3 | 4 | 5 | 6
23
+ scrollable?: boolean
23
24
  } & CustomizableOptions>(), {
24
25
  title: undefined,
25
26
  width: '800px',
@@ -29,6 +30,7 @@
29
30
  persistent: false,
30
31
  autofocusValidateBtn: false,
31
32
  headingLevel: 2,
33
+ scrollable: false,
32
34
  })
33
35
 
34
36
  defineEmits(['cancel', 'confirm', 'update:modelValue'])
@@ -139,6 +141,7 @@
139
141
  :class="{
140
142
  'sy-dialog-box-draggable': props.draggable,
141
143
  'sy-dialog-box-draggable--active': props.draggable && isGrabbing,
144
+ 'sy-dialog-box--scrollable': props.scrollable,
142
145
  }"
143
146
  :aria-label="props.draggable ? locales.draggable : undefined"
144
147
  >
@@ -187,6 +190,10 @@
187
190
 
188
191
  <div
189
192
  class="px-6"
193
+ :class="{ 'sy-dialog-box-content--scrollable': props.scrollable }"
194
+ :tabindex="props.scrollable ? 0 : undefined"
195
+ :role="props.scrollable ? 'region' : undefined"
196
+ :aria-label="props.scrollable ? (props.title || locales.scrollableContent) : undefined"
190
197
  v-bind="options.cardText"
191
198
  >
192
199
  <slot />
@@ -250,6 +257,7 @@
250
257
 
251
258
  .sy-dialog-box-title {
252
259
  line-height: normal;
260
+ flex-shrink: 0;
253
261
  }
254
262
 
255
263
  .v-btn--icon {
@@ -284,6 +292,7 @@ h2 {
284
292
  flex-direction: column;
285
293
  justify-content: stretch;
286
294
  gap: 16px;
295
+ flex-shrink: 0;
287
296
  }
288
297
 
289
298
  .sy-dialog-box-draggable .sy-dialog-box-title {
@@ -301,6 +310,17 @@ h2 {
301
310
  user-select: none;
302
311
  }
303
312
 
313
+ .sy-dialog-box--scrollable {
314
+ display: flex;
315
+ flex-direction: column;
316
+ max-height: calc(100vh - 48px);
317
+ }
318
+
319
+ .sy-dialog-box-content--scrollable {
320
+ overflow-y: auto;
321
+ min-height: 0;
322
+ }
323
+
304
324
  @media screen and (width >= 600px) {
305
325
  .sy-dialog-box-actions-ctn {
306
326
  flex-direction: row;
@@ -5,4 +5,5 @@ export const locales = {
5
5
  draggable: 'Déplaçable',
6
6
  dragInstruction: 'Déplacer la boîte de dialogue',
7
7
  dragInstructionLabel: 'Déplacer la boîte de dialogue avec les flèches directionnelles',
8
+ scrollableContent: 'Contenu de la boîte de dialogue',
8
9
  }
@@ -5,6 +5,7 @@ import { describe, expect, it } from 'vitest'
5
5
  import { defineComponent } from 'vue'
6
6
  import { VCard } from 'vuetify/components'
7
7
  import DialogBox from '../DialogBox.vue'
8
+ import { locales } from '../locales'
8
9
 
9
10
  const defaultProps = {
10
11
  modelValue: true,
@@ -642,4 +643,76 @@ describe('DialogBox', () => {
642
643
 
643
644
  wrapper.unmount()
644
645
  })
646
+
647
+ it('adds scrollable classes when scrollable prop is true', () => {
648
+ const wrapper = mount(DialogBox, {
649
+ props: {
650
+ ...defaultProps,
651
+ scrollable: true,
652
+ headingLevel: 2,
653
+ },
654
+ attachTo: document.body,
655
+ })
656
+
657
+ const card = wrapper.getComponent(VCard)
658
+
659
+ expect(card.classes()).toContain('sy-dialog-box--scrollable')
660
+ expect(card.find('.sy-dialog-box-content--scrollable').exists()).toBe(true)
661
+
662
+ wrapper.unmount()
663
+ })
664
+
665
+ it('does not add scrollable classes when scrollable prop is false', () => {
666
+ const wrapper = mount(DialogBox, {
667
+ props: {
668
+ ...defaultProps,
669
+ scrollable: false,
670
+ headingLevel: 2,
671
+ },
672
+ attachTo: document.body,
673
+ })
674
+
675
+ const card = wrapper.getComponent(VCard)
676
+
677
+ expect(card.classes()).not.toContain('sy-dialog-box--scrollable')
678
+ expect(card.find('.sy-dialog-box-content--scrollable').exists()).toBe(false)
679
+
680
+ wrapper.unmount()
681
+ })
682
+
683
+ it('exposes the scrollable content as a keyboard-focusable, named region', () => {
684
+ const wrapper = mount(DialogBox, {
685
+ props: {
686
+ ...defaultProps,
687
+ scrollable: true,
688
+ },
689
+ attachTo: document.body,
690
+ })
691
+
692
+ const region = wrapper.getComponent(VCard).find('.sy-dialog-box-content--scrollable')
693
+ expect(region.attributes('role')).toBe('region')
694
+ expect(region.attributes('tabindex')).toBe('0')
695
+ // Nommée par le titre quand il est fourni
696
+ expect(region.attributes('aria-label')).toBe('Test title')
697
+
698
+ wrapper.unmount()
699
+ })
700
+
701
+ it('names the scrollable region with a default label when no title is provided', () => {
702
+ const wrapper = mount(DialogBox, {
703
+ props: {
704
+ ...defaultProps,
705
+ title: undefined,
706
+ scrollable: true,
707
+ },
708
+ attachTo: document.body,
709
+ })
710
+
711
+ const region = wrapper.getComponent(VCard).find('.sy-dialog-box-content--scrollable')
712
+ // Une région doit toujours avoir un nom accessible (repli sur la locale)
713
+ expect(region.attributes('aria-label')).toBe(locales.scrollableContent)
714
+ expect(region.attributes('aria-label')).toBeTruthy()
715
+
716
+ wrapper.unmount()
717
+ })
645
718
  })
@@ -73,4 +73,28 @@ describe('DialogBox - Visual regression tests', () => {
73
73
  waitForDialogTransitionEnd()
74
74
  cy.matchImageSnapshot('dialog-box-custom-texts')
75
75
  })
76
+
77
+ it('displays the scrollable dialog box', () => {
78
+ cy.mountWithVuetify(DialogBox, {
79
+ ...dialogTransitionOptions,
80
+ props: {
81
+ 'modelValue': true,
82
+ 'title': 'Dialog scrollable',
83
+ 'scrollable': true,
84
+ 'onUpdate:modelValue': () => {},
85
+ },
86
+ slots: {
87
+ default: () => h(
88
+ 'div',
89
+ Array.from({ length: 20 }, (_, index) =>
90
+ h('p', { class: 'mb-4' }, `Ligne de contenu numéro ${index + 1}`),
91
+ ),
92
+ ),
93
+ },
94
+ })
95
+
96
+ cy.get('.v-dialog').should('be.visible')
97
+ waitForDialogTransitionEnd()
98
+ cy.matchImageSnapshot('dialog-box-scrollable')
99
+ })
76
100
  })
@@ -1,5 +1,5 @@
1
1
  import { Controls, Canvas, Meta, Source } from "@storybook/blocks";
2
- import '../../stories/styles/shared.css';
2
+
3
3
  import * as ErrorPageStories from "./ErrorPage.stories";
4
4
 
5
5
  <Meta of={ErrorPageStories} />
@@ -65,7 +65,6 @@ Vous pouvez utiliser le slot `link-icon` pour remplacer l'icône dans les liens.
65
65
 
66
66
  const arrowIcon = mdiArrowTopRight
67
67
  </script>
68
- import '../../stories/styles/shared.css';
69
68
 
70
69
  <template>
71
70
  <ExternalLinks
@@ -76,7 +76,6 @@ Il est possible de personnaliser les icônes de fichier en utilisant le slot dyn
76
76
  state: 'initial',
77
77
  },
78
78
  ])
79
- import '../../stories/styles/shared.css';
80
79
  </script>
81
80
 
82
81
  <FileList
@@ -92,7 +92,6 @@ const filters = ref([
92
92
  title: 'Profession',
93
93
  },
94
94
  ])
95
- import '../../stories/styles/shared.css';
96
95
 
97
96
  const folderTypes = [
98
97
  {
@@ -93,7 +93,6 @@ const filters = ref([
93
93
  title: 'Profession',
94
94
  },
95
95
  ])
96
- import '../../stories/styles/shared.css';
97
96
 
98
97
  const folderTypes = [
99
98
  {
@@ -237,6 +236,14 @@ const professionList = [
237
236
  }}
238
237
  />
239
238
 
239
+ ## Titre du panneau
240
+
241
+ Vous pouvez afficher un titre au-dessus des filtres via la prop `title`. C'est utile pour distinguer plusieurs `FilterSideBar` présents sur une même page (par exemple associés à des tableaux différents).
242
+
243
+ Le niveau sémantique du titre est configurable via la prop `headingLevel` (`1` à `6`, défaut `2`) afin de l'intégrer correctement dans la hiérarchie de titres de la page. Le titre sert également de **nom accessible** au panneau (`aria-labelledby`).
244
+
245
+ <Canvas of={FilterSideBarStories.Title} />
246
+
240
247
  ## Gestion du z-index
241
248
 
242
249
  Le `FilterSideBar` utilise un `VNavigationDrawer` de Vuetify dont le z-index par défaut est **1000**.