Skip to content

Commit 1c233d1

Browse files
authored
Merge pull request #903 from dnum-mi/develop
Develop
2 parents 830421d + b5a00ef commit 1c233d1

File tree

11 files changed

+180
-43
lines changed

11 files changed

+180
-43
lines changed

src/components/DsfrInput/DsfrInput.stories.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -73,16 +73,6 @@ export default {
7373
description:
7474
'Signale si le champ est de type textarea (`true`) ou non (`false`, par défaut)',
7575
},
76-
errorMessage: {
77-
control: 'text',
78-
description:
79-
'Message d’erreur à associer au champ. **Ne fait pas partie du composant. Il appartient à <a href="/?path=/story/composants-champ-de-saisie-champ-avec-message-associ%C3%A9-dsfrinputgroup--champ-en-erreur">DsfrInputGroup</a>**',
80-
},
81-
validMessage: {
82-
control: 'text',
83-
description:
84-
'Message de validation à associer au champ. **Ne fait pas partie du composant. Il appartient à <a href="/?path=/story/composants-champ-de-saisie-champ-avec-message-associ%C3%A9-dsfrinputgroup--champ-valide">DsfrInputGroup</a>**',
85-
},
8676
isWithWrapper: {
8777
control: 'boolean',
8878
description:

src/components/DsfrInput/DsfrInput.types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export type DsfrInputGroupProps = {
2121
labelClass?: string
2222
modelValue?: string | number | null
2323
placeholder?: string
24-
errorMessage?: string
25-
validMessage?: string
24+
errorMessage?: string | string[]
25+
validMessage?: string | string[]
2626
wrapperClass?: string
2727
}

src/components/DsfrInput/DsfrInputGroup.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ Ce composant est très utile si vous souhaitez afficher un message d’erreur ou
1010

1111
| Nom | Type | Défaut | Obligatoire | Description |
1212
|-----------------|-------------|-------------------------|---------------|---------------------------------------------------------------|
13-
| `descriptionId` | `Function` | `() => getRandomId(...)`| | ID unique pour la description du groupe, généré automatiquement si non spécifié. |
14-
| `hint` | `string` | `''` | | Texte d'indice pour guider l'utilisateur dans le groupe de champs. |
15-
| `label` | `string` | `''` | | Le libellé associé au groupe de champs. |
16-
| `labelClass` | `string` | `''` | | Classe CSS personnalisée pour le style du libellé. |
17-
| `modelValue` | `string` | `''` | | La valeur liée au modèle du composant `DsfrInput`. |
18-
| `wrapperClass` | `string` | `''` | | Classe CSS pour le style du conteneur du groupe. |
19-
| `placeholder` | `string` | `undefined` | | Texte de l'espace réservé pour l'input. |
20-
| `errorMessage` | `string` | `undefined` | | Message d'erreur à afficher si une erreur est présente. |
21-
| `validMessage` | `string` | `undefined` | | Message de validation à afficher si l'input est valide. |
13+
| `descriptionId` | `Function` | `() => getRandomId(...)`| | ID unique pour la description du groupe, généré automatiquement si non spécifié. |
14+
| `hint` | `string` | `''` | | Texte d'indice pour guider l'utilisateur dans le groupe de champs. |
15+
| `label` | `string` | `''` | | Le libellé associé au groupe de champs. |
16+
| `labelClass` | `string` | `''` | | Classe CSS personnalisée pour le style du libellé. |
17+
| `modelValue` | `string` | `''` | | La valeur liée au modèle du composant `DsfrInput`. |
18+
| `wrapperClass` | `string` | `''` | | Classe CSS pour le style du conteneur du groupe. |
19+
| `placeholder` | `string` | `undefined` | | Texte de l'espace réservé pour l'input. |
20+
| `errorMessage` | `string \| string[]` | `undefined` | | Message(s) d'erreur à afficher si une erreur est présente. |
21+
| `validMessage` | `string \| string[]` | `undefined` | | Message(s) de validation à afficher si l'input est valide. |
2222

2323
### Attributs implicitement déclarés
2424

src/components/DsfrInput/DsfrInputGroup.stories.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@ export default {
5353
},
5454
errorMessage: {
5555
control: 'text',
56-
description: 'Message d’erreur',
56+
description: 'Message d’erreur (ou tableau de messages)',
5757
},
5858
validMessage: {
5959
control: 'text',
60-
description: 'Message de validation',
60+
description: 'Message de validation (ou tableau de messages)',
6161
},
6262
},
6363
}

