Interrupteur - DsfrToggleSwitch
🌟 Introduction
Le DsfrToggleSwitch est un composant Vue versatile, conçu pour permettre à l’utilisateur de faire un choix entre deux états opposés (activé / désactivé).
🏅 La documentation sur les interrupteurs sur le DSFR
La story sur la carte sur le storybook de VueDsfr🛠️ Props
| Nom | Type | Défaut | Obligatoire | Description |
|---|---|---|---|---|
modelValue | boolean | Valeur booléenne associée à la case à cocher | ||
disabled | boolean | Valeur booléenne pour désactiver le toggle | ||
hint | string | Texte d'information complémentaire affiché en dessous de l'interrupteur | ||
label | string | '' | Texte du label associé à l'interrupteur | |
name | string | undefined | Attribut name de l’input | |
labelLeft | boolean | false | ⚠️ prop obsolète (donc désactivée) ♿️ | |
borderBottom | boolean | false | Affiche une bordure sous l'interrupteur et le label | |
inputId | string | useRandomId('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 | |
status | string | undefined | statut du message. | |
validMessage | string | Message de validité | ||
errorMessage | string | Message d'erreur |
📡Évenements
DsfrToggleSwitch émet l'événement suivant :
| Nom | type | Description |
|---|---|---|
update:modelValue | boolean | Est émis lorsque la valeur de l'interrupteur change |
🧩 Slots
Aucun slot n'est prévu dans ce composant. Le contenu est entièrement basé sur les props.
📝 Exemples
Exemple Basique
vue
<script lang="ts" setup>
import DsfrToggleSwitch from '../DsfrToggleSwitch.vue'
</script>
<template>
<div
class="flex flex-col"
>
<div>
<DsfrToggleSwitch label="Label action interrupteur" />
</div>
<div>
<DsfrToggleSwitch
label="Label action interrupteur"
/>
</div>
<div>
<DsfrToggleSwitch
label="Vitesse lumière ?"
border-bottom
active-text="Vers l'infini et au-delà"
inactive-text="restons terre à terre"
/>
</div>
</div>
</template>Exemple en erreur
vue
<script lang="ts" setup>
import DsfrToggleSwitch from '../DsfrToggleSwitch.vue'
</script>
<template>
<div
class="flex flex-col"
>
<div>
<DsfrToggleSwitch
label="Label action interrupteur (sans statut)"
border-bottom
/>
</div>
<div>
<DsfrToggleSwitch
label="Label action interrupteur (valide)"
border-bottom
status="valid"
valid-message="C'est tout bon !"
/>
</div>
<div>
<DsfrToggleSwitch
label="Label action interrupteur (en erreur)"
border-bottom
status="error"
error-message="Il y a une erreur"
/>
</div>
</div>
</template>⚙️ Code source du composant
vue
<script lang="ts" setup>
import type { DsfrToggleSwitchProps } from './DsfrToggleSwitch.types'
import { computed } from 'vue'
import { useRandomId } from '../../utils/random-utils'
export type { DsfrToggleSwitchProps }
const props = withDefaults(defineProps<DsfrToggleSwitchProps>(), {
inputId: () => useRandomId('toggle'),
hint: '',
label: '',
labelLeft: false,
borderBottom: false,
activeText: 'Activé',
inactiveText: 'Désactivé',
noText: false,
name: undefined,
status: undefined,
})
const emit = defineEmits<{
/** Émis par le composant DsfrToggleSwitch */
'update:modelValue': [payload: boolean]
}>()
const labelId = computed(() => {
return `${props.inputId}-label`
})
const message = computed(() => {
if (props.status === 'valid') {
return props.validMessage
}
if (props.status === 'error') {
return props.errorMessage
}
return undefined
})
</script>
<template>
<div
class="fr-toggle"
:class="{
[`fr-toggle--${status}`]: status,
'fr-toggle--border-bottom': borderBottom,
}"
>
<input
:id="inputId"
:disabled="disabled"
:aria-disabled="disabled"
type="checkbox"
:checked="modelValue"
:data-testid="inputId"
class="fr-toggle__input"
:aria-describedby="labelId"
:name="name"
@input="emit('update:modelValue', ($event.target as HTMLInputElement).checked)"
>
<label
:id="labelId"
class="fr-toggle__label"
:for="inputId"
:data-fr-checked-label="noText ? undefined : activeText"
:data-fr-unchecked-label="noText ? undefined : inactiveText"
style="--toggle-status-width: 3.55208125rem;"
>
{{ label }}
</label>
<p
v-if="hint"
:id="`${inputId}-hint-text`"
class="fr-hint-text"
>
{{ hint }}
</p>
<div
v-if="status"
:id="`${labelId}-messages`"
class="fr-messages-group"
aria-live="polite"
>
<p
:id="`${labelId}-message-${status}`"
class="fr-message"
:class="{
'fr-message--error': status === 'error',
'fr-message--valid': status === 'valid',
}"
>
{{ message }}
</p>
</div>
</div>
</template>ts
import type { InputHTMLAttributes } from 'vue'
export type DsfrToggleSwitchProps = {
modelValue?: boolean
inputId?: string
hint?: string
label?: string
disabled?: boolean
labelLeft?: boolean
borderBottom?: boolean
activeText?: string
inactiveText?: string
noText?: boolean
name?: string
status?: undefined | 'valid' | 'error'
validMessage?: string
errorMessage?: string
}
export type DsfrToggleSwitchGroupProps = {
id?: string
legend?: string
disabled?: boolean
toggleSwitches?: (DsfrToggleSwitchProps & InputHTMLAttributes)[]
borders?: boolean
activeText?: string
inactiveText?: string
noText?: boolean
status?: undefined | 'valid' | 'error'
validMessage?: string
errorMessage?: string
}