Carousel
Native Scroll-Snap-Slides mit Momentum auf Touch, Maus-Ziehen, Pfeiltasten, Punkten, Thumbnails und einem Autoplay, das pausiert, wenn es soll.
pnpm dlx shadcn@latest add https://hextaui.com/r/carousel.jsonFügt die Komponente, die HextaUI-Theme-Tokens und alle HextaUI-Komponenten hinzu, von denen sie abhängt.
Füge die Theme-Tokens zu deinem globalen CSS hinzu, falls du das noch nicht getan hast.
Installiere die Abhängigkeiten.
pnpm add @base-ui/react @tabler/icons-react class-variance-authority cnKopiere den folgenden Code und füge ihn in dein Projekt ein.
components/ui/carousel.tsx components/ui/button.tsx components/ui/number-flow.tsx lib/motion.ts Passe die Importpfade an dein Projekt-Setup an.
Folien scrollen nativ mit CSS Scroll Snap, sodass Touch-Schwung und Trackpad-Scrollen sich wie die Plattform anfühlen. Eine Maus kann ziehen, und die Pfeiltasten bewegen jeweils eine Folie.
API
Übergib setApi, um die Carousel-API zu erhalten, und höre auf select, um deine eigene Position anzuzeigen. Next ist auf der letzten Folie deaktiviert, behält aber den Fokus.
Mehrere pro Ansicht
Elemente setzen ihre eigene basis. Die Abstände kommen aus der spacing-Prop und bleiben deshalb bei jeder Basis exakt.
Punkte und Zähler
Der aktive Punkt dehnt sich, während die Folien scrollen, und seine Nachbarn machen Platz. Der Zähler dreht nur die Ziffer, die sich geändert hat.
Autoplay
autoplay ist standardmäßig aus und bleibt bei reduzierter Bewegung aus. Es pausiert bei Hover, Tastaturfokus, Touch, Drag, einem verborgenen Tab oder wenn es aus dem Sichtbereich gescrollt wird, und der aktive Punkt füllt sich, während der Timer läuft.
Thumbnails
<CarouselThumbnails /> folgt dem Haupt-Carousel und scrollt, um das aktive Thumbnail im Blick zu halten.
Vertikal
orientation="vertical" braucht eine Höhe auf <CarouselContent />. Die Buttons wandern nach oben und unten.
Kontrolliert
Übergib index und onIndexChange. Wischen aktualisiert deinen State, und dein State scrollt das Carousel.
Zurückspulen und Startindex
rewind schickt Next auf der letzten Folie zurück zur ersten. defaultIndex öffnet auf einer Folie ohne Scroll-Animation.
Links und fokussierbarer Inhalt
Ein Link, den du mit der Maus ziehst, scrollt, ohne geöffnet zu werden. Das Tabben zu einer Folie außerhalb des Bildschirms scrollt sie in den Sichtbereich.
Folien hinzufügen und entfernen
Punkte, Zähler und Buttons aktualisieren sich, wenn Folien hinzukommen und wegfallen.
Verschachtelt
Pfeiltasten, Ziehen und Punkte bewegen nur das Carousel, in dem du dich befindest.
Langer Inhalt und eine einzelne Folie
Text ohne Umbruchstelle wird in der Folie umgebrochen. Bei nur einer Folie werden die Punkte ausgeblendet, und die Buttons bleiben deaktiviert.
Rechts nach links
Folien beginnen rechts, die Pfeile kehren sich um, die Taste Pfeil links geht vorwärts, und die Punkte füllen sich von rechts.
Die Tasten funktionieren, solange der Fokus irgendwo im Carousel liegt, außer in Textfeldern und verschachtelten Carousels.
| Taste | Aktion |
|---|---|
| → | Nächste Folie. Vorherige in Rechts-nach-links-Layouts. ↓ in vertikalen Carousels. |
| ← | Vorherige Folie. Nächste in Rechts-nach-links-Layouts. ↑ in vertikalen Carousels. |
| Tab | Geht durch die Buttons, den aktiven Punkt und den Inhalt der Folien und scrollt Folien außerhalb des Bildschirms in den Sichtbereich. |
| EnterSpace | Aktiviert den fokussierten Button, Punkt oder das fokussierte Thumbnail. |
- Die Root ist eine
region, die als Carousel beschrieben ist. Gib ihr einaria-label. - Jedes Element ist eine
group, die als Folie beschrieben und mit ihrer Position beschriftet ist, etwa „3 of 5“. - Eine Live-Region mit polite-Priorität sagt die neue Folie nach der Navigation per Tastatur oder Button an und bleibt still, solange Autoplay läuft.
- Punkte und Thumbnails nutzen einen einzigen Tab-Stopp, und der Fokus folgt dem aktiven.
- Previous und Next bleiben im deaktivierten Zustand fokussierbar, sodass der Fokus an keinem Ende verloren geht.
| Prop | Typ | Standard |
|---|---|---|
orientation | "horizontal" | "vertical" | "horizontal" |
spacingAbstand zwischen den Folien. | "none" | "sm" | "default" | "lg" | "default" |
index | number | – |
defaultIndex | number | 0 |
onIndexChange | (index: number) => void | – |
rewindVon der letzten Folie zurück zur ersten springen. | boolean | false |
mouseDragDie Folien mit der Maus ziehen lassen. | boolean | true |
autoplayPer Timer weiterschalten. delay beträgt standardmäßig 5000 ms, mindestens 1000 ms. | boolean | { delay?: number } | false |
setApi | (api: CarouselApi) => void | – |
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribut | Beschreibung |
|---|---|
data-slot="carousel" | Das Root in CSS ansprechen. |
data-orientation | Die Ausrichtung. |
--carousel-spacing | Der Abstand zwischen den Folien, festgelegt durch spacing. |
| Prop | Typ | Standard |
|---|---|---|
classNameWird auf die Spur angewendet, die die Folien enthält. | string | – |
viewportClassNameWird auf den scrollenden Viewport angewendet. | string | – |
| Attribut | Beschreibung |
|---|---|
data-slot="carousel-content" | Der scrollende Viewport. |
data-slot="carousel-container" | Die Spur darin. |
data-scrollable | Vorhanden, wenn es mehr als eine Position gibt. |
data-dragging | Vorhanden, solange ein Maus-Drag läuft. |
| Prop | Typ | Standard |
|---|---|---|
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribut | Beschreibung |
|---|---|
data-slot="carousel-item" | Setze basis-*, um mehrere pro Ansicht zu zeigen. |
Beide rendern ein <Button /> und akzeptieren dessen Props. Sie sitzen außerhalb des Inhalts, lass also Platz um das Carousel.
| Prop | Typ | Standard |
|---|---|---|
variant | ButtonProps["variant"] | "outline" |
size | ButtonProps["size"] | "icon-sm" |
childrenFolgt der Ausrichtung und der Richtung. | ReactNode | Arrow icon |
| Attribut | Beschreibung |
|---|---|
data-slot="carousel-previous" | Beschriftet mit „Previous slide“. |
data-slot="carousel-next" | Beschriftet mit „Next slide“. |
data-disabled | An beiden Enden vorhanden. Der Button bleibt fokussierbar. |
| Prop | Typ | Standard |
|---|---|---|
aria-label | string | "Choose slide" |
| Attribut | Beschreibung |
|---|---|
data-slot="carousel-dots" | Die Gruppe der Punkte. Bei nur einer Position ausgeblendet. |
data-slot="carousel-dot" | Jeder Punkt. Der aktive hat aria-current. |
--dot-active | 0 bis 1, wie aktiv ein Punkt beim Scrollen ist. |
| Attribut | Beschreibung |
|---|---|
data-slot="carousel-counter" | Zeigt die aktuelle Position über der Gesamtzahl mit einer rollenden Ziffer. |
| Prop | Typ | Standard |
|---|---|---|
variant | ButtonProps["variant"] | "ghost" |
size | ButtonProps["size"] | "icon-sm" |
| Attribut | Beschreibung |
|---|---|
data-slot="carousel-autoplay-toggle" | Beschriftet mit „Pause slideshow“ oder „Play slideshow“. |
| Prop | Typ | Standard |
|---|---|---|
aria-label | string | "Slides" |
| Attribut | Beschreibung |
|---|---|
data-slot="carousel-thumbnails" | Der scrollende Streifen. |
| Prop | Typ | Standard |
|---|---|---|
indexDie Folie, die sie öffnet. Standardmäßig ihre Position im Streifen. | number | – |
render | ReactElement | (props, state) => ReactElement | <button> |
| Attribut | Beschreibung |
|---|---|
data-slot="carousel-thumbnail" | Thumbnails in CSS ansprechen. |
data-active | Vorhanden, solange die Folie im Sichtbereich ist. |
Wird über setApi und useCarousel() zurückgegeben. Übergib jump: true, um sich ohne Animation zu bewegen.
| Prop | Typ | Standard |
|---|---|---|
scrollPrev | (jump?: boolean) => void | – |
scrollNext | (jump?: boolean) => void | – |
scrollToScrollt zu einer Snap-Position. | (index: number, jump?: boolean) => void | – |
scrollToSlideScrollt zu der Position, die eine Folie zeigt. | (slideIndex: number, jump?: boolean) => void | – |
canScrollPrev | () => boolean | – |
canScrollNext | () => boolean | – |
selectedScrollSnap | () => number | – |
scrollSnapList | () => number[] | – |
slidesInView | () => number[] | – |
slideNodes | () => HTMLElement[] | – |
viewportNode | () => HTMLElement | null | – |
play | () => void | – |
stop | () => void | – |
isPlaying | () => boolean | – |
on / off | (event: "select" | "scroll" | "settle" | "reInit", listener) => CarouselApi | – |
Verwende es innerhalb von <Carousel />, um eigene Bedienelemente zu bauen. Gibt api, orientation, selectedIndex, snapCount, slideCount, slidesInView, canScrollPrev, canScrollNext, isPlaying sowie die Scroll- und Wiedergabemethoden zurück.
- ButtonButtons in allen Varianten und Größen, mit eingebautem Lade-, Erfolgs- und Fehlerablauf, der den Spinner bei schnellen Anfragen überspringt.
- Number flowAnimierte Zahlen, bei denen sich nur die geänderten Ziffern drehen, mit beliebigem Intl-Format und Locale.
- AccordionGestapelte Überschriften, die jeweils ein Panel aufklappen, mit einer Höhenbewegung, die sich mittendrin umkehren lässt, und Panels, die auch geschlossen durchsuchbar bleiben.
- Aspect ratioEine Box, die ihre Form behält, bevor Medien geladen sind, beim Laden schimmert, das Medium einblendet und bei einem Fehler auf einen Fallback zurückfällt.
- CollapsibleEin Panel, das mit einer Höhenbewegung ein- und ausgeblendet wird, die sich mittendrin umkehren lässt, ohne das Layout springen zu lassen.
- ResizablePanels, die du auseinanderziehen kannst, mit einem dezenten Trenner, der beim Hover aufwacht, Größen, die beim Zurücksetzen oder Einklappen gleiten, und Layouts, die erhalten bleiben.