COMPOSANTS
Bascule de vue
Bascule tableau / grille
Deux boutons icône dans un join. La vue affichée porte btn-active (fond navy plein) et pointer-events-none ; l'autre reste un bouton default, donc visiblement cliquable.
<div class="join">
<button class="join-item btn btn-sm btn-active pointer-events-none" title="Vue tableau" aria-label="Vue tableau">
<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M3 6h18M3 14h18M3 18h18"/>
</svg>
</button>
<button class="join-item btn btn-sm" title="Vue grille" aria-label="Vue grille">
<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6z
M14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6z
M4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2z
M14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z"/>
</svg>
</button>
</div> Contexte dans une toolbar
Le toggle s'intègre dans la barre d'outils entre le compteur de résultats et le CTA principal. Il ne doit pas monopoliser l'attention.
284 produits
<div class="flex items-center justify-between mb-4">
<div class="flex items-center gap-3">
<span class="text-sm text-base-content/60">284 produits</span>
<div class="join">
<button class="join-item btn btn-sm btn-active pointer-events-none" title="Vue tableau">
<!-- icône lignes -->
</button>
<button class="join-item btn btn-sm" title="Vue grille">
<!-- icône grille -->
</button>
</div>
</div>
<button class="btn btn-primary btn-sm">Ajouter un produit</button>
</div> Persistance localStorage
La préférence de vue est mémorisée entre les sessions. Appliquer au chargement de la page, sauvegarder à chaque changement.
// Stimulus — les deux vues sont rendues, le contrôleur en masque une
applyView(mode) {
const isGrid = mode === "grid"
this.tableViewTarget.classList.toggle("hidden", isGrid)
this.gridViewTarget.classList.toggle("hidden", !isGrid)
this._setActive(this.tableBtnTarget, !isGrid)
this._setActive(this.gridBtnTarget, isGrid)
}
_setActive(btn, active) {
btn.classList.toggle("btn-active", active)
btn.classList.toggle("pointer-events-none", active)
} ✓ Vue sélectionnée :
btn-active + pointer-events-none, les deux ensemble.✓ Stocker la préférence en localStorage (persistante entre les sessions), avec une clé unique par liste.
✓ Défaut selon le type : grille pour les listes visuelles (images/vignettes), table pour les listes de données.
✓ Toujours ajouter
title et aria-label (icônes uniquement).✗ Ne pas marquer l'inactif en
btn-ghost : sans fond ni bordure, rien ne dit qu'il est cliquable.✗ Ne pas utiliser un dropdown pour basculer entre 2 vues — utiliser
join + btn.