Vai al contenuto

Ridimensionabile

Riquadri divisibili trascinabili per editor di codice, alberi di file e layout di dashboard — con lo stile neobrutalista caratterizzato da bordi e ombre.

import {
  ResizableHandle,
  ResizablePanel,

Il componente resizable divide una regione in pannelli che l’utente trascina per riproporzionare — in orizzontale o in verticale, annidabili, con maniglie utilizzabili da tastiera. Entrambe le varianti avvolgono react-resizable-panels di bvaughn, rifinite secondo la ricetta neobrutalista: bordi spessi, ombre nette e tipografia in grassetto.

Quando usarlo:

  • Editor di codice e layout in stile IDE — albero dei file, editor e pannelli di anteprima che l’utente dimensiona a piacere.
  • Viste master–detail — posta in arrivo e conversazione, tabella e ispettore del record, con il divisore dove lo vuole l’utente.
  • Dashboard e console — lascia che un pannello di log o un terminale sottragga altezza alla vista principale senza una finestra modale.

Informazioni

Il componente Resizable è basato su react-resizable-panels di bvaughn.

Installazione

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

Installa le seguenti dipendenze:

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

Copia e incolla il seguente codice nel tuo progetto.

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 }

Aggiorna i percorsi di importazione in base alla configurazione del tuo progetto.

Utilizzo

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

Composizione

Usa la seguente composizione per costruire un ResizablePanelGroup:

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

Esempi

Verticale

Usa orientation="vertical" per un ridimensionamento verticale.

import {
  ResizableHandle,
  ResizablePanel,

Maniglia

Usa la prop withHandle su ResizableHandle per mostrare una maniglia visibile.

import {
  ResizableHandle,
  ResizablePanel,

RTL

Per abilitare il supporto RTL in Neobrutalism, consulta la guida alla configurazione RTL.

"use client"

import * as React from "react"

Accessibilità

La maniglia segue il pattern WAI-ARIA Window Splitter: react-resizable-panels rende ogni maniglia come role="separator" focalizzabile, con aria-valuenow / aria-valuemin / aria-valuemax e aria-controls che punta al pannello che ridimensiona, così gli screen reader annunciano la posizione della divisione man mano che cambia.

Interazioni da tastiera:

TastoAzione
Tab / Shift + TabSposta il focus su una maniglia di ridimensionamento o via da essa
ArrowLeft / ArrowRightRidimensiona un gruppo orizzontale di un passo
ArrowUp / ArrowDownRidimensiona un gruppo verticale di un passo
HomeRiduce il pannello prima della maniglia alla sua dimensione minima
EndEspande il pannello prima della maniglia alla sua dimensione massima
EnterAlterna un pannello comprimibile tra chiuso ed espanso

Riferimento API

Consulta la documentazione react-resizable-panels.

Registro delle modifiche

2025-02-02 react-resizable-panels v4

Aggiornato a react-resizable-panels v4. Consulta le note di rilascio v4.0.0 per tutti i dettagli.

Se usi direttamente le primitive di react-resizable-panels, tieni presente le seguenti modifiche:

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