Sheet
Un panneau qui glisse depuis n’importe quel bord, avec fermeture par balayage, verrouillage du défilement et imbrication empilée.
pnpm dlx shadcn@latest add https://hextaui.com/r/sheet.jsonAjoute le composant, les tokens de thème HextaUI et les composants HextaUI dont il dépend.
Ajoutez les tokens de thème à votre CSS global, si ce n’est pas déjà fait.
Installez les dépendances.
pnpm add @base-ui/react @tabler/icons-react class-variance-authority cnCopiez et collez le code suivant dans votre projet.
components/ui/sheet.tsx components/ui/button.tsx Mettez à jour les chemins d’import selon la configuration de votre projet.
Côtés
Définissez side pour la faire glisser depuis n'importe quel bord. Chaque sheet peut être balayée vers son propre bord, et le geste de fermeture suit votre doigt avec de l'inertie.
Contenu long
<SheetBody /> défile de lui-même, si bien que l'en-tête et le pied restent en place quelle que soit la longueur du contenu.
Sans le bouton de fermeture
Définissez showCloseButton={false} quand le pied offre déjà une sortie. Escape, le fond et le balayage la ferment toujours.
Imbriqué
Une sheet ou un alert dialog ouvert depuis une sheet se superpose. Le parent se réduit légèrement et chaque couche supplémentaire ajoute un fond plus clair, pour que la pile reste lisible. Escape ne ferme que la couche du dessus.
Contrôlé
Passez open et onOpenChange pour l’ouvrir de n’importe où, sans déclencheur.
Déclencheurs détachés
Partagez une sheet entre plusieurs déclencheurs avec createSheetHandle. Chaque déclencheur passe un payload que la sheet rend via une fonction enfant.
De droite à gauche
Avec dir="rtl", le côté droit passe au bord gauche, la sheet y entre en glissant et se balaie dans le même sens.
| Touche | Action |
|---|---|
| EnterSpace | Sur le déclencheur, ouvre la sheet et place le focus à l'intérieur. |
| TabShift + Tab | Se déplace entre les éléments focalisables. Le focus reste dans la sheet. |
| Esc | Ferme la sheet la plus haute et rend le focus à son déclencheur. |
- La sheet est un dialog modal.
<SheetTitle />la nomme et<SheetDescription />la décrit : incluez donc toujours un titre. - Le défilement de la page est verrouillé et le contenu derrière est masqué aux technologies d'assistance tant qu'elle est ouverte.
- Le bouton de fermeture a le label « Close ». La poignée sur le bord intérieur montre que la sheet peut être tirée et est masquée aux technologies d'assistance.
- Avec la réduction des animations, la sheet apparaît et disparaît en fondu au lieu de glisser.
Construit sur le drawer de Base UI. Chaque partie accepte les props de la primitive qu’elle enveloppe.
| Prop | Type | Par défaut |
|---|---|---|
defaultOpen | boolean | false |
open | boolean | – |
onOpenChange | (open: boolean, details) => void | – |
onOpenChangeCompleteAppelé à la fin de l’animation d’ouverture ou de fermeture. | (open: boolean) => void | – |
modal | boolean | "trap-focus" | true |
disablePointerDismissalLe garde ouvert lors d’un clic sur l’arrière-plan. | boolean | false |
swipeDirectionDéfini automatiquement d'après le côté et la direction du contenu. | "up" | "down" | "left" | "right" | – |
handle | SheetHandle<Payload> | – |
children | ReactNode | ({ payload }) => ReactNode | – |
| Prop | Type | Par défaut |
|---|---|---|
handle | SheetHandle<Payload> | – |
payload | Payload | – |
render | ReactElement | (props, state) => ReactElement | <button> |
| Attribut | Description |
|---|---|
data-slot="sheet-trigger" | Ciblez le déclencheur en CSS. |
data-popup-open | Présent tant que sa sheet est ouverte. |
Rend le portail, le fond, le viewport et la popup, ainsi que la poignée de glissement et le bouton de fermeture.
| Prop | Type | Par défaut |
|---|---|---|
side | "top" | "right" | "bottom" | "left" | "right" |
showCloseButton | boolean | true |
dirDéfinit la direction de la sheet. right et left sont inversés en rtl. | "ltr" | "rtl" | – |
initialFocus | boolean | RefObject | (type) => HTMLElement | boolean | – |
finalFocus | boolean | RefObject | (type) => HTMLElement | boolean | – |
classNameLes sheets latérales font 75% de large, jusqu'à 24rem à partir du point de rupture sm. | string | (state) => string | – |
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribut | Description |
|---|---|
data-slot="sheet-content" | Le panneau de la sheet. |
data-side | Le côté depuis lequel elle s'ouvre. |
data-open | Présent tant que la sheet est ouverte. |
data-starting-style | Présent pendant l’animation d’entrée. |
data-ending-style | Présent pendant l’animation de sortie. |
data-swiping | Présent pendant qu’on le fait glisser. |
data-swipe-direction | La direction qui la ferme. |
data-nested-drawer-open | Présent tant qu'une sheet imbriquée est ouverte au-dessus. |
data-slot="sheet-handle" | La poignée de glissement sur le bord intérieur. |
data-slot="sheet-close-button" | Le bouton de fermeture intégré. |
--drawer-swipe-movement-x | Distance de glissement horizontale. Une variable -y existe aussi. |
--nested-drawers | Combien de sheets imbriquées sont ouvertes au-dessus. |
Rendu par <SheetContent />. Les couches imbriquées ont un fond plus clair.
| Attribut | Description |
|---|---|
data-slot="sheet-overlay" | L’arrière-plan. |
data-nested | Présent sur les fonds des couches imbriquées. |
Des éléments <div> simples qui disposent la sheet. L'en-tête laisse la place au bouton de fermeture, le corps défile et prend la hauteur restante, et le pied empile ses actions sur petit écran et les aligne en fin à partir du point de rupture sm.
| Attribut | Description |
|---|---|
data-slot="sheet-header" | Titre et description. |
data-slot="sheet-body" | Contenu défilant. |
data-slot="sheet-footer" | Actions. |
| Prop | Type | Par défaut |
|---|---|---|
render | ReactElement | (props, state) => ReactElement | <h2> |
| Attribut | Description |
|---|---|
data-slot="sheet-title" | Nomme la sheet. |
| Prop | Type | Par défaut |
|---|---|---|
render | ReactElement | (props, state) => ReactElement | <p> |
| Attribut | Description |
|---|---|
data-slot="sheet-description" | Décrit la sheet. |
| Prop | Type | Par défaut |
|---|---|---|
render | ReactElement | (props, state) => ReactElement | <button> |
| Attribut | Description |
|---|---|
data-slot="sheet-close" | Ferme la sheet quand on appuie dessus. |
createSheetHandle<Payload>() renvoie un handle qui relie un <Sheet /> à des déclencheurs rendus ailleurs. Créez-le une seule fois, en dehors de votre composant.
- ButtonDes boutons dans toutes les variantes et tailles, avec un flux de chargement, de succès et d’erreur intégré qui évite le spinner pour les requêtes rapides.
- Alert dialogUne boîte de dialogue de confirmation pour les actions destructrices ou importantes, qui attend le travail asynchrone et devient une bottom sheet sur mobile.
- CommandUne liste d’actions recherchable, intégrée ou en palette ⌘K, avec pages, raccourcis et correspondances surlignées.
- Context menuUn menu d’actions au clic droit ou à l’appui long, avec sous-menus, éléments case à cocher et radio, et retour visuel de maintien au toucher.
- DialogUne fenêtre au-dessus de la page pour les formulaires et les tâches ciblées, avec en-tête et pied de page épinglés, imbrication, et une bottom sheet balayable sur mobile.
- DrawerUn panneau qui glisse depuis n’importe quel bord et suit votre doigt, avec des points d’accroche, une poignée fonctionnelle et des drawers imbriqués qui s’empilent.
Utilisé dans les blocks
Des blocks qui s’appuient sur Sheet.