Skip to content

SuSlider ​

Composant SuSlider pour la sélection de valeurs numériques avec support du dual-range automatique, orientation verticale/horizontale, tooltips, marques personnalisées et accessibilité complète selon les normes W3C.

Utilisation simple ​

Le composant SuSlider peut être utilisé de manière autonome sans le wrapper SuFormField.

Slider de base ​

Slider simple

vue
<script setup>
import { ref } from 'vue'

const volume = ref(50)
</script>

<template>
  <SuSlider 
    :min="0"
    :max="100"
    v-model="volume"
  />
</template>

Dual-range (plage de valeurs) ​

Sélection d'une plage

vue
<script setup>
import { ref } from 'vue'

const priceRange = ref([200, 800])
const formatPrice = (value) => `${value}€`
</script>

<template>
  <SuSlider 
    :min="0"
    :max="1000"
    :step="10"
    :showValue="true"
    :formatValue="formatPrice"
    v-model="priceRange"
  />
</template>

Utilisation avec SuFormField ​

Pour une meilleure structuration des formulaires, utilisez SuSlider avec le composant SuFormField.

Slider avec label et message ​

Slider dans un formulaire

vue
<script setup>
import { ref } from 'vue'

const volume = ref(50)
</script>

<template>
  <SuFormField 
    label="Volume"
    message="Ajustez le volume"
  >
    <SuSlider 
      :min="0"
      :max="100"
      :showValue="true"
      v-model="volume"
    />
  </SuFormField>
</template>

Dual-range avec validation ​

Fourchette de prix avec validation

vue
<script setup>
import { ref, computed } from 'vue'

const priceRange = ref([200, 800])

const formatPrice = (value) => `${value}€`

const budgetState = computed(() => {
  const [min, max] = priceRange.value
  if (max - min < 100) return 'error'
  if (max - min > 500) return 'success'
  return 'default'
})

const budgetMessage = computed(() => {
  const [min, max] = priceRange.value
  if (max - min < 100) return 'La plage doit être d\'au moins 100€'
  if (max - min > 500) return 'Budget défini avec succès'
  return 'Définissez votre budget'
})
</script>

<template>
  <SuFormField 
    label="Fourchette de prix"
    :state="budgetState"
    :message="budgetMessage"
    required
  >
    <SuSlider 
      :min="0"
      :max="1000"
      :step="10"
      :showValue="true"
      :showLabels="true"
      :formatValue="formatPrice"
      v-model="priceRange"
    />
  </SuFormField>
</template>

Avec tooltips ​

Tooltips au survol

vue
<script setup>
import { ref } from 'vue'

const volume = ref(60)
const range = ref([30, 70])
</script>

<template>
  <SuFormField 
    label="Volume avec tooltip"
    message="Survolez le curseur pour voir la valeur"
  >
    <SuSlider 
      :min="0"
      :max="100"
      tooltip="top"
      v-model="volume"
    />
  </SuFormField>
  
  <SuFormField 
    label="Plage avec tooltips"
    message="Tooltips en bas"
  >
    <SuSlider 
      :min="0"
      :max="100"
      tooltip="bottom"
      v-model="range"
    />
  </SuFormField>
</template>

Avec marques personnalisées ​

Marques sur le slider

vue
<script setup>
import { ref } from 'vue'

const difficulty = ref(60)

const formatDifficulty = (value) => {
  if (value === 0) return 'Facile'
  if (value === 25) return 'Moyen'
  if (value === 50) return 'Difficile'
  if (value === 75) return 'Expert'
  if (value === 100) return 'Maître'
  return value.toString()
}
</script>

<template>
  <SuFormField 
    label="Niveau de difficulté"
  >
    <SuSlider 
      :min="0"
      :max="100"
      :marks="[0, 25, 50, 75, 100]"
      tooltip="top"
      :formatValue="formatDifficulty"
      v-model="difficulty"
    />
  </SuFormField>
</template>

Avec graduations et labels ​

Slider avec graduations

vue
<script setup>
import { ref } from 'vue'

const rating = ref(7)
</script>

<template>
  <SuFormField 
    label="Note"
    message="Donnez une note de 0 à 10"
  >
    <SuSlider 
      :min="0"
      :max="10"
      :step="1"
      :showValue="true"
      :showTicks="true"
      :showLabels="true"
      v-model="rating"
    />
  </SuFormField>
</template>

Orientation verticale ​

Slider vertical

vue
<script setup>
import { ref } from 'vue'

const verticalVolume = ref(75)
</script>

