UI componentsdocs/ui/components/actions.md

Actions

Trigger something: buttons and toolbars.

← Component reference

Button #

Buttons, including loading, confirming and unstyled variants.

Button #

Button (or link when href is set).

Interact with the example: callbacks show up here.
<Button onClick={() => {}}>
    Save changes
</Button>

Slots: root end label spinner start

PropTypeRequiredDefaultDescription
childrencontentButton label.
disabledbooleanDisables the button (also sets data-disabled).
endcontentTrailing content after the label (icon, badge, Kbd).
fullWidthbooleanStretch to the container's width.
hrefstringRender as a link.
iconOnlybooleanSquare icon-only button; pass aria-label.
loadingbooleanKeeps focus and width; blocks clicks and announces aria-busy.
onClick(e: MouseEvent) => voidCalled on click (not while disabled or loading).
size"sm" | "md" | "lg" | "xs""md"Height and padding.
startcontentLeading / trailing content (icons, badges, kbd).
targetstringLink target when href is set; _blank also adds rel="noopener noreferrer".
type"button" | "submit" | "reset""button"Native button type; submit submits the enclosing form.
variant"default" | "link" | "soft" | "warning" | "success" | "danger" | "solid" | "outline" | "ghost""solid"Visual style: solid (primary), default, soft, outline, ghost, link, or a tone (danger, warning, success).

ButtonVariant

type ButtonVariant = | "solid" | "default" | "soft" | "outline" | "ghost" | "link" | "danger" | "warning" | "success" | undefined;

LoadingButton #

Button that shows a spinner next to its label while busy.

<LoadingButton loading>
    Saving…
</LoadingButton>
PropTypeRequiredDefaultDescription
childrencontentButton label.
disabledbooleanDisables the button.
loadingbooleanShow a spinner and block clicks (width stays the same).
onClick(e: MouseEvent) => voidCalled when pressed (not while loading).
size"sm" | "md"Button size.
type"button" | "submit" | "reset"Native button type.
variant"danger" | "solid" | "ghost"Button style.

ConfirmButton #

Two-step confirm control (click → confirm).

Interact with the example: callbacks show up here.
<ConfirmButton label="Delete project" onConfirm={() => {}} />
PropTypeRequiredDefaultDescription
labelcontentyesButton label before confirming.
onConfirm() => voidyesCalled on the second click; the first click only arms the button.
confirmLabelcontent"Confirm?"Label on the second, confirming click.
size"sm" | "md"Button size.
variant"danger" | "solid" | "ghost"Button style.

UnstyledButton #

Button with browser chrome reset — bring your own look.

Interact with the example: callbacks show up here.
<UnstyledButton onClick={() => {}}>
    Plain clickable text
</UnstyledButton>
PropTypeRequiredDefaultDescription
childrencontentButton content (no built-in styling).
disabledbooleanDisables the button.
onClick(e: MouseEvent) => voidCalled when the button is pressed.
type"button" | "submit" | "reset""button"Native button type.

Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.

ButtonGroup #

Bootstrap-style button group.

Interact with the example: callbacks show up here.
<ButtonGroup label="Text alignment">
    <Button variant="outline" onClick={() => {}}>
        Left
    </Button>
    <Button variant="outline" onClick={() => {}}>
        Center
    </Button>
    <Button variant="outline" onClick={() => {}}>
        Right
    </Button>
</ButtonGroup>
PropTypeRequiredDefaultDescription
attachedbooleanJoin the buttons edge to edge; otherwise they sit apart with a gap.
childrencontentThe Buttons.
labelstringAccessible name for the group.

Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.

SplitButton #

Primary action + caret menu.

Pick a strategy from the caret menu.

function Example() {
    const strategy = signal("Merge");
    const merged = signal("");
    return (
        <Stack gap="0.5rem">
            <SplitButton
                label={strategy()}
                caretLabel="More merge options"
                onClick={() => merged.set(`${strategy()} done`)}
                menu={[
                    { label: "Merge", onSelect: () => strategy.set("Merge") },
                    { label: "Squash and merge", onSelect: () => strategy.set("Squash and merge") },
                    { label: "Rebase and merge", onSelect: () => strategy.set("Rebase and merge") },
                ]}
            />
            <Text muted>{merged() || "Pick a strategy from the caret menu."}</Text>
        </Stack>
    );
}

Slots: root caret main menu

PropTypeRequiredDefaultDescription
labelcontentyesMain button label.
menu{ label: string; onSelect: () => void; danger?: boolean; }[]yesAlternative actions in the caret menu: label, onSelect, optional danger.
caretLabelstring"More actions"Accessible name for the caret (default "More actions").
disabledbooleanDisables both halves.
onClick() => voidCalled when the main button is pressed.
size"sm" | "md"Button size.
variant"danger" | "solid" | "ghost"Button style.

Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.

Icon buttons #

Compact buttons with just an icon.

ActionIcon #

Icon-only button (label is its accessible name).

Interact with the example: callbacks show up here.
<ActionIcon label="Edit project" variant="subtle" onClick={() => {}}>
    <Icon name="edit" />
</ActionIcon>
PropTypeRequiredDefaultDescription
labelstringyesAccessible name (required: the button has no visible text).
childrencontentThe icon.
disabledbooleanDisables the button.
onClick(e: MouseEvent) => voidCalled when the button is pressed.
size"sm" | "md" | "lg""md"Button size.
variant"outline" | "subtle" | "filled""subtle"Button style.

CloseButton #

Dismiss control (×).