src/components/DsfrInput/DsfrInputGroup.vue

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
<script lang="ts" setup>
2-
import { computed } from 'vue'
3-
42
import DsfrInput from './DsfrInput.vue'
53
64
import { getRandomId } from '../../utils/random-utils'
@@ -13,7 +11,7 @@ defineOptions({
1311
inheritAttrs: false,
1412
})
1513
16-
const props = withDefaults(defineProps<DsfrInputGroupProps>(), {
14+
withDefaults(defineProps<DsfrInputGroupProps>(), {
1715
descriptionId: () => getRandomId('basic', 'input'),
1816
hint: '',
1917
label: '',
@@ -26,9 +24,6 @@ const props = withDefaults(defineProps<DsfrInputGroupProps>(), {
2624
})
2725
2826
defineEmits<{ (e: 'update:modelValue', payload: string): void }>()
29-
30-
const message = computed(() => props.errorMessage || props.validMessage)
31-
const messageClass = computed(() => props.errorMessage ? 'fr-error-text' : 'fr-valid-text')
3227
</script>
3328

3429
<template>
@@ -37,7 +32,7 @@ const messageClass = computed(() => props.errorMessage ? 'fr-error-text' : 'fr-v
3732
:class="[
3833
{
3934
'fr-input-group--error': errorMessage,
40-
'fr-input-group--valid': validMessage,
35+
'fr-input-group--valid': (validMessage && !errorMessage),
4136
},
4237
wrapperClass,
4338
]"
@@ -52,24 +47,61 @@ const messageClass = computed(() => props.errorMessage ? 'fr-error-text' : 'fr-v
5247
:is-invalid="!!errorMessage"
5348
:label="label"
5449
:hint="hint"
55-
:description-id="(message && descriptionId) || undefined"
50+
:description-id="((errorMessage || validMessage) && descriptionId) || undefined"
5651
:label-visible="labelVisible"
5752
:model-value="modelValue"
5853
:placeholder="placeholder"
5954
@update:model-value="$emit('update:modelValue', $event)"
6055
/>
6156
<div
62-
v-if="message"
6357
class="fr-messages-group"
6458
role="alert"
6559
aria-live="polite"
6660
>
61+
<template
62+
v-if="Array.isArray(errorMessage)"
63+
>
64+
<p
65+
v-for="message in errorMessage"
66+
:id="descriptionId"
67+
:key="message"
68+
:data-testid="descriptionId"
69+
class="fr-error-text"
70+
>
71+
<span>{{ message }}</span>
72+
</p>
73+
</template>
74+
<p
75+
v-else-if="errorMessage"
76+
:id="descriptionId"
77+
:key="errorMessage"
78+
:data-testid="descriptionId"
79+
class="fr-error-text"
80+
>
81+
<span>{{ errorMessage }}</span>
82+
</p>
83+
84+
<template
85+
v-if="Array.isArray(validMessage)"
86+
>
87+
<p
88+
v-for="message in validMessage"
89+
:id="descriptionId"
90+
:key="message"
91+
:data-testid="descriptionId"
92+
class="fr-valid-text"
93+
>
94+
<span>{{ message }}</span>
95+
</p>
96+
</template>
6797
<p
98+
v-else-if="validMessage"
6899
:id="descriptionId"
100+
:key="validMessage"
69101
:data-testid="descriptionId"
70-
:class="messageClass"
102+
class="fr-valid-text"
71103
>
72-
<span>{{ message }}</span>
104+
<span>{{ validMessage }}</span>
73105
</p>
74106
</div>
75107
</div>

src/components/DsfrInput/docs-demo/DsfrInputGroupDemo.vue

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ const label = 'Label champ de saisie'
99
const placeholder = 'Yo'
1010
const modelValue = ref('')
1111
const modelValue2 = ref('')
12-
const validMessage = 'Message de validation'
13-
const errorMessage = 'Message d’erreur'
12+
const validMessage1 = 'Message de validation'
13+
const errorMessage1 = 'Message d’erreur'
14+
const errorMessage2 = 'Message d’erreur 2'
1415
const hint = 'Texte d’indice du champ'
1516
const id = ''
1617
const readonly = ''
@@ -22,7 +23,7 @@ const readonly = ''
2223

2324
<DsfrInputGroup
2425
:id="id"
25-
:valid-message="validMessage"
26+
:valid-message="validMessage1"
2627
:placeholder="placeholder"
2728
:readonly="readonly !== ''"
2829
:model-value="modelValue"
@@ -36,7 +37,7 @@ const readonly = ''
3637

3738
<DsfrInputGroup
3839
:id="id"
39-
:error-message="errorMessage"
40+
:error-message="errorMessage1"
4041
:placeholder="placeholder"
4142
:readonly="readonly !== ''"
4243
:model-value="modelValue"
@@ -46,7 +47,22 @@ const readonly = ''
4647
label-visible
4748
/>
4849

49-
<h2>3. Avec plusieurs champs de saisie</h2>
50+
<h2>3. Avec plusieurs messages</h2>
51+
52+
<DsfrInputGroup
53+
:id="id"
54+
:error-message="[errorMessage1, errorMessage2]"
55+
:valid-message="[validMessage1]"
56+
:placeholder="placeholder"
57+
:readonly="readonly !== ''"
58+
:model-value="modelValue"
59+
:label="label"
60+
:type="type"
61+
:hint="hint"
62+
label-visible
63+
/>
64+
65+
<h2>4. Avec plusieurs champs de saisie</h2>
5066

5167
<DsfrInputGroup
5268
valid-message="Tout va bien pour ces deux champs"

src/components/DsfrToggleSwitch/DsfrToggleSwitch.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ Le `DsfrToggleSwitch` est un composant Vue versatile, conçu pour permettre à l
1919
| `labelLeft` | `boolean` | `false` | | Permet d'afficher le label à gauche de l'interrupteur |
2020
| `borderBottom` | `boolean` | `false` | | Affiche une bordure sous l'interrupteur et le label |
2121
| `inputId` | `string` | `getRandomId('toggle')` | | Identifiant unique pour le toggle. Utilisé pour l'accessibilité. |
22+
| `activeText` | `string` | `Activé` | | Texte à afficher sous l'interrupteur lorsqu'il est activé |
23+
| `inactiveText` | `string` | `Désactivé` | | Texte à afficher sous l'interrupteur lorsqu'il est désactivé |
24+
| `notext` | `boolean` | `false` | | Désactive l'affichage de activeText et inactiveText |
2225

2326
## 📡 Évenements
2427

src/components/DsfrToggleSwitch/DsfrToggleSwitch.stories.ts

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { fn } from '@storybook/test'
1+
import { expect, fn, within } from '@storybook/test'
22

33
import DsfrToggleSwitch from './DsfrToggleSwitch.vue'
44

@@ -43,6 +43,18 @@ export default {
4343
description:
4444
'Appelé à chaque changement de la valeur `checked`.\n\n*N.B. : Ne fait pas partie du composant.*',
4545
},
46+
activeText: {
47+
control: 'text',
48+
description: 'Texte à afficher sous l\'interrupteur lorsqu\'il est activé',
49+
},
50+
inactiveText: {
51+
control: 'text',
52+
description: 'Texte à afficher sous l\'interrupteur lorsqu\'il est désactivé',
53+
},
54+
noText: {
55+
control: 'boolean',
56+
description: 'Désactive l\'affichage de activeText et inactiveText',
57+
},
4658
'update:modelValue': {
4759
description:
4860
'Evènement de mise à jour de la valeur contenue dans modelValue',
@@ -137,3 +149,79 @@ InterrupteurAvecBordure.args = {
137149
modelValue: true,
138150
borderBottom: true,
139151
}
152+
153+
export const InterrupteurAvecTextePersonnalisé = (args) => ({
154+
components: { DsfrToggleSwitch },
155+
data () {
156+
return args
157+
},
158+
template: `
159+
<DsfrToggleSwitch
160+
v-model="modelValue"
161+
:label="label"
162+
:hint="hint"
163+
:input-id="inputId"
164+
:active-text="activeText"
165+
:inactive-text="inactiveText"
166+
/>
167+
`,
168+
watch: {
169+
modelValue (newVal) {
170+
this.onChange(newVal)
171+
},
172+
},
173+
})
174+
InterrupteurAvecTextePersonnalisé.args = {
175+
label: 'Interrupteur 1',
176+
hint: 'Indice',
177+
inputId: 'toggle-4',
178+
modelValue: true,
179+
activeText: 'Autorisé',
180+
inactiveText: 'Interdit',
181+
}
182+
183+
export const InterrupteurSansTexte = (args) => ({
184+
components: { DsfrToggleSwitch },
185+
data () {
186+
return args
187+
},
188+
template: `
189+
<DsfrToggleSwitch
190+
v-model="modelValue"
191+
:label="label"
192+
:hint="hint"
193+
:input-id="inputId"
194+
:no-text="noText"
195+
/>
196+
`,
197+
watch: {
198+
modelValue (newVal) {
199+
this.onChange(newVal)
200+
},
201+
},
202+
})
203+
InterrupteurSansTexte.args = {
204+
label: 'Interrupteur 1',
205+
hint: 'Indice',
206+
inputId: 'toggle-5',
207+
modelValue: true,
208+
noText: true,
209+
}
210+
211+
InterrupteurAvecTextePersonnalisé.play = async ({ canvasElement }) => {
212+
const canvas = within(canvasElement)
213+
const toggleSwitch = canvas.getByLabelText('Interrupteur 1') as HTMLInputElement
214+
expect(toggleSwitch.checked).toBe(true)
215+
toggleSwitch.click()
216+
expect(toggleSwitch.checked).toBe(false)
217+
toggleSwitch.click()
218+
219+
const toggleSwitchLabel = canvas.getByText('Interrupteur 1') as HTMLLabelElement
220+
toggleSwitchLabel.click()
221+
expect(toggleSwitch.checked).toBe(false)
222+
toggleSwitchLabel.click()
223+
expect(toggleSwitch.checked).toBe(true)
224+
225+
const hint = canvas.getByText('Indice') as HTMLParagraphElement
226+
expect(hint).toBeVisible()
227+
}

src/components/DsfrToggleSwitch/DsfrToggleSwitch.types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,7 @@ export type DsfrToggleSwitchProps = {
66
disabled?: boolean
77
labelLeft?: boolean
88
borderBottom?: boolean
9+
activeText?: string
10+
inactiveText?: string
11+
noText?: boolean
912
}

src/components/DsfrToggleSwitch/DsfrToggleSwitch.vue

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ const props = withDefaults(defineProps<DsfrToggleSwitchProps>(), {
1313
label: '',
1414
labelLeft: false,
1515
borderBottom: false,
16+
activeText: 'Activé',
17+
inactiveText: 'Désactivé',
18+
noText: false,
1619
})
1720
1821
defineEmits<{ (e: 'update:modelValue', payload: boolean): void }>()
@@ -45,8 +48,8 @@ const labelId = computed(() => {
4548
:id="labelId"
4649
class="fr-toggle__label"
4750
:for="inputId"
48-
data-fr-checked-label="Activé"
49-
data-fr-unchecked-label="Désactivé"
51+
:data-fr-checked-label="noText ? undefined : activeText"
52+
:data-fr-unchecked-label="noText ? undefined : inactiveText"
5053
style="--toggle-status-width: 3.55208125rem;"
5154
>
5255
{{ label }}

0 commit comments

Comments
 (0)