Skip to content

GridLayout ​

Grille de cellules de même importance : listes de produits, galeries, tableaux de bord. Les cellules se lisent ligne par ligne. Le nombre de colonnes suit la largeur du conteneur, ou s'adapte seul à partir d'une largeur minimale de cellule. Un mode liste empile les cellules, avec un sélecteur grille / liste en option.

Exemples d'utilisation ​

Colonnes par largeur ​

Par défaut : 1 colonne, 2 dès 640px, 3 dès 1024px.

vue
<template>
  <SuGridLayout :columns="{ base: 1, sm: 2, lg: 3, xl: 4 }">
    <ProductCard v-for="product in products" :key="product.id" :product="product" />
  </SuGridLayout>
</template>

Chaque valeur s'applique jusqu'au seuil suivant (mobile first). Un nombre seul fixe les colonnes à toutes les largeurs : :columns="4".

Colonnes automatiques ​

min-item-width fixe la largeur minimale d'une cellule : la grille place autant de colonnes que possible (auto-fill), sans point de rupture. Une cellule ne dépasse jamais la largeur du conteneur.

vue
<SuGridLayout min-item-width="14rem" gap="sm">
  <MediaTile v-for="item in gallery" :key="item.id" :item="item" />
</SuGridLayout>

Grille ou liste ​

v-model:view passe en liste ('list') : les cellules sont empilées sur une colonne. view-toggle affiche dans l'en-tête un sélecteur grille / liste ; le slot header accueille le titre, le nombre de résultats ou des filtres. Le slot default reçoit view pour adapter les cellules.

vue
<script setup lang="ts">
import { ref } from 'vue'

const view = ref<'grid' | 'list'>('grid')
</script>

<template>
  <SuGridLayout v-model:view="view" view-toggle items-tag="ul">
    <template #header>
      <h2>Produits</h2>
      <p>{{ products.length }} résultats</p>
    </template>

    <li v-for="product in products" :key="product.id">
      <ProductCard :product="product" :direction="view === 'list' ? 'horizontal' : 'vertical'" />
    </li>
  </SuGridLayout>
</template>

Sans view-toggle, l'affichage reste pilotable de l'extérieur, par exemple avec votre propre contrôle dans une barre d'outils : <SuGridLayout :view="view">.

API ​

Props ​

PropTypeDéfautDescription
view (v-model:view)'grid' | 'list''grid'Affichage : en liste, les cellules sont empilées sur une colonne
columnsnumber | { base?, sm?, md?, lg?, xl? }{ base: 1, sm: 2, lg: 3 }Colonnes, fixes ou par largeur de conteneur
minItemWidthstring—Largeur minimale d'une cellule (longueur CSS) : colonnes automatiques, remplace columns
align'start' | 'center' | 'end' | 'stretch''stretch'Alignement vertical des cellules d'une rangée (stretch : même hauteur)
itemsTag'div' | 'ul' | 'ol''div'Élément qui contient les cellules : ul ou ol pour une liste (cellules li)
viewTogglebooleanfalseAffiche le sélecteur grille / liste dans l'en-tête
viewToggleLabelstring'Affichage'Nom accessible du sélecteur
gridLabelstring'Grille'Libellé du bouton « grille »
listLabelstring'Liste'Libellé du bouton « liste »
gap'none' | 'sm' | 'md' | 'lg' | 'xl''md'Écart entre les cellules

Événements ​

ÉvénementPayloadDescription
update:view'grid' | 'list'Affichage choisi dans le sélecteur

Slots ​

SlotPropsDescription
header—Titre, nombre de résultats, filtres (à côté du sélecteur)
default{ view }Cellules : chaque enfant direct est une cellule

Comportement responsive ​

Largeur du conteneurColonnes (valeur par défaut)
< 640px1
≥ 640px2
≥ 1024px3

Avec min-item-width, le nombre de colonnes dépend uniquement de la place disponible. En liste, une seule colonne quelle que soit la largeur.

Accessibilité ​

  • Ordre de lecture : les cellules se lisent ligne par ligne, dans l'ordre du DOM, comme la tabulation. C'est la grille à préférer quand l'ordre compte (résultats triés, fil chronologique).
  • Listes : avec items-tag="ul" (ou "ol") et des cellules <li>, les lecteurs d'écran annoncent le nombre d'éléments. Le rôle list est posé explicitement, car certains navigateurs le retirent aux listes sans puces.
  • Sélecteur grille / liste : un groupe nommé (viewToggleLabel) de deux boutons bascule (aria-pressed). Les libellés ne changent pas : seul l'état enfoncé indique l'affichage actif.

Publié sous licence MIT.