COMPOSANTS

Pagination

Précédent / Suivant

Deux boutons et un indicateur de position, alignés à droite sous la liste. Pas de numéros de page : sur des listes filtrées, sauter à la page 17 n'a pas de sens, avancer et reculer si.

3 / 25
<div class="flex items-center justify-end gap-3">
  <button class="btn btn-sm">
    <svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
    </svg>
    Précédent
  </button>
  <span class="text-sm text-base-content/50 font-accent">3 / 25</span>
  <button class="btn btn-sm">
    Suivant
    <svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
    </svg>
  </button>
</div>

Bornes : première et dernière page

Le bouton qui ne mène nulle part devient un span en opacity-40 pointer-events-none. Il garde sa place, donc les deux boutons ne bougent pas d'une page à l'autre.

Première page
Précédent 1 / 25
Dernière page
25 / 25 Suivant
<!-- Bouton inactif : span, pas button[disabled], pas btn-disabled -->
<span class="btn btn-sm opacity-40 pointer-events-none">
  <svg class="h-4 w-4" ...></svg>
  Précédent
</span>

Rails (ERB)

Le contrôleur expose la page courante et le nombre total de pages ; la vue choisit lien ou span selon la borne.

<div class="flex items-center justify-end gap-3">
  <% if @page > 1 %>
    <%= link_to products_path(page: @page - 1), class: "btn btn-sm" do %>
      <svg class="h-4 w-4" ...></svg>
      Précédent
    <% end %>
  <% else %>
    <span class="btn btn-sm opacity-40 pointer-events-none">
      <svg class="h-4 w-4" ...></svg>
      Précédent
    </span>
  <% end %>

  <span class="text-sm text-base-content/50 font-accent"><%= @page %> / <%= @total_pages %></span>

  <% if @page < @total_pages %>
    <%= link_to products_path(page: @page + 1), class: "btn btn-sm" do %>
      Suivant
      <svg class="h-4 w-4" ...></svg>
    <% end %>
  <% else %>
    <span class="btn btn-sm opacity-40 pointer-events-none">
      Suivant
      <svg class="h-4 w-4" ...></svg>
    </span>
  <% end %>
</div>

Règles

Sous la liste, aligné à droite (justify-end), jamais au-dessus.
Indicateur page / total entre les deux boutons, en font-accent.
Le compteur de résultats reste dans la barre d'outils en haut de liste ; la pagination ne le répète pas.
Jamais btn-disabled ni disabled pour la borne : leur fond gris est plus visible que le bouton actif, le contraste dit l'inverse de l'état.
Jamais join ici : il est réservé aux segments d'un même choix (bascule de vue), pas à deux actions opposées.
Pas de numéros de page ni de « aller à la page ».