Interact with the example: callbacks show up here.
<CloseButton onClick={() => {}} />
PropTypeRequiredDefaultDescription
labelstring"Close"Accessible name of the button.
onClick(e: MouseEvent) => voidCalled when the button is clicked.
size"sm" | "md""md"Button size.

FloatingActionButton #

Pinned primary action. children replaces the icon.

Interact with the example: callbacks show up here.
<FloatingActionButton
    label="New project"
    icon="plus"
    onClick={() => {}}
/>

Slots: root icon

PropTypeRequiredDefaultDescription
labelstringyesAccessible name (and tooltip) of the button.
childrencontentCustom content instead of icon.
iconIconName"plus"Icon shown in the button.
onClick(e: MouseEvent) => voidCalled when the button is pressed.
position"bottom-left" | "bottom-right""bottom-right"Viewport corner to float in.

IconName — Material Design Icons path names used by <Icon />.

type IconName = | "check" | "x" | "plus" | "minus" | "search" | "user" | "users" | "settings" | "menu" | "home" | "heart" | "star" | "bell" | "mail" | "calendar" | "clock" | "edit" | "trash" | "copy" | "download" | "upload" | "link" | "external" | "info" | "warning" | "error" | "success" | "chevron-down" | "chevron-up" | "chevron-left" | "chevron-right" | "arrow-left" | "arrow-right" | "eye" | "eye-off" | "eye-outline" | "lock" | "unlock" | "filter" | "more" | "close" | "spinner" | "sun" | "moon" | "play" | "pause" | "refresh" | "share" | "image" | "file" | "folder" | "zap" | "phone" | "git" | "code";

Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.

Copy & share #

Copy a value or share a link.

CopyButton #

Copies value to the clipboard. Renders a {@link Button}; data-copied while confirming.

bun add @arachnejs/ui
<Group gap="0.5rem">
    <code>bun add @arachnejs/ui</code>
    <CopyButton value="bun add @arachnejs/ui" />
</Group>

Slots: root

PropTypeRequiredDefaultDescription
valuestringyesText written to the clipboard.
copiedLabelstring"Copied"Button text shown briefly after a successful copy.
labelstring"Copy"Button text before copying.
size"sm" | "md" | "lg" | "xs""sm"Button size.
variant"default" | "soft" | "solid" | "outline" | "ghost""ghost"Button style (as on Button).

CopyId #

Monospace id with a copy button.

prj_8f3k29dz
<CopyId value="prj_8f3k29dz" />

Slots: root button label value

PropTypeRequiredDefaultDescription
valuestringyesId shown and copied.
labelcontentLabel before the id.

ShareButton #

No description.

<ShareButton url="https://arachne.dev/ui" title="Arachne UI" />
PropTypeRequiredDefaultDescription
copiedLabelcontent"Link copied"Label shown after the link was copied (fallback path). Default "Link copied".
labelcontent"Share"Button label.
onClick() => boolean | voidCalled after sharing or copying; return false from onClick to handle sharing yourself.
onShared(method: "copy" | "share") => voidCalled after sharing, with how: the native sheet or a copied link.
size"sm" | "md"Button size.
textstringText passed to the share sheet.
titlestringTitle passed to the share sheet.
urlstringLink to share (default: the current page URL).

Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.

Toolbars #

Groups of related actions.

CommandBar #

WAI-ARIA toolbar for page-level actions: one Tab stop, arrow keys (and Home / End) move focus between its controls.

Interact with the example: callbacks show up here.
<CommandBar label="Selection actions">
    <Button size="sm" variant="ghost" onClick={() => {}}>
        Archive
    </Button>
    <Button size="sm" variant="ghost" onClick={() => {}}>
        Move
    </Button>
    <Button size="sm" variant="ghost" onClick={() => {}}>
        Delete
    </Button>
</CommandBar>
PropTypeRequiredDefaultDescription
childrencontentToolbar buttons (one Tab stop; arrows move between them).
labelstringAccessible name for the toolbar.
orientation"horizontal" | "vertical""horizontal"Layout, and which arrow keys move between buttons.

FloatingToolbar #

Floating toolbar for contextual actions (e.g. over a selection): a WAI-ARIA toolbar with one Tab stop and arrow-key focus.

Interact with the example: callbacks show up here.
<FloatingToolbar label="Text formatting">
    <Button size="sm" variant="ghost" onClick={() => {}}>
        Bold
    </Button>
    <Button size="sm" variant="ghost" onClick={() => {}}>
        Italic
    </Button>
    <Button size="sm" variant="ghost" onClick={() => {}}>
        Link
    </Button>
</FloatingToolbar>
PropTypeRequiredDefaultDescription
childrencontentToolbar buttons.
labelstringAccessible name for the toolbar.

BulkBar #

Selection action bar.

3 selected
function Example() {
    const selected = signal(3);
    return (
        <Show
            when={selected() > 0}
            fallback={
                <Button size="sm" variant="outline" onClick={() => selected.set(3)}>
                    Select 3 deploys
                </Button>
            }
        >
            <BulkBar count={selected()} onClear={() => selected.set(0)}>
                <Button size="sm" variant="outline" onClick={() => selected.set(0)}>
                    Archive
                </Button>
            </BulkBar>
        </Show>
    );
}

Slots: root actions clear count

PropTypeRequiredDefaultDescription
countnumberyesNumber of selected items.
childrencontentBulk actions for the selection.
countLabel(count: number) => unknownCustom count text (default N selected).
onClear() => voidShows a clear-selection button; called when it is pressed.

Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.