Skip to content

RadioGroupField

Composant RadioGroupField pour la sélection unique avec deux styles d'affichage : classique ou en cartes. Support complet de l'accessibilité selon les normes W3C.

Exemples d'utilisation

RadioGroupField de base

Style par défaut

vue
<script setup>
const selectedValue = ref('')
const options = [
  { value: 'option1', label: 'Option 1' },
  { value: 'option2', label: 'Option 2' },
  { value: 'option3', label: 'Option 3' },
  { value: 'option4', label: 'Option 4', disabled: true }
]
</script>

<template>
  <SuRadioGroupField 
    :options="options"
    label="Sélection unique"
    name="basic-radio"
    v-model:value="selectedValue"
  />
</template>

Style carte

Cartes en bloc

vue
<template>
  <SuRadioGroupField 
    :options="[
      { 
        value: 'basic', 
        label: 'Plan Basic', 
        description: 'Fonctionnalités de base pour débuter'
      },
      { 
        value: 'pro', 
        label: 'Plan Pro', 
        description: 'Fonctionnalités avancées pour les professionnels'
      },
      { 
        value: 'enterprise', 
        label: 'Plan Enterprise', 
        description: 'Solution complète pour les grandes entreprises'
      }
    ]"
    displayType="block-card"
    label="Plan d'abonnement"
    name="plan-radio"
    v-model:value="selectedPlan"
  />
</template>

Cartes en ligne

Cartes inline

vue
<template>
  <SuRadioGroupField 
    :options="[
      { value: 'small', label: 'Small', description: 'Jusqu\'à 5 utilisateurs' },
      { value: 'medium', label: 'Medium', description: 'Jusqu\'à 25 utilisateurs' },
      { value: 'large', label: 'Large', description: 'Utilisateurs illimités' }
    ]"
    displayType="inline-card"
    direction="horizontal"
    label="Taille d'équipe"
    name="team-size-radio"
    v-model:value="teamSize"
  />
</template>

Avec icônes

Options avec icônes

vue
<script setup>
import { UserIcon, BuildingOfficeIcon, GlobeAltIcon } from '@heroicons/vue/24/outline'

const accountType = ref('')
const accountOptions = [
  { value: 'user', label: 'Particulier', icon: UserIcon },
  { value: 'business', label: 'Entreprise', icon: BuildingOfficeIcon },
  { value: 'organization', label: 'Organisation', icon: GlobeAltIcon }
]
</script>

<template>
  <SuRadioGroupField 
    :options="accountOptions"
    displayType="block-card"
    label="Type de compte"
    name="account-type-radio"
    v-model:value="accountType"
  />
</template>

Tailles

Tailles disponibles

vue
<template>
  <SuRadioGroupField size="sm" label="Small" name="size-sm" />
  <SuRadioGroupField size="md" label="Medium" name="size-md" />
  <SuRadioGroupField size="lg" label="Large" name="size-lg" />
</template>

États et validation

États de validation

vue
<template>
  <SuRadioGroupField 
    state="default"
    label="État par défaut"
    message="Sélectionnez une option"
  />
  <SuRadioGroupField 
    state="error"
    label="État d'erreur"
    message="Veuillez faire une sélection"
    :required="true"
  />
  <SuRadioGroupField 
    state="success"
    label="État de succès"
    message="Sélection valide !"
  />
</template>

Direction horizontale

Disposition horizontale

vue
<template>
  <SuRadioGroupField 
    :options="options"
    direction="horizontal"
    label="Acceptez-vous les conditions ?"
    name="horizontal-radio"
    v-model:value="acceptance"
  />
</template>

Scroll avec hauteur limitée

Liste avec scroll vertical

vue
<template>
  <SuRadioGroupField 
    :options="longCountriesList"
    maxHeight="180px"
    label="Pays (avec scroll)"
    name="countries-scroll"
    message="Liste avec hauteur limitée et scroll automatique"
    v-model:value="selectedCountry"
  />
</template>

Avec slots personnalisés

Slots before et after

