Action Bar
Action Bar is used to display a bottom action bar with a set of actions for selected items.
pnpm dlx dreamy add action-barAction Bar is a component that displays a set of actions at the bottom of the screen, typically used for bulk operations on selected items.
Show Action Bar
function ControlledActionBar() {
const { isOpen, onToggle, onClose } = useControllable();
return (
<>
<Switch size={"sm"} isChecked={isOpen} onChangeValue={onToggle}>
Show Action Bar
</Switch>
<ActionBar.Root isOpen={isOpen} onClose={onClose}>
<ActionBar.Content>
<ActionBar.SelectionTrigger>2 items selected</ActionBar.SelectionTrigger>
<ActionBar.Separator />
<Button size="sm" variant="outline" rightIcon={<LuTrash />}>
Delete
</Button>
<Button size="sm" variant="outline" rightIcon={<LuShare />}>
Share
</Button>
</ActionBar.Content>
</ActionBar.Root>
</>
);
}Add a close button to allow users to dismiss the action bar manually.
Show Action Bar
function ActionBarWithClose() {
const { isOpen, onToggle, onClose } = useControllable();
return (
<>
<Switch isChecked={isOpen} onChangeValue={onToggle} size={"sm"}>
Show Action Bar
</Switch>
<ActionBar.Root isOpen={isOpen} onClose={onClose}>
<ActionBar.Content>
<ActionBar.SelectionTrigger>5 items selected</ActionBar.SelectionTrigger>
<ActionBar.Separator />
<Button rightIcon={<LuSquarePlus />} size="sm" variant="outline">
Add to collection
</Button>
<Button color="error" rightIcon={<LuTrash />} size="sm">
Delete items
</Button>
<ActionBar.CloseTrigger />
</ActionBar.Content>
</ActionBar.Root>
</>
);
}You can include multiple action buttons to provide various operations.
Show Action Bar
function ActionBarMultiple() {
const { isOpen, onToggle, onClose } = useControllable();
return (
<>
<Switch isChecked={isOpen} onChangeValue={onToggle} size={"sm"}>
Show Action Bar
</Switch>
<ActionBar.Root isOpen={isOpen} onClose={onClose}>
<ActionBar.Content>
<ActionBar.SelectionTrigger>12 files selected</ActionBar.SelectionTrigger>
<ActionBar.Separator />
<Button rightIcon={<LuDownload />} size="sm" variant="outline">
Download
</Button>
<Button rightIcon={<LuShare />} size="sm" variant="outline">
Share
</Button>
<Button rightIcon={<LuFolderPlus />} size="sm" variant="outline">
Move to folder
</Button>
<ActionBar.Separator />
<Button color="error" rightIcon={<LuTrash />} size="sm">
Delete
</Button>
</ActionBar.Content>
</ActionBar.Root>
</>
);
}You can change the size of the action bar using the size prop.
Small
Show sm Action Bar
Medium
Show md Action Bar
Large
Show lg Action Bar
function ActionBarSizes({ size = "md" }: { size?: ActionBarVariantProps["size"] }) {
const { isOpen, onToggle, onClose } = useControllable();
return (
<>
<Switch isChecked={isOpen} onChangeValue={onToggle} size={"sm"}>
Show {size} Action Bar
</Switch>
<ActionBar.Root isOpen={isOpen} onClose={onClose} size={size}>
<ActionBar.Content>
<ActionBar.SelectionTrigger>2 selected</ActionBar.SelectionTrigger>
<ActionBar.Separator />
<Button color="error" size={size} variant="outline">
Delete
</Button>
<ActionBar.CloseTrigger size={size} />
</ActionBar.Content>
</ActionBar.Root>
</>
);
}A common use case is integrating the action bar with table selections.
| Name | Age | Gender | |
|---|---|---|---|
| John Doe | 20 | Male | |
| Jane Doe | 22 | Female | |
| Jim Doe | 25 | Male |
interface User {
id: number;
name: string;
age: number;
gender: string;
isSelected: boolean;
}
function ActionBarTable() {
const [users, setUsers] = useState<User[]>([
{ id: 1, name: "John Doe", age: 20, gender: "Male", isSelected: false },
{ id: 2, name: "Jane Doe", age: 22, gender: "Female", isSelected: false },
{ id: 3, name: "Jim Doe", age: 25, gender: "Male", isSelected: false }
]);
const { isOpen, onClose } = useControllable({
isOpen: users.some((user) => user.isSelected),
onClose: () => setUsers((prev) => prev.map((user) => ({ ...user, isSelected: false })))
});
const toggleSelection = useCallback((id: number) => {
setUsers((prev) =>
prev.map((user) => (user.id === id ? { ...user, isSelected: !user.isSelected } : user))
);
}, []);
const unselectAll = useCallback(() => {
setUsers((prev) => prev.map((user) => ({ ...user, isSelected: false })));
}, []);
const toggleSelectionAll = useCallback(() => {
setUsers((prev) =>
prev.map((user) => ({ ...user, isSelected: !prev.every((user) => user.isSelected) }))
);
}, []);
return (
<>
<Table.Root variant={"simple"} w="full" withBackground>
<Table.Table>
<Table.Header>
<Table.Row>
<Table.ColumnHeader w={"60px"}>
<Checkbox
isChecked={users.every((user) => user.isSelected)}
isIndeterminate={
users.some((user) => user.isSelected) &&
!users.every((user) => user.isSelected)
}
onChangeValue={toggleSelectionAll}
/>
</Table.ColumnHeader>
<Table.ColumnHeader>Name</Table.ColumnHeader>
<Table.ColumnHeader>Age</Table.ColumnHeader>
<Table.ColumnHeader>Gender</Table.ColumnHeader>
</Table.Row>
</Table.Header>
<Table.Body>
{users.map((user, index) => (
<Table.Row
/* apply border radiuses to first and last rows in the cells */
_first={{
"& > td:first-of-type": {
borderStartStartRadius: "l2"
},
"& > td:last-of-type": {
borderStartEndRadius: "l2"
}
}}
_hover={{
bg: "alpha.50"
}}
_last={{
"& > td:first-of-type": {
borderEndStartRadius: "l2"
},
"& > td:last-of-type": {
borderEndEndRadius: "l2"
}
}}
bg={user.isSelected ? "alpha.50" : "transparent"}
cursor={"pointer"}
key={index}
onClick={() => toggleSelection(user.id)}
>
<Table.Cell w={"60px"}>
<Checkbox
isChecked={user.isSelected}
onChangeValue={() => toggleSelection(user.id)}
/>
</Table.Cell>
<Table.Cell>{user.name}</Table.Cell>
<Table.Cell>{user.age}</Table.Cell>
<Table.Cell>{user.gender}</Table.Cell>
</Table.Row>
))}
</Table.Body>
</Table.Table>
</Table.Root>
<ActionBar.Root isOpen={isOpen} onClose={onClose}>
<ActionBar.Content>
<ActionBar.SelectionTrigger>
{users.filter((user) => user.isSelected).length} selected
</ActionBar.SelectionTrigger>
<ActionBar.Separator />
<Button size="sm" variant="outline">
Download
</Button>
<Button
color="error"
onClick={() => {
unselectAll();
onClose();
}}
rightIcon={<LuTrash />}
size="sm"
variant="outline"
>
Delete
</Button>
</ActionBar.Content>
</ActionBar.Root>
</>
);
}You can use the action bar in an uncontrolled mode with defaultIsOpen.
<ActionBar.Root defaultIsOpen onClose={() => console.log('closed')}>
<ActionBar.Positioner>
<ActionBar.Content>
<ActionBar.SelectionTrigger>
1 selected
</ActionBar.SelectionTrigger>
<ActionBar.Separator />
<Button size="sm" variant="outline">
Action
</Button>
<ActionBar.CloseTrigger>
<CloseButton size="sm" />
</ActionBar.CloseTrigger>
</ActionBar.Content>
</ActionBar.Positioner>
</ActionBar.Root>