Skip to content

Commit

Permalink
Merge pull request #903 from dnum-mi/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
laruiss authored Aug 30, 2024
2 parents 830421d + b5a00ef commit 1c233d1
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 43 deletions.
10 changes: 0 additions & 10 deletions src/components/DsfrInput/DsfrInput.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,6 @@ export default {
description:
'Signale si le champ est de type textarea (`true`) ou non (`false`, par défaut)',
},
errorMessage: {
control: 'text',
description:
'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>**',
},
validMessage: {
control: 'text',
description:
'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>**',
},
isWithWrapper: {
control: 'boolean',
description:
Expand Down
4 changes: 2 additions & 2 deletions src/components/DsfrInput/DsfrInput.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export type DsfrInputGroupProps = {
labelClass?: string
modelValue?: string | number | null
placeholder?: string
errorMessage?: string
validMessage?: string
errorMessage?: string | string[]
validMessage?: string | string[]
wrapperClass?: string
}
18 changes: 9 additions & 9 deletions src/components/DsfrInput/DsfrInputGroup.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ Ce composant est très utile si vous souhaitez afficher un message d’erreur ou

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

### Attributs implicitement déclarés

Expand Down
4 changes: 2 additions & 2 deletions src/components/DsfrInput/DsfrInputGroup.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ export default {
},
errorMessage: {
control: 'text',
description: 'Message d’erreur',
description: 'Message d’erreur (ou tableau de messages)',
},
validMessage: {
control: 'text',
description: 'Message de validation',
description: 'Message de validation (ou tableau de messages)',
},
},
}
Expand Down
54 changes: 43 additions & 11 deletions src/components/DsfrInput/DsfrInputGroup.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
<script lang="ts" setup>
import { computed } from 'vue'
import DsfrInput from './DsfrInput.vue'
import { getRandomId } from '../../utils/random-utils'
Expand All @@ -13,7 +11,7 @@ defineOptions({
inheritAttrs: false,
})
const props = withDefaults(defineProps<DsfrInputGroupProps>(), {
withDefaults(defineProps<DsfrInputGroupProps>(), {
descriptionId: () => getRandomId('basic', 'input'),
hint: '',
label: '',
Expand All @@ -26,9 +24,6 @@ const props = withDefaults(defineProps<DsfrInputGroupProps>(), {
})
defineEmits<{ (e: 'update:modelValue', payload: string): void }>()
const message = computed(() => props.errorMessage || props.validMessage)
const messageClass = computed(() => props.errorMessage ? 'fr-error-text' : 'fr-valid-text')
</script>

<template>
Expand All @@ -37,7 +32,7 @@ const messageClass = computed(() => props.errorMessage ? 'fr-error-text' : 'fr-v
:class="[
{
'fr-input-group--error': errorMessage,
'fr-input-group--valid': validMessage,
'fr-input-group--valid': (validMessage && !errorMessage),
},
wrapperClass,
]"
Expand All @@ -52,24 +47,61 @@ const messageClass = computed(() => props.errorMessage ? 'fr-error-text' : 'fr-v
:is-invalid="!!errorMessage"
:label="label"
:hint="hint"
:description-id="(message && descriptionId) || undefined"
:description-id="((errorMessage || validMessage) && descriptionId) || undefined"
:label-visible="labelVisible"
:model-value="modelValue"
:placeholder="placeholder"
@update:model-value="$emit('update:modelValue', $event)"
/>
<div
v-if="message"
class="fr-messages-group"
role="alert"
aria-live="polite"
>
<template
v-if="Array.isArray(errorMessage)"
>
<p
v-for="message in errorMessage"
:id="descriptionId"
:key="message"
:data-testid="descriptionId"
class="fr-error-text"
>
<span>{{ message }}</span>
</p>
</template>
<p
v-else-if="errorMessage"
:id="descriptionId"
:key="errorMessage"
:data-testid="descriptionId"
class="fr-error-text"
>
<span>{{ errorMessage }}</span>
</p>

<template
v-if="Array.isArray(validMessage)"
>
<p
v-for="message in validMessage"
:id="descriptionId"
:key="message"
:data-testid="descriptionId"
class="fr-valid-text"
>
<span>{{ message }}</span>
</p>
</template>
<p
v-else-if="validMessage"
:id="descriptionId"
:key="validMessage"
:data-testid="descriptionId"
:class="messageClass"
class="fr-valid-text"
>
<span>{{ message }}</span>
<span>{{ validMessage }}</span>
</p>
</div>
</div>
Expand Down
26 changes: 21 additions & 5 deletions src/components/DsfrInput/docs-demo/DsfrInputGroupDemo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ const label = 'Label champ de saisie'
const placeholder = 'Yo'
const modelValue = ref('')
const modelValue2 = ref('')
const validMessage = 'Message de validation'
const errorMessage = 'Message d’erreur'
const validMessage1 = 'Message de validation'
const errorMessage1 = 'Message d’erreur'
const errorMessage2 = 'Message d’erreur 2'
const hint = 'Texte d’indice du champ'
const id = ''
const readonly = ''
Expand All @@ -22,7 +23,7 @@ const readonly = ''

<DsfrInputGroup
:id="id"
:valid-message="validMessage"
:valid-message="validMessage1"
:placeholder="placeholder"
:readonly="readonly !== ''"
:model-value="modelValue"
Expand All @@ -36,7 +37,7 @@ const readonly = ''

<DsfrInputGroup
:id="id"
:error-message="errorMessage"
:error-message="errorMessage1"
:placeholder="placeholder"
:readonly="readonly !== ''"
:model-value="modelValue"
Expand All @@ -46,7 +47,22 @@ const readonly = ''
label-visible
/>

<h2>3. Avec plusieurs champs de saisie</h2>
<h2>3. Avec plusieurs messages</h2>

<DsfrInputGroup
:id="id"
:error-message="[errorMessage1, errorMessage2]"
:valid-message="[validMessage1]"
:placeholder="placeholder"
:readonly="readonly !== ''"
:model-value="modelValue"
:label="label"
:type="type"
:hint="hint"
label-visible
/>

<h2>4. Avec plusieurs champs de saisie</h2>

<DsfrInputGroup
valid-message="Tout va bien pour ces deux champs"
Expand Down
3 changes: 3 additions & 0 deletions src/components/DsfrToggleSwitch/DsfrToggleSwitch.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ Le `DsfrToggleSwitch` est un composant Vue versatile, conçu pour permettre à l
| `labelLeft` | `boolean` | `false` | | Permet d'afficher le label à gauche de l'interrupteur |
| `borderBottom` | `boolean` | `false` | | Affiche une bordure sous l'interrupteur et le label |
| `inputId` | `string` | `getRandomId('toggle')` | | Identifiant unique pour le toggle. Utilisé pour l'accessibilité. |
| `activeText` | `string` | `Activé` | | Texte à afficher sous l'interrupteur lorsqu'il est activé |
| `inactiveText` | `string` | `Désactivé` | | Texte à afficher sous l'interrupteur lorsqu'il est désactivé |
| `notext` | `boolean` | `false` | | Désactive l'affichage de activeText et inactiveText |

## 📡 Évenements

Expand Down
90 changes: 89 additions & 1 deletion src/components/DsfrToggleSwitch/DsfrToggleSwitch.stories.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { fn } from '@storybook/test'
import { expect, fn, within } from '@storybook/test'

import DsfrToggleSwitch from './DsfrToggleSwitch.vue'

Expand Down Expand Up @@ -43,6 +43,18 @@ export default {
description:
'Appelé à chaque changement de la valeur `checked`.\n\n*N.B. : Ne fait pas partie du composant.*',
},
activeText: {
control: 'text',
description: 'Texte à afficher sous l\'interrupteur lorsqu\'il est activé',
},
inactiveText: {
control: 'text',
description: 'Texte à afficher sous l\'interrupteur lorsqu\'il est désactivé',
},
noText: {
control: 'boolean',
description: 'Désactive l\'affichage de activeText et inactiveText',
},
'update:modelValue': {
description:
'Evènement de mise à jour de la valeur contenue dans modelValue',
Expand Down Expand Up @@ -137,3 +149,79 @@ InterrupteurAvecBordure.args = {
modelValue: true,
borderBottom: true,
}

export const InterrupteurAvecTextePersonnalisé = (args) => ({
components: { DsfrToggleSwitch },
data () {
return args
},
template: `
<DsfrToggleSwitch
v-model="modelValue"
:label="label"
:hint="hint"
:input-id="inputId"
:active-text="activeText"
:inactive-text="inactiveText"
/>
`,
watch: {
modelValue (newVal) {
this.onChange(newVal)
},
},
})
InterrupteurAvecTextePersonnalisé.args = {
label: 'Interrupteur 1',
hint: 'Indice',
inputId: 'toggle-4',
modelValue: true,
activeText: 'Autorisé',
inactiveText: 'Interdit',
}

export const InterrupteurSansTexte = (args) => ({
components: { DsfrToggleSwitch },
data () {
return args
},
template: `
<DsfrToggleSwitch
v-model="modelValue"
:label="label"
:hint="hint"
:input-id="inputId"
:no-text="noText"
/>
`,
watch: {
modelValue (newVal) {
this.onChange(newVal)
},
},
})
InterrupteurSansTexte.args = {
label: 'Interrupteur 1',
hint: 'Indice',
inputId: 'toggle-5',
modelValue: true,
noText: true,
}

InterrupteurAvecTextePersonnalisé.play = async ({ canvasElement }) => {
const canvas = within(canvasElement)
const toggleSwitch = canvas.getByLabelText('Interrupteur 1') as HTMLInputElement
expect(toggleSwitch.checked).toBe(true)
toggleSwitch.click()
expect(toggleSwitch.checked).toBe(false)
toggleSwitch.click()

const toggleSwitchLabel = canvas.getByText('Interrupteur 1') as HTMLLabelElement
toggleSwitchLabel.click()
expect(toggleSwitch.checked).toBe(false)
toggleSwitchLabel.click()
expect(toggleSwitch.checked).toBe(true)

const hint = canvas.getByText('Indice') as HTMLParagraphElement
expect(hint).toBeVisible()
}
3 changes: 3 additions & 0 deletions src/components/DsfrToggleSwitch/DsfrToggleSwitch.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,7 @@ export type DsfrToggleSwitchProps = {
disabled?: boolean
labelLeft?: boolean
borderBottom?: boolean
activeText?: string
inactiveText?: string
noText?: boolean
}
7 changes: 5 additions & 2 deletions src/components/DsfrToggleSwitch/DsfrToggleSwitch.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ const props = withDefaults(defineProps<DsfrToggleSwitchProps>(), {
label: '',
labelLeft: false,
borderBottom: false,
activeText: 'Activé',
inactiveText: 'Désactivé',
noText: false,
})
defineEmits<{ (e: 'update:modelValue', payload: boolean): void }>()
Expand Down Expand Up @@ -45,8 +48,8 @@ const labelId = computed(() => {
:id="labelId"
class="fr-toggle__label"
:for="inputId"
data-fr-checked-label="Activé"
data-fr-unchecked-label="Désactivé"
:data-fr-checked-label="noText ? undefined : activeText"
:data-fr-unchecked-label="noText ? undefined : inactiveText"
style="--toggle-status-width: 3.55208125rem;"
>
{{ label }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ import DsfrToggleSwitch from '../DsfrToggleSwitch.vue'
label-left
/>
<DsfrToggleSwitch
label="Label action interrupteur"
label="Vitesse lumière ?"
border-bottom
active-text="Vers l'infini et au-delà"
inactive-text="restons terre à terre"
/>
</div>
</template>

0 comments on commit 1c233d1

Please sign in to comment.