Zum Inhalt springen

Größenveränderbar

Verschiebbare geteilte Fenster für Code-Editoren, Dateibäume und Dashboard-Layouts – mit dem neobrutalistischen Design aus Rahmen und Schatten.

import {
  ResizableHandle,
  ResizablePanel,

Die Resizable-Komponente teilt einen Bereich in Panels, deren Größenverhältnis Nutzer per Ziehen anpassen – horizontal oder vertikal, verschachtelbar, mit per Tastatur bedienbaren Handles. Beide Varianten kapseln react-resizable-panels von bvaughn und folgen dem neobrutalistischen Rezept: dicke Rahmen, harte Schatten und kräftige Typografie.

Typische Anwendungsfälle:

  • Code-Editoren und IDE-artige Layouts – Dateibaum, Editor und Vorschau, die Nutzer nach eigenem Geschmack dimensionieren.
  • Master-Detail-Ansichten – Posteingang und Thread, Tabelle und Datensatz-Inspektor, mit dem Teiler genau dort, wo ihn die Nutzer haben wollen.
  • Dashboards und Konsolen – ein Log-Bereich oder Terminal darf der Hauptansicht Höhe abnehmen, ganz ohne Modal.

Über

Die Komponente Resizable basiert auf react-resizable-panels von bvaughn.

Installation

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

Installiere die folgenden Abhängigkeiten:

pnpm add react-resizable-panels
npm install react-resizable-panels
yarn add react-resizable-panels
bun add react-resizable-panels

Kopiere den folgenden Code und füge ihn in dein Projekt ein.

components/ui/resizable.tsx
"use client"

import * as ResizablePrimitive from "react-resizable-panels"

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

function ResizablePanelGroup({
  className,
  ...props
}: ResizablePrimitive.GroupProps) {
  return (
    <ResizablePrimitive.Group
      data-slot="resizable-panel-group"
      className={cn(
        "flex h-full w-full aria-[orientation=vertical]:flex-col",
        className
      )}
      {...props}
    />
  )
}

function ResizablePanel({ ...props }: ResizablePrimitive.PanelProps) {
  return <ResizablePrimitive.Panel data-slot="resizable-panel" {...props} />
}

function ResizableHandle({
  withHandle,
  className,
  ...props
}: ResizablePrimitive.SeparatorProps & {
  withHandle?: boolean
}) {
  return (
    <ResizablePrimitive.Separator
      data-slot="resizable-handle"
      className={cn(
        "relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary aria-[orientation=horizontal]:h-px aria-[orientation=horizontal]:w-full aria-[orientation=horizontal]:after:left-0 aria-[orientation=horizontal]:after:h-1 aria-[orientation=horizontal]:after:w-full aria-[orientation=horizontal]:after:translate-x-0 aria-[orientation=horizontal]:after:-translate-y-1/2 [&[aria-orientation=horizontal]>div]:rotate-90",
        className
      )}
      {...props}
    >
      {withHandle && (
        <div className="z-10 flex h-6 w-1 shrink-0 rounded-lg bg-border" />
      )}
    </ResizablePrimitive.Separator>
  )
}

export { ResizableHandle, ResizablePanel, ResizablePanelGroup }

Passe die Importpfade an dein Projekt-Setup an.

Verwendung

import {
  ResizableHandle,
  ResizablePanel,
  ResizablePanelGroup,
} from "@/components/ui/resizable"
<ResizablePanelGroup orientation="horizontal">
  <ResizablePanel>One</ResizablePanel>
  <ResizableHandle />
  <ResizablePanel>Two</ResizablePanel>
</ResizablePanelGroup>

Komposition

Verwende die folgende Komposition, um eine ResizablePanelGroup aufzubauen:

ResizablePanelGroup
├── ResizablePanel
├── ResizableHandle
└── ResizablePanel

Beispiele

Vertikal

Verwende orientation="vertical" für eine vertikale Größenänderung.

import {
  ResizableHandle,
  ResizablePanel,

Griff

Verwende die Prop withHandle an ResizableHandle, um einen sichtbaren Griff anzuzeigen.

import {
  ResizableHandle,
  ResizablePanel,

RTL

Um RTL-Unterstützung in Neobrutalism zu aktivieren, sieh dir die RTL-Konfigurationsanleitung an.

"use client"

import * as React from "react"

Barrierefreiheit

Das Handle folgt dem WAI-ARIA-Pattern „Window Splitter“: react-resizable-panels rendert jedes Handle als fokussierbares Element mit role="separator", aria-valuenow / aria-valuemin / aria-valuemax sowie einem aria-controls, das auf das jeweils veränderte Panel zeigt – Screenreader kündigen die Position der Teilung daher bei jeder Änderung an.

Tastaturinteraktionen:

TasteAktion
Tab / Shift + TabBewegt den Fokus auf ein Resize-Handle bzw. von ihm weg
ArrowLeft / ArrowRightPasst eine horizontale Gruppe um einen Schritt an
ArrowUp / ArrowDownPasst eine vertikale Gruppe um einen Schritt an
HomeVerkleinert das Panel vor dem Handle auf seine Minimalgröße
EndVergrößert das Panel vor dem Handle auf seine Maximalgröße
EnterSchaltet ein einklappbares Panel zwischen ein- und ausgeklappt um

API-Referenz

Sieh dir die Dokumentation von react-resizable-panels an.

Changelog

2025-02-02 react-resizable-panels v4

Aktualisiert auf react-resizable-panels v4. Alle Details findest du in den Release Notes zu v4.0.0.

Wenn du die Primitives von react-resizable-panels direkt verwendest, beachte die folgenden Änderungen:

v3v4
PanelGroupGroup
PanelResizeHandleSeparator
direction proporientation prop
defaultSize={50}defaultSize="50%"
onLayoutonLayoutChange
ImperativePanelHandlePanelImperativeHandle
ref prop on PanelpanelRef prop
data-panel-group-directionaria-orientation