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 LocalStorage or Cookie
To save values to localStorage or Cookie, 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. | orientation="horizontal" |
ArrowLeft | Decreases the value. | orientation="horizontal" |
ArrowUp | Increases the value. | orientation="vertical" |
ArrowDown | Decreases the 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. | - |
F6 | Moves focus to the next separator. | - |
Shift + F6 | Moves focus to the previous separator. | - |
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 the separator direction. If orientation is "horizontal", it is set to "vertical", and vice versa. | |
aria-valuemin | Calculated from 0 to 100 based on the minSize value. Default is 0. | |
aria-valuemax | Calculated from 0 to 100 based on the maxSize value. Default is 100. | |
aria-valuenow | Sets the current value. | |
aria-disabled | Sets to true when disabled. |
Similar Components
Bleed
Bleed is a component used to extend elements beyond the boundaries of a container.
Box
Box is the most abstract component on which all other components are built. By default, it renders a div element.
Center
Center is a component that aligns the child elements in the center within the component.
Container
Container is a component used as a general division element. By default, it renders the section element.
Flex
Flex is a component that sets flex to Box. Also, convenient style shorthand is available.
Float
Float is a component used to fix elements to the edges of a container.
Grid
Grid is a component for managing grid layouts. It also comes with handy style shorthand.
Group
Group is a component that groups and attaches multiple elements together.