Chuyển tới nội dung

Pro đang mở bán trước. Cài đặt mở từ tháng 1/2027. Xem Pro

Component

ResizablePanels

Các panel cạnh nhau hoặc chồng lên nhau, với một đường kẻ giữa hai panel mà người dùng kéo hoặc di chuyển bằng phím mũi tên để cho một panel thêm chỗ, như một danh sách cạnh phần chi tiết hoặc một truy vấn phía trên kết quả. Kích thước là phần trăm của nhóm.

  • npm: 1 trực tiếp, 2 tổng
  • registry: 2 trực tiếp, 2 tổng

Xem trước

Hộp thư đến

Tin nhắn

Props

  • orientation
  • label
  • withHandle
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "@/components/ui/resizable-panels"

<ResizablePanelGroup className="h-64 w-full rounded-container border border-border">
  <ResizablePanel defaultSize={35} minSize={20} className="p-md">
    <p className="text-sm text-text-secondary">Hộp thư đến</p>
  </ResizablePanel>
  <ResizableHandle label="Đổi kích thước hộp thư" />
  <ResizablePanel className="p-md">
    <p className="text-sm text-text-secondary">Tin nhắn</p>
  </ResizablePanel>
</ResizablePanelGroup>

Cách dùng

Khi nào dùng

  • Cho người dùng thêm chỗ cho một trong hai hoặc ba panel, như một danh sách cạnh phần chi tiết.
  • Chia một trình soạn thảo và kết quả của nó, hoặc một bảng và phần xem trước, theo kích thước người dùng chọn.

Khi nào không dùng

  • Cột điều hướng chính của ứng dụng. Dùng Sidebar.
  • Nội dung tràn ra khỏi một khung. Dùng ScrollArea.
  • Chuyển giữa các view ở cùng một chỗ. Dùng Tabs.

Biến thể

orientation

Đặt trên ResizablePanelGroup. horizontal đặt các panel cạnh nhau, vertical xếp chúng chồng lên nhau.

  • Hộp thư đến

    Tin nhắn

    horizontalmặc định

  • Truy vấn

    Kết quả

    vertical

import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "@/components/ui/resizable-panels"

<ResizablePanelGroup className="h-64 w-full rounded-container border border-border">
  <ResizablePanel defaultSize={35} minSize={20} className="p-md">
    <p className="text-sm text-text-secondary">Hộp thư đến</p>
  </ResizablePanel>
  <ResizableHandle label="Đổi kích thước hộp thư" />
  <ResizablePanel className="p-md">
    <p className="text-sm text-text-secondary">Tin nhắn</p>
  </ResizablePanel>
</ResizablePanelGroup>
<ResizablePanelGroup orientation="vertical" className="h-64 w-full rounded-container border border-border">
  <ResizablePanel defaultSize={35} minSize={20} className="p-md">
    <p className="text-sm text-text-secondary">Truy vấn</p>
  </ResizablePanel>
  <ResizableHandle label="Đổi kích thước hộp thư" />
  <ResizablePanel className="p-md">
    <p className="text-sm text-text-secondary">Kết quả</p>
  </ResizablePanel>
</ResizablePanelGroup>

Ví dụ

Danh sách và chi tiết

Hộp thư đến

Tin nhắn

import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "@/components/ui/resizable-panels"

<ResizablePanelGroup className="h-64 w-full rounded-container border border-border">
  <ResizablePanel defaultSize={35} minSize={20} className="p-md">
    <p className="text-sm text-text-secondary">Hộp thư đến</p>
  </ResizablePanel>
  <ResizableHandle label="Đổi kích thước hộp thư" />
  <ResizablePanel className="p-md">
    <p className="text-sm text-text-secondary">Tin nhắn</p>
  </ResizablePanel>
</ResizablePanelGroup>

Xếp chồng, có tay nắm

Nhóm dọc đặt các panel chồng lên nhau; tay nắm cho thấy chỗ cần nắm.

Truy vấn

Kết quả

import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "@/components/ui/resizable-panels"

<ResizablePanelGroup orientation="vertical" className="h-72 w-full rounded-container border border-border">
  <ResizablePanel defaultSize={60} className="p-md">
    <p className="text-sm text-text-secondary">Truy vấn</p>
  </ResizablePanel>
  <ResizableHandle label="Đổi kích thước phần kết quả" withHandle />
  <ResizablePanel className="p-md">
    <p className="text-sm text-text-secondary">Kết quả</p>
  </ResizablePanel>
</ResizablePanelGroup>

Ba panel

Thư mục

Tệp

Xem trước

import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "@/components/ui/resizable-panels"