vue
<template>
  <SuRadioGroupField 
    :options="planOptions"
    displayType="block-card"
    label="Choisissez votre plan"
    name="subscription-plan"
    v-model:value="selectedPlan"
  >
    <template #before>
      <div class="plan-info">
        🎯 Choisissez le plan qui correspond le mieux à vos besoins.
      </div>
    </template>
    <template #after>
      <div class="plan-comparison">
        <a href="/plans/compare">Comparer tous les plans en détail →</a>
      </div>
    </template>
  </SuRadioGroupField>
</template>

API

Props

PropTypeDefaultDescription
optionsRadioOption[][]Liste des options radio
valuestring | numberundefinedValeur sélectionnée
namestringundefinedNom du groupe radio (généré automatiquement si non fourni)
size'sm' | 'md' | 'lg''md'Taille des éléments
state'default' | 'error' | 'success' | 'warning''default'État visuel
disabledbooleanfalseDésactive tout le groupe
requiredbooleanfalseChamp requis
displayType'default' | 'inline-card' | 'block-card''default'Type d'affichage
direction'horizontal' | 'vertical''vertical'Direction du groupe
maxHeightstringnullHauteur maximale avec scroll automatique
labelstringundefinedLabel du groupe
messagestringundefinedMessage affiché (style déterminé par le state)

Types d'options

RadioOption

typescript
interface RadioOption {
  value: string | number
  label: string
  description?: string
  disabled?: boolean
  icon?: Component
}

Events

EventTypeDescription
@update:value(value: string | number) => voidÉmis lors du changement de valeur
@change(value: string | number) => voidÉmis lors du changement
@focus(event: FocusEvent) => voidÉmis lors du focus
@blur(event: FocusEvent) => voidÉmis lors de la perte de focus

Accessibilité

Le composant RadioGroup respecte les normes WCAG 2.1 AA :

✅ Fonctionnalités d'accessibilité

  • Fieldset et Legend : Structure sémantique correcte avec <fieldset> et <legend>
  • Attributs ARIA : role="radiogroup", aria-required, aria-invalid
  • Navigation au clavier : Support des touches fléchées, Tab, Espace
  • Labels associés : Chaque radio a un label correctement associé
  • Messages d'état : Messages avec aria-live pour les lecteurs d'écran
  • Focus visible : Indicateurs de focus clairs et contrastés
  • Contraste des couleurs : Ratios conformes WCAG AA
  • Groupement logique : Options regroupées sémantiquement

🎯 Bonnes pratiques

vue
<!-- RadioGroup avec validation -->
<SuRadioGroupField 
  :options="options"
  :required="true"
  label="Méthode de paiement"
  name="payment-method"
  :state="hasError ? 'error' : 'default'"
  :message="hasError ? 'Veuillez sélectionner une méthode de paiement' : undefined"
  v-model:value="paymentMethod"
/>

<!-- RadioGroup avec cartes et descriptions -->
<SuRadioGroupField 
  :options="planOptions"
  displayType="block-card"
  label="Plan d'abonnement"
  name="subscription-plan"
  message="Choisissez le plan qui correspond à vos besoins"
  v-model:value="selectedPlan"
/>
ToucheAction
TabNaviguer vers/depuis le groupe
FlèchesNaviguer entre les options du groupe
EspaceSélectionner l'option focalisée

Exemples d'usage avancés

Formulaire de configuration

vue
<script setup>
import { ref } from 'vue'
import { CogIcon, UserIcon, ShieldCheckIcon } from '@heroicons/vue/24/outline'

const theme = ref('light')
const privacy = ref('public')
const notifications = ref('all')

const themeOptions = [
  { value: 'light', label: 'Clair', description: 'Interface claire' },
  { value: 'dark', label: 'Sombre', description: 'Interface sombre' },
  { value: 'auto', label: 'Automatique', description: 'Suit les préférences système' }
]

const privacyOptions = [
  { value: 'public', label: 'Public', icon: UserIcon },
  { value: 'private', label: 'Privé', icon: ShieldCheckIcon }
]
</script>

<template>
  <form class="space-y-6">
    <SuRadioGroupField 
      :options="themeOptions"
      displayType="block-card"
      label="Thème"
      name="theme"
      v-model:value="theme"
    />
    
    <SuRadioGroupField 
      :options="privacyOptions"
      displayType="inline-card"
      direction="horizontal"
      label="Confidentialité"
      name="privacy"
      v-model:value="privacy"
    />
  </form>
</template>

Publié sous licence MIT.