<template>
  <SuFormField 
    label="Volume vertical"
    message="Contrôle vertical du volume"
  >
    <SuSlider 
      :min="0"
      :max="100"
      orientation="vertical"
      tooltip="top"
      :showLabels="true"
      v-model="verticalVolume"
    />
  </SuFormField>
</template>

Avec slots before et after ​

Slider avec contenu personnalisé

vue
<script setup>
import { ref } from 'vue'

const volume = ref(60)
</script>

<template>
  <SuFormField 
    label="Volume avec contrôles"
  >
    <SuSlider 
      :min="0"
      :max="100"
      tooltip="top"
      v-model="volume"
    >
      <template #before>
        <div class="volume-icons">
          <span>🔇</span>
          <span>Silencieux</span>
        </div>
      </template>
      <template #after>
        <div class="volume-icons">
          <span>Fort</span>
          <span>🔊</span>
        </div>
      </template>
    </SuSlider>
  </SuFormField>
</template>

États de validation ​

États de formulaire

vue
<template>
  <SuFormField 
    label="État par défaut"
    message="Message d'aide normal"
    state="default"
  >
    <SuSlider :min="0" :max="100" :value="50" />
  </SuFormField>
  
  <SuFormField 
    label="État d'erreur"
    message="La valeur doit être supérieure à 30"
    state="error"
    required
  >
    <SuSlider :min="0" :max="100" :value="20" />
  </SuFormField>
  
  <SuFormField 
    label="État de succès"
    message="Valeur validée avec succès"
    state="success"
  >
    <SuSlider :min="0" :max="100" :value="80" />
  </SuFormField>
  
  <SuFormField 
    label="État d'avertissement"
    message="Attention, valeur proche du maximum"
    state="warning"
  >
    <SuSlider :min="0" :max="100" :value="95" />
  </SuFormField>
</template>

Support RTL ​

Support des langues RTL

vue
<script setup>
import { ref } from 'vue'

const volume = ref(70)
</script>

<template>
  <SuFormField 
    label="مستوى الصوت (RTL)"
    dir="rtl"
  >
    <SuSlider 
      :min="0"
      :max="100"
      dir="rtl"
      tooltip="top"
      :showLabels="true"
      :formatValue="(value) => value + '%'"
      v-model="volume"
    />
  </SuFormField>
</template>

Utilisation avec SuSliderField ​

Pour plus de simplicité, vous pouvez également utiliser le composant SuSliderField qui regroupe SuFormField et SuSlider en un seul composant :

vue
<script setup>
import { ref } from 'vue'

const volume = ref(50)
</script>

<template>
  <SuSliderField 
    label="Volume"
    :min="0"
    :max="100"
    :showValue="true"
    message="Ajustez le volume"
    v-model="volume"
  />
</template>

Cette approche est équivalente à :

vue
<SuFormField 
  label="Volume"
  message="Ajustez le volume"
>
  <SuSlider 
    :min="0"
    :max="100"
    :showValue="true"
    v-model="volume"
  />
</SuFormField>

API ​

Props ​

PropTypeDefaultDescription
valuenumber | [number, number]minValeur du slider (nombre simple ou tableau pour dual-range)
minnumber0Valeur minimale
maxnumber100Valeur maximale
stepnumber1Pas d'incrémentation
size'sm' | 'md' | 'lg''md'Taille du slider
disabledbooleanfalseDésactive le slider
readonlybooleanfalseSlider en lecture seule
orientation'horizontal' | 'vertical''horizontal'Orientation du slider
tooltip'none' | 'top' | 'bottom''none'Position du tooltip au survol
marksnumber[][]Marques à afficher sur le slider
showValuebooleantrueAfficher la valeur courante
showTicksbooleanfalseAfficher les graduations
showLabelsbooleanfalseAfficher les labels min/max
formatValue(value: number) => stringundefinedFonction de formatage des valeurs
dir'ltr' | 'rtl' | 'auto''auto'Direction du texte

Attributs d'accessibilité ​

PropTypeDefaultDescription
ariaLabelstringundefinedLabel accessible
ariaDescribedBystringundefinedID de l'élément de description
ariaInvalidbooleanundefinedIndique si la valeur est invalide
ariaRequiredbooleanundefinedIndique si le champ est requis
ariaValueTextstringundefinedDescription textuelle de la valeur

Events ​

EventTypeDescription
@update:modelValue(value: number | [number, number]) => voidÉmis lors du changement de valeur (v-model)
@change(value: number | [number, number]) => voidÉmis lors du changement
@input(value: number | [number, number]) => voidÉmis pendant le glissement
@focus(event: FocusEvent) => voidÉmis lors du focus
@blur(event: FocusEvent) => voidÉmis lors de la perte de focus
@keydown(event: KeyboardEvent) => voidÉmis lors de l'appui sur une touche