<ResizablePanelGroup className="h-64 w-full rounded-container border border-border">
  <ResizablePanel defaultSize={25} minSize={15} className="p-md">
    <p className="text-sm text-text-secondary">Thư mục</p>
  </ResizablePanel>
  <ResizableHandle label="Đổi kích thước thư mục" />
  <ResizablePanel className="p-md">
    <p className="text-sm text-text-secondary">Tệp</p>
  </ResizablePanel>
  <ResizableHandle label="Đổi kích thước danh sách tệp" />
  <ResizablePanel defaultSize={30} minSize={20} className="p-md">
    <p className="text-sm text-text-secondary">Xem trước</p>
  </ResizablePanel>
</ResizablePanelGroup>

Nên và không nên

Nên

  • Đặt minSize để không panel nào nhỏ hơn mức nội dung cần.
  • Lưu bố cục từ onLayout và truyền lại làm defaultSize ở lần ghé sau.
  • Dưới md, xếp nội dung chồng lên nhau hoặc hiện từng panel một.

Không nên

  • Đừng dùng cho cột điều hướng chính của ứng dụng. Dùng Sidebar, có thể thu gọn.
  • Đừng đặt quá ba panel trong một nhóm.
  • Đừng đặt handle ở đầu hoặc cuối; handle nằm giữa hai panel.

Props

TênKiểuGiá trịMặc địnhMô tả
orientationenumhorizontal | verticalhorizontalĐặt trên ResizablePanelGroup. horizontal đặt các panel cạnh nhau, vertical xếp chúng chồng lên nhau.
onLayout(sizes: number[]) => void--Đặt trên ResizablePanelGroup. Được gọi với kích thước của mọi panel theo phần trăm sau khi kéo hoặc nhấn phím, để lưu bố cục.
keyboardStepnumber-5Đặt trên ResizablePanelGroup. Số phần trăm một handle di chuyển với mỗi lần nhấn phím mũi tên.
defaultSizenumber--Đặt trên ResizablePanel. Kích thước ban đầu theo phần trăm. Các panel không có nó chia phần còn lại.
minSizenumber-10Đặt trên ResizablePanel. Kích thước nhỏ nhất theo phần trăm.
maxSizenumber-90Đặt trên ResizablePanel. Kích thước lớn nhất theo phần trăm.
label bắt buộcstring--Đặt trên ResizableHandle. Tên của handle, như Đổi kích thước hộp thư.
withHandleboolean-falseĐặt trên ResizableHandle. Hiện một ô tay nắm nhỏ trên đường kẻ, cho handle khó tìm.

Slot

TênBắt buộcMô tả
panelskhôngChildren của ResizablePanelGroup: ResizablePanel và ResizableHandle, một handle giữa mỗi hai panel, là children trực tiếp.

Cấu tạo

PhầnMô tả
rootNhóm: một hàng hoặc cột flex lấp đầy phần chứa nó. Cho nó chiều cao khi nằm ngang.
panelMột panel. Giãn theo phần của nó và tự cuộn khi nội dung lớn hơn.
handleĐường kẻ 1px giữa hai panel, focus được và kéo được.
hitArea::before trong suốt ngang qua đường kẻ, rộng size-target-min.
gripÔ nhỏ tùy chọn trên đường kẻ cho thấy chỗ cần nắm.
iconIcon tay nắm trong ô, 16px.

Khả năng truy cập

Role: separator

PhímHành động
TabChuyển focus tới handle tiếp theo.
ArrowLeft / ArrowRightTrong nhóm nằm ngang, làm panel trước handle nhỏ hơn hoặc lớn hơn keyboardStep phần trăm.
ArrowUp / ArrowDownTrong nhóm dọc, làm panel phía trên handle nhỏ hơn hoặc lớn hơn keyboardStep phần trăm.
Home / EndLàm panel trước handle nhỏ nhất hoặc lớn nhất mà giới hạn cho phép.
  • Mỗi handle là một separator focus được, đặt tên bằng label, như EN `Resize sidebar`. Nó điều khiển panel trước nó (aria-controls).
  • aria-valuenow là kích thước của panel trước handle theo phần trăm; aria-valuemin và aria-valuemax là giới hạn của nó, có tính cả giới hạn của panel kế tiếp.
  • Nhóm nằm ngang có separator dọc (aria-orientation="vertical") và ngược lại.
  • Trên trang phải sang trái, phím mũi tên và thao tác kéo theo hướng đọc.
  • Đường kẻ 1px có vùng chạm rộng size-target-min, nên dễ nắm bằng ngón tay.

Cài đặt

npx werewolf-ui add resizable-panels

Chạy npx werewolf-ui init một lần trong app trước khi thêm component. Init cài token, thêm CSS import và luật cho agent. Add cài component này cùng các dependency và giữ nguyên theme của bạn. Xem Cài đặt để biết yêu cầu và cách cài qua registry.