Resizable
Resizable is accessible resizable panel groups and layouts with keyboard support.
<Resizable.Root h="md" borderWidth="1px">
<Resizable.Item display="center">One</Resizable.Item>
<Resizable.Trigger />
<Resizable.Item display="center">Two</Resizable.Item>
</Resizable.Root>
Usage
import { Resizable } from "@yamada-ui/react"
import { Resizable } from "@/components/ui"
import { Resizable } from "@workspaces/ui"
<Resizable.Root>
<Resizable.Item />
<Resizable.Trigger />
</Resizable.Root>
Change Variants
<VStack>
<For each={["border", "spacer"]}>
{(variant) => (
<Resizable.Root
key={variant}
variant={variant}
h="md"
borderWidth={variant === "border" ? "1px" : undefined}
>
<Resizable.Item
display="center"
borderWidth={variant === "spacer" ? "1px" : undefined}
>
{toTitleCase(variant)}
</Resizable.Item>
<Resizable.Trigger />
<Resizable.Item
display="center"
borderWidth={variant === "spacer" ? "1px" : undefined}
>
Two
</Resizable.Item>
</Resizable.Root>
)}
</For>
</VStack>
Change Color Scheme
<VStack>
<For each={["success", "warning"]}>
{(colorScheme) => (
<Resizable.Root
key={colorScheme}
variant="spacer"
colorScheme={colorScheme}
h="md"
>
<Resizable.Item display="center" borderWidth="1px">
One
</Resizable.Item>
<Resizable.Trigger />
<Resizable.Item display="center" borderWidth="1px">
Two
</Resizable.Item>
</Resizable.Root>
)}
</For>
</VStack>
Change Orientation
To change the orientation, set orientation to either "horizontal" or "vertical". By default, "horizontal" is set.
<VStack>
<For each={["horizontal", "vertical"]}>
{(orientation) => (
<Resizable.Root
key={orientation}
orientation={orientation}
h="md"
borderWidth="1px"
>
<Resizable.Item display="center">One</Resizable.Item>
<Resizable.Trigger />
<Resizable.Item display="center">Two</Resizable.Item>
</Resizable.Root>
)}
</For>
</VStack>
Use Default Size
To set the default size, set a string or number for defaultSize in Resizable.Item.
<Resizable.Root h="md" borderWidth="1px">
<Resizable.Item display="center" defaultSize="30%">
One
</Resizable.Item>
<Resizable.Trigger />
<Resizable.Item display="center">Two</Resizable.Item>
</Resizable.Root>
Use Min and Max Size
To set the minimum and maximum sizes, set a string or number for minSize and maxSize in Resizable.Item.
<Resizable.Root h="md" borderWidth="1px">
<Resizable.Item display="center" minSize="30%" maxSize="70%">
One
</Resizable.Item>
<Resizable.Trigger />
<Resizable.Item display="center">Two</Resizable.Item>
</Resizable.Root>
Collapsible
To make an item collapsible, set collapsible to true.
Specify the string or number before collapsing with minSize, and the string or number when collapsed with collapsedSize.
<VStack>
<Resizable.Root h="md" borderWidth="1px">
<Resizable.Item
display="center"
collapsedSize="15%"
collapsible
defaultSize="30%"
minSize="30%"
maxSize="50%"
>
One
</Resizable.Item>
<Resizable.Trigger />
<Resizable.Item display="center">Two</Resizable.Item>
</Resizable.Root>
<Resizable.Root orientation="vertical" h="md" borderWidth="1px">
<Resizable.Item
display="center"
collapsedSize="15%"
collapsible
defaultSize="30%"
minSize="30%"
maxSize="50%"
>
One
</Resizable.Item>
<Resizable.Trigger />
<Resizable.Item display="center">Two</Resizable.Item>
</Resizable.Root>
</VStack>
Add Icons
To add icons, set a ReactNode to the icon of Resizable.Trigger.
<VStack>
<Resizable.Root h="md" borderWidth="1px">
<Resizable.Item display="center">One</Resizable.Item>
<Resizable.Trigger icon={<GripVerticalIcon />} />
<Resizable.Item display="center">Two</Resizable.Item>
</Resizable.Root>
<Resizable.Root variant="spacer" h="md" orientation="vertical">
<Resizable.Item display="center" borderWidth="1px">
One
</Resizable.Item>
<Resizable.Trigger icon={<GripVerticalIcon />} />
<Resizable.Item display="center" borderWidth="1px">
Two
</Resizable.Item>
</Resizable.Root>
</VStack>
Nested Structure
<VStack>
<Resizable.Root h="md" borderWidth="1px">
<Resizable.Item display="center">Left</Resizable.Item>
<Resizable.Trigger />
<Resizable.Item>
<Resizable.Root orientation="vertical">
<Resizable.Item display="center">Top</Resizable.Item>
<Resizable.Trigger />
<Resizable.Item display="center">Bottom</Resizable.Item>
</Resizable.Root>
</Resizable.Item>
</Resizable.Root>
<Resizable.Root orientation="vertical" h="md" borderWidth="1px">
<Resizable.Item display="center">Top</Resizable.Item>
<Resizable.Trigger />
<Resizable.Item>
<Resizable.Root>
<Resizable.Item display="center">Left</Resizable.Item>
<Resizable.Trigger />
<Resizable.Item display="center">Right</Resizable.Item>
</Resizable.Root>
</Resizable.Item>
</Resizable.Root>
</VStack>
Disable
To disable, set disabled to true.
<Resizable.Root disabled h="md" borderWidth="1px">
<Resizable.Item display="center">One</Resizable.Item>
<Resizable.Trigger />
<Resizable.Item display="center">Two</Resizable.Item>
<Resizable.Trigger />
<Resizable.Item display="center">Three</Resizable.Item>
</Resizable.Root>
<Resizable.Root h="md" borderWidth="1px">
<Resizable.Item display="center">One</Resizable.Item>
<Resizable.Trigger disabled />
<Resizable.Item display="center">Two</Resizable.Item>
<Resizable.Trigger />
<Resizable.Item display="center">Three</Resizable.Item>
</Resizable.Root>
Handle Resize Events
<Resizable.Root
h="md"
borderWidth="1px"
onLayoutChange={(layout) => {
console.log("layout change", layout)
}}
onLayoutChanged={(layout) => {
console.log("layout changed", layout)
}}
>
<Resizable.Item
display="center"
onResize={(panelSize, id, prevPanelSize) => {
console.log("item resize", panelSize, id, prevPanelSize)
}}
>
One
</Resizable.Item>
<Resizable.Trigger />
<Resizable.Item display="center">Two</Resizable.Item>
</Resizable.Root>
"use client" to the top of the file.Save Values to Local Storage or Cookies
To save values to local storage or Cookies, use Resizable.useLayout.
id to Resizable.Item to associate each saved value with the Resizable.Item.const storage: Resizable.Storage = useMemo(
() => ({
getItem: (key) => {
if (!createdDom()) return null
const match = document.cookie.match(new RegExp(`(^| )${key}=([^;]+)`))
return match ? (match[2] ?? null) : null
},
setItem: (key, value) => {
if (!createdDom()) return
document.cookie = `${key}=${value}; max-age=31536000; path=/`
},
}),
[],
)
const { defaultLayout, onLayoutChanged } = Resizable.useLayout({
id: "persistence",
storage,
})
return (
<Resizable.Root
borderWidth="1px"
defaultLayout={defaultLayout}
h="md"
rounded="l2"
onLayoutChanged={onLayoutChanged}
>
<Resizable.Item id="one" display="center">
One
</Resizable.Item>
<Resizable.Trigger />
<Resizable.Item id="two" display="center">
Two
</Resizable.Item>
</Resizable.Root>
)
"use client" to the top of the file.To use local storage, set localStorage to storage.
const { defaultLayout, onLayoutChanged } = Resizable.useLayout({
id: "persistence",
storage: localStorage,
})
Control
const controlRef = useRef<Resizable.ItemControl>(null)
return (
<>
<Wrap gap="md">
<Button onClick={() => controlRef.current?.collapse()}>
Collapse "one"
</Button>
<Button onClick={() => controlRef.current?.expand()}>Expand "one"</Button>
<Button onClick={() => controlRef.current?.resize("30%")}>
Resize "one" to 30
</Button>
<Button onClick={() => controlRef.current?.resize("50%")}>
Resize "one" to 50
</Button>
</Wrap>
<Resizable.Root borderWidth="1px" h="md" rounded="l2">
<Resizable.Item
collapsedSize="15%"
collapsible
controlRef={controlRef}
display="center"
maxSize="50%"
minSize="30%"
>
One
</Resizable.Item>
<Resizable.Trigger />
<Resizable.Item display="center">Two</Resizable.Item>
</Resizable.Root>
</>
)
"use client" to the top of the file.Props
Accessibility
The Resizable follows the WAI-ARIA - Window Splitter Pattern for accessibility.
Keyboard Navigation
| Key | Description | State |
|---|---|---|
ArrowRight | Increases the value based on the keyboardStep value. | orientation="horizontal" |
ArrowLeft | Decreases the value based on the keyboardStep value. | orientation="horizontal" |
ArrowUp | Increases the value based on the keyboardStep value. | orientation="vertical" |
ArrowDown | Decreases the value based on the keyboardStep value. | orientation="vertical" |
Enter | If expanded, collapses the pane; if collapsed, restores it to minSize. | collapsible="true" |
Home | Sets the value to minSize. | - |
End | Sets the value to maxSize. | - |
ARIA Roles and Attributes
| Component | Roles and Attributes | Usage |
|---|---|---|
Resizable.Item | id | Used to associate with Resizable.Trigger. |
Resizable.Trigger | role="separator" | Indicates that this is a separator. |
aria-controls | Sets the id of the associated Resizable.Item. | |
aria-orientation | Sets "horizontal" or "vertical" based on the orientation value. Default is "horizontal". | |
aria-valuemin | Sets the minSize value. Default is 0. | |
aria-valuemax | Sets the maxSize value. Default is 100. | |
aria-valuenow | Sets the current value. |