Aller au contenu

Zone de défilement

Un conteneur défilable doté de barres de défilement personnalisées et compatibles avec tous les navigateurs, destiné aux fenêtres de discussion, aux barres latérales et aux arborescences de fichiers — avec un curseur « chunky » de style néobrutaliste.

import * as React from "react"

import { ScrollArea } from "@/components/ui/scroll-area"

La zone de défilement remplace les barres de défilement par défaut du navigateur par des barres que vous stylez — le défilement natif reste en dessous, si bien que molette, tactile et inertie se comportent comme d’habitude. Construite sur le composant Base UI Scroll Area et stylisée selon la recette néobrutaliste : un curseur plein et trapu dans la couleur de bordure, et un anneau de focus franc sur le viewport.

À privilégier dans ces cas :

  • Panneaux de discussion et de journaux — fixez la hauteur et laissez les messages défiler dans le panneau, pas dans la page.
  • Barres latérales et arborescences de fichiers — de longues listes de navigation qui défilent indépendamment du contenu principal.
  • Bandeaux horizontaux — rangées de tags, galeries de cartes et tableaux larges via orientation="horizontal".

Installation

pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/scroll-area.json
npx shadcn@latest add https://neobrutalism.com/r/base/scroll-area.json
yarn dlx shadcn@latest add https://neobrutalism.com/r/base/scroll-area.json
bunx --bun shadcn@latest add https://neobrutalism.com/r/base/scroll-area.json

Installez les dépendances suivantes :

pnpm add @base-ui/react
npm install @base-ui/react
yarn add @base-ui/react
bun add @base-ui/react

Copiez et collez le code suivant dans votre projet.

components/ui/scroll-area.tsx
"use client"

import * as React from "react"
import { ScrollArea as ScrollAreaPrimitive } from "radix-ui"

import { cn } from "@/lib/utils"

function ScrollArea({
  className,
  children,
  ...props
}: React.ComponentProps<typeof ScrollAreaPrimitive.Root>) {
  return (
    <ScrollAreaPrimitive.Root
      data-slot="scroll-area"
      className={cn("relative", className)}
      {...props}
    >
      <ScrollAreaPrimitive.Viewport
        data-slot="scroll-area-viewport"
        className="size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary"
      >
        {children}
      </ScrollAreaPrimitive.Viewport>
      <ScrollBar />
      <ScrollAreaPrimitive.Corner />
    </ScrollAreaPrimitive.Root>
  )
}

function ScrollBar({
  className,
  orientation = "vertical",
  ...props
}: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>) {
  return (
    <ScrollAreaPrimitive.ScrollAreaScrollbar
      data-slot="scroll-area-scrollbar"
      data-orientation={orientation}
      orientation={orientation}
      className={cn(
        "flex touch-none p-px transition-colors select-none data-horizontal:h-2.5 data-horizontal:flex-col data-horizontal:border-t data-horizontal:border-t-transparent data-vertical:h-full data-vertical:w-2.5 data-vertical:border-l data-vertical:border-l-transparent",
        className
      )}
      {...props}
    >
      <ScrollAreaPrimitive.ScrollAreaThumb
        data-slot="scroll-area-thumb"
        className="relative flex-1 rounded bg-border"
      />
    </ScrollAreaPrimitive.ScrollAreaScrollbar>
  )
}

export { ScrollArea, ScrollBar }

Adaptez les chemins d’import à la structure de votre projet.

Utilisation

import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area"
<ScrollArea className="h-[200px] w-[350px] rounded-md border p-4">
  Your scrollable content here.
</ScrollArea>

Composition

Utilisez la composition suivante pour construire un ScrollArea :

ScrollArea
└── ScrollBar

Exemples

Horizontal

Utilisez ScrollBar avec orientation="horizontal" pour un défilement horizontal.

import * as React from "react"
import Image from "next/image"

RTL

Pour activer le RTL dans Neobrutalism, consultez le guide de configuration RTL.

"use client"

import * as React from "react"

Accessibilité

Il n’existe pas de modèle WAI-ARIA pour les zones de défilement — et il n’en faut pas : le composant Base UI conserve un vrai conteneur de défilement natif en dessous, si bien que molette, tactile et clavier se comportent exactement comme dans le navigateur. Tous les navigateurs ne rendent pas d’eux-mêmes un conteneur de défilement focalisable au clavier : si le contenu ne comporte aucun élément focalisable, ajoutez tabIndex={0} et un aria-label au viewport pour que les utilisateurs au clavier puissent l’atteindre et le faire défiler — les styles prévoient déjà un anneau de focus visible pour ce cas. La barre de défilement personnalisée et son curseur sont des affordances réservées au pointeur ; elles ne doivent jamais être le seul moyen de faire défiler.

Référence API

Consultez la documentation Base UI Scroll Area.