SelectSearch

Documentation de cbk-toolkit

SelectSearch

Select custom pour filtrer par catégorie. Affiche Toutes les {label}s + la liste d'options, gère le clear X, le clic hors zone et la touche Escape. Re-sélectionner la même option désélectionne.

Démo en direct — filtre simple

Sélectionnez un rôle — le bouton X efface la sélection, Escape ou clic hors zone ferme.

Sélection : aucune

Démo en direct — pré-sélectionné

Avec une valeur initiale, le composant affiche directement l'option.

Valeur : Utilisateur

Démo en direct — combiné InputSearch + SelectSearch + Table

Pattern fréquent : barre de filtres au-dessus d'un tableau.

6 résultat(s) — recherche: "—" — rôle: tous

Utilisateurs: 6
NomRôle
Alice Martin
Administrateur
Bernard Dupont
Utilisateur
Camille Petit
Modérateur
David Leroy
Utilisateur
Émilie Moreau
Administrateur
Lignes par page :
Page 1 sur 2
Combinez les deux composants pour un filtrage multi-critères — chaque filtre reste contrôlé par son state.
Code source complet — copier-coller

Exemple complet avec filtres + Table.

"use client";

import { useState, useMemo } from "react";
import { InputSearch, SelectSearch, Table } from "@ramses1er/cbk-toolkit/client";
import type { SelectSearchOption, Column } from "@ramses1er/cbk-toolkit/client";

const ROLE_OPTIONS: SelectSearchOption[] = [
  { id: "admin", name: "Administrateur" },
  { id: "user", name: "Utilisateur" },
  { id: "moderator", name: "Modérateur" },
];

type User = { id: number; fullname: string; role: string };

export default function UsersPage() {
  const [search, setSearch] = useState("");
  const [role, setRole] = useState<SelectSearchOption | null>(null);

  const filtered = useMemo(() => {
    return users.filter((u) => {
      const matchSearch = !search || u.fullname.toLowerCase().includes(search.toLowerCase());
      const matchRole = !role || u.role === role.id;
      return matchSearch && matchRole;
    });
  }, [search, role]);

  const columns: Column<User>[] = [
    { header: "Nom", accessor: "fullname" },
    { header: "Rôle", render: (row) => row.role },
  ];

  return (
    <div className="space-y-4">
      <div className="flex gap-3">
        <InputSearch value={search} onChange={setSearch} placeholder="Rechercher..." />
        <SelectSearch label="rôle" options={ROLE_OPTIONS} selectedOption={role} onSelect={setRole} />
      </div>
      <Table data={filtered} columns={columns} label="Utilisateurs" />
    </div>
  );
}
Props
PropTypeDéfautDescription
labelstringrequisUtilisé pour "Toutes les {label}s" et placeholder
optionsSelectSearchOption[]requisListe des options {id, name}
selectedOptionSelectSearchOption | nullnullOption sélectionnée (contrôlé)
onSelect(option: SelectSearchOption | null) => voidrequisCallback — null = désélection / "Toutes"
placeholderstring"Filtrer par {label}"Texte quand aucune sélection
classNamestring—Classes pour le conteneur
Type — SelectSearchOption
type SelectSearchOption = {
  id: string;
  name: string;
};
Comportement
  • Clic sur le bouton ouvre/ferme la liste
  • Clic hors zone ou touche Escape ferme
  • Option "Toutes les {label}s" en tête — désélectionne
  • Re-cliquer sur la même option désélectionne (toggle)
  • Si aucune sélection, bouton X masqué ; sinon X visible à droite du Chevron
  • Si options vide → "Aucune option"