Slots ​

SlotDescription
beforeContenu affiché avant le slider
afterContenu affiché après le slider

Méthodes exposées ​

MéthodeTypeDescription
focus()() => voidDonne le focus au slider
sliderRefRef<HTMLDivElement>Référence au conteneur
thumb1RefRef<HTMLDivElement>Référence au premier thumb
thumb2RefRef<HTMLDivElement>Référence au second thumb (dual)

Détection automatique du dual-range ​

Le composant détecte automatiquement s'il doit fonctionner en mode dual-range en vérifiant si la valeur est un tableau :

vue
<!-- Mode simple -->
<SuSlider :value="50" />

<!-- Mode dual-range (détecté automatiquement) -->
<SuSlider :value="[20, 80]" />

Tooltips ​

Les tooltips affichent la valeur formatée au survol ou au focus des curseurs :

🎯 Positions disponibles ​

  • tooltip="none" : Pas de tooltip (défaut)
  • tooltip="top" : Tooltip au-dessus du curseur
  • tooltip="bottom" : Tooltip en dessous du curseur
vue
<!-- Tooltip en haut -->
<SuSlider tooltip="top" :value="50" />

<!-- Tooltip en bas -->
<SuSlider tooltip="bottom" :value="[20, 80]" />

<!-- Pas de tooltip, affichage statique -->
<SuSlider tooltip="none" :showValue="true" :value="50" />

Marques personnalisées ​

Les marques permettent d'afficher des valeurs spécifiques sur le slider :

📍 Fonctionnalités des marques ​

  • Positionnement automatique : Calcul de la position en pourcentage
  • Filtrage intelligent : Seules les marques dans la plage min/max sont affichées
  • Formatage : Utilise la fonction formatValue si fournie
  • Support RTL : Positionnement adapté à la direction
vue
<script setup>
import { ref } from 'vue'

const temperature = ref(22)
const formatTemp = (value) => `${value}°C`
</script>

<template>
  <SuSlider 
    :min="0"
    :max="40"
    :marks="[0, 10, 18, 24, 30, 40]"
    :formatValue="formatTemp"
    tooltip="top"
    v-model="temperature"
  />
</template>

Slots before et after ​

Les slots permettent d'ajouter du contenu personnalisé autour du slider :

🎨 Cas d'usage ​

  • Icônes : Indicateurs visuels (🔇 🔊)
  • Labels : Descriptions textuelles
  • Boutons : Actions rapides (reset, presets)
  • Informations : Contexte supplémentaire
vue
<template>
  <SuSlider 
    :min="0"
    :max="100"
    v-model="brightness"
  >
    <template #before>
      <div class="slider-controls">
        <span>🌙</span>
        <span>Sombre</span>
      </div>
    </template>
    <template #after>
      <div class="slider-controls">
        <span>Lumineux</span>
        <span>☀️</span>
      </div>
    </template>
  </SuSlider>
</template>

Support RTL ​

Le composant gère automatiquement les langues de droite à gauche :

🌐 Fonctionnalités RTL ​

  • Inversion automatique : Les pourcentages sont inversés
  • Calcul adapté : Position des curseurs ajustée
  • Marques et ticks : Positionnement correct
  • Navigation clavier : Flèches adaptées à la direction
vue
<!-- Support RTL -->
<SuSlider 
  dir="rtl"
  :min="0"
  :max="100"
  :value="70"
  tooltip="top"
/>

<!-- Auto-détection -->
<SuSlider 
  dir="auto"
  :value="50"
/>

Accessibilité ​

Le composant Slider respecte les normes WCAG 2.1 AA et les bonnes pratiques W3C :

✅ Fonctionnalités d'accessibilité ​

  • Rôle ARIA : role="slider" avec aria-valuemin, aria-valuemax, aria-valuenow
  • Navigation au clavier : Support des touches fléchées, Page Up/Down, Home/End
  • Orientation ARIA : aria-orientation pour les lecteurs d'écran
  • Annonces vocales : Messages pour les lecteurs d'écran lors des changements
  • Labels associés : Chaque slider a un label correctement associé via SuFormField
  • Messages d'état : Messages avec aria-live pour les lecteurs d'écran
  • Contraste des couleurs : Ratios conformes WCAG AA (4.5:1 minimum)
  • Focus visible : Indicateurs de focus clairs et contrastés
  • Tailles minimales : Thumbs de 44px minimum pour l'accessibilité tactile
  • Mode sombre : Contraste adapté automatiquement
  • Contraste élevé : Support de prefers-contrast: high
  • Réduction d'animation : Respect de prefers-reduced-motion

🎯 Bonnes pratiques ​

vue
<!-- Slider avec validation et accessibilité -->
<SuFormField 
  label="Niveau de difficulté"
  :required="true"
  :state="hasError ? 'error' : 'default'"
  :message="hasError ? 'Veuillez sélectionner un niveau' : 'Choisissez votre niveau'"
>
  <SuSlider 
    :min="1"
    :max="10"
    tooltip="top"
    :showTicks="true"
    ariaLabel="Sélecteur de niveau de difficulté"
    v-model="difficulty"
  />
</SuFormField>

<!-- Dual-range avec formatage -->
<SuFormField 
  label="Fourchette de prix"
  message="Définissez votre budget"
>
  <SuSlider 
    :min="0"
    :max="5000"
    :step="50"
    :value="[500, 2000]"
    tooltip="top"
    :showLabels="true"
    :formatValue="(value) => `${value}€`"
    v-model="priceRange"
  />
</SuFormField>

<!-- Slider vertical avec graduations -->
<SuFormField 
  label="Température"
>
  <SuSlider 
    :min="-10"
    :max="40"
    :step="1"
    orientation="vertical"
    tooltip="top"
    :showTicks="true"
    :showLabels="true"
    :formatValue="(value) => `${value}°C`"
    v-model="temperature"
  />
</SuFormField>
ToucheAction
TabNaviguer vers/depuis le slider
FlèchesAjuster la valeur par pas
Page UpAugmenter de 10% de la plage
Page DownDiminuer de 10% de la plage
HomeAller à la valeur minimale
EndAller à la valeur maximale

Fonctionnalités avancées ​

🎯 Dual-range intelligent ​

En mode dual-range (valeur tableau), le composant gère automatiquement :

  • Collision des thumbs : Les valeurs min/max ne peuvent pas se croiser
  • Sélection intelligente : Clic sur la track sélectionne le thumb le plus proche
  • Navigation clavier : Chaque thumb est focusable indépendamment

💬 Tooltips interactifs ​

Les tooltips offrent un feedback visuel immédiat :

  • Affichage au survol : Apparition fluide au hover
  • Affichage au focus : Visible lors de la navigation clavier
  • Affichage pendant le drag : Reste visible pendant le glissement
  • Formatage personnalisé : Utilise la fonction formatValue

📊 Marques personnalisées ​

Les marques permettent de mettre en évidence des valeurs importantes :

  • Positionnement précis : Calcul automatique de la position
  • Labels formatés : Affichage avec la fonction formatValue
  • Filtrage automatique : Seules les marques valides sont affichées
  • Style adaptatif : S'adapte à l'orientation et à la direction

🎨 Formatage flexible ​

La fonction formatValue permet :

  • Unités personnalisées : €, %, °C, km, etc.
  • Formatage complexe : Étoiles, barres de progression, etc.
  • Localisation : Adaptation aux différentes langues

Exemples d'usage avancés ​

Filtres de recherche ​

vue
<script setup>
import { ref } from 'vue'

const filters = ref({
  price: [100, 500],
  distance: 20,
  rating: 4
})

const formatPrice = (value) => `${value}€`
const formatDistance = (value) => `${value} km`
const formatRating = (value) => '★'.repeat(Math.floor(value)) + (value % 1 ? '☆' : '')
</script>

<template>
  <div class="filters">
    <h3>Filtres de recherche</h3>
    
    <SuFormField 
      label="Fourchette de prix"
      message="Définissez votre budget"
    >
      <SuSlider 
        :min="0"
        :max="1000"
        :step="10"
        tooltip="top"
        :showLabels="true"
        :marks="[0, 250, 500, 750, 1000]"
        :formatValue="formatPrice"
        v-model="filters.price"
      />
    </SuFormField>
    
    <SuFormField 
      label="Distance maximale"
      message="Rayon de recherche"
    >
      <SuSlider 
        :min="0"
        :max="50"
        :step="5"
        tooltip="bottom"
        :showTicks="true"
        :showLabels="true"
        :formatValue="formatDistance"
        v-model="filters.distance"
      />
    </SuFormField>
    
    <SuFormField 
      label="Note minimale"
      message="Note minimum souhaitée"
    >
      <SuSlider 
        :min="1"
        :max="5"
        :step="0.5"
        tooltip="top"
        :marks="[1, 2, 3, 4, 5]"
        :formatValue="formatRating"
        v-model="filters.rating"
      />
    </SuFormField>
  </div>
</template>

Publié sous licence MIT.