Skip to Content
Button

Button

Button component is used to trigger actions.

#

Documentation

#

Usage

"use client"; import type { ComponentPropsWithRef } from "react"; import { Button } from "@optiaxiom/react"; export function App({ appearance = "default", size = "md", }: Pick<ComponentPropsWithRef<typeof Button>, "appearance" | "size">) { return ( <Button appearance={appearance} size={size}> Button </Button> ); }

#

Appearance

Use the appearance prop to select between the different button appearances.

import { Button, Group } from "@optiaxiom/react"; export function App() { return ( <Group flexDirection={["column", "row"]} gap="16"> <Button appearance="primary">Delete</Button> <Button appearance="danger">Delete</Button> <Button appearance="danger-outline">Delete</Button> <Button appearance="default">Delete</Button> <Button appearance="subtle">Delete</Button> </Group> ); }

#

Different sizes

Use the size prop to modify the size of the button.

import { Button, Group } from "@optiaxiom/react"; export function App() { return ( <Group flexDirection="column" gap="16"> <Group gap="16"> <Button size="sm">Small</Button> <Button size="md">Medium</Button> <Button size="lg">Large</Button> </Group> <Group gap="16"> <Button appearance="primary" size="sm"> Small </Button> <Button appearance="primary" size="md"> Medium </Button> <Button appearance="primary" size="lg"> Large </Button> </Group> </Group> ); }

#

Disabled state

Set the disabled prop to true to disable buttons and prevent any interactions.

Include visible text that explains why it’s disabled: a disabled button leaves the tab order, so keyboard and screen reader users can’t reach a tooltip on it.

Select an article to publish, duplicate or archive it.

import { Button, Group, Text } from "@optiaxiom/react"; export function App() { return ( <Group alignItems="start" flexDirection="column" gap="8"> <Group gap="16"> <Button appearance="primary" disabled> Publish </Button> <Button disabled>Duplicate</Button> <Button appearance="subtle" disabled> Archive </Button> </Group> <Text color="fg.secondary" fontSize="sm"> Select an article to publish, duplicate or archive it. </Text> </Group> ); }

#

Icons

Use the icon prop to add icons to a button.

#

Left and right icons

Icons are placed to the left by default but can be placed to the right using the iconPosition prop.

"use client"; import type { ComponentPropsWithRef } from "react"; import { IconTrashCan } from "@optiaxiom/icons"; import { Button } from "@optiaxiom/react"; export function App({ appearance = "default", iconPosition = "start", }: Pick<ComponentPropsWithRef<typeof Button>, "appearance" | "iconPosition">) { return ( <Button appearance={appearance} icon={<IconTrashCan />} iconPosition={iconPosition} > Delete </Button> ); }

#

Icon only button

Use the icon prop and omit the children to display an icon only button.

For accessibility please make sure to always include an aria-label prop for screen readers and optionally use tooltips to visually denote the button’s intent.

import { IconPen, IconTrashCan } from "@optiaxiom/icons"; import { Button, Group, Tooltip } from "@optiaxiom/react"; export function App() { return ( <Group gap="16"> <Button appearance="subtle" aria-label="Edit item" icon={<IconPen />} /> <Tooltip content="Remove item"> <Button appearance="subtle" aria-label="Remove item" icon={<IconTrashCan />} /> </Tooltip> </Group> ); }

#

Grouping buttons

Use the <ButtonGroup /> component to group related buttons together.

import { Button, ButtonGroup } from "@optiaxiom/react"; export function App() { return ( <ButtonGroup> <Button>First</Button> <Button>Second</Button> <Button>Third</Button> </ButtonGroup> ); }

Set asChild to true and wrap children in an <a> element to render buttons as links.

import { Button } from "@optiaxiom/react"; export function App() { return ( <Button asChild> <a href="./props">Sample Link</a> </Button> ); }

Make sure to prevent interactions manually using event.preventDefault() since <a> elements do not support the disabled prop.

Alternatively you can use our Link component which supports the disabled prop.

View report

The report is ready once the import finishes.

import { Button, Group, Link, Text } from "@optiaxiom/react"; export function App() { return ( <Group gap="8"> <Button asChild disabled> <Link href="./props">View report</Link> </Button> <Text color="fg.secondary" fontSize="sm"> The report is ready once the import finishes. </Text> </Group> ); }

#

Loading state

Set the loading prop to true to show a loading spinner and mark the button aria-busy.

Don’t also set disabled: a disabled button loses keyboard focus mid-action. The button stays clickable while loading, so ignore repeat clicks in your onClick handler if the action shouldn’t run twice.

"use client"; import { Button, Group, Switch, Tooltip } from "@optiaxiom/react"; import { useState } from "react"; export function App() { const [loading, setLoading] = useState(true); return ( <Group flexDirection="column" gap="16"> <Group gap="16"> <Tooltip content="Loading button demo"> <Button appearance="primary" loading={loading}> Primary </Button> </Tooltip> <Tooltip content="Loading button demo"> <Button loading={loading}>Default</Button> </Tooltip> <Tooltip content="Loading button demo"> <Button appearance="subtle" loading={loading}> Subtle </Button> </Tooltip> </Group> <Switch checked={loading} onCheckedChange={() => setLoading((loading) => !loading)} > Loading </Switch> </Group> ); }

#

File upload

We can create a simple file upload button by rendering the button as a label and including a visually hidden file input.

import { IconUpload } from "@optiaxiom/icons"; import { Button } from "@optiaxiom/react"; import { VisuallyHidden } from "@radix-ui/react-visually-hidden"; export function App() { return ( <Button asChild icon={<IconUpload />}> <label> Upload file <VisuallyHidden> <input type="file" /> </VisuallyHidden> </label> </Button> ); }

DropdownMenu

Display a dropdown menu.

SegmentedControl

Toggle buttons for switching between different values or views.

ToggleButton

ToggleButton component represents a button that can be toggled on or off.

#

Props

#

Button

import { Button } from "@optiaxiom/react"; // or import { Button } from "@optiaxiom/react/button";

Supports all Box props in addition to its own. Renders a <button> element.

Prop

addonAfter

Display content inside the button after children.

ReactNode

addonBefore

Display content inside the button before children.

ReactNode

appearance

Control the appearance by selecting between the different button types.

"default" | "danger" | "primary" | "subtle" | "danger-outline" | "default-opal" | "inverse" | "primary-opal"

asChild

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

false | true

children

ReactNode

className

string

disabled

Whether the button is disabled.

false | true

icon

Display an icon before or after the button content or omit children to only show the icon.

ReactNode

iconPosition

Control whether to show the icon before or after the button content.

"end" | "start"

Default: start

loading

Show a loading spinner and mark the button aria-busy. The button stays focusable and clickable: don’t also set disabled, which drops keyboard focus mid-action, and ignore repeat clicks in onClick if the action shouldn’t run twice. Nothing is announced when loading starts or ends, so tell screen reader users the outcome yourself, e.g. with a toast.

false | true

size

Control the size of the button.

"sm" | "md" | "lg"

square

Whether button should have square shape (an icon-only button with no label).

false | true

type

The default behavior of the button.

"button" | "reset" | "submit"

#

ButtonGroup

import { ButtonGroup } from "@optiaxiom/react"; // or import { ButtonGroup } from "@optiaxiom/react/button";

Supports all Box props in addition to its own. Renders a <div> element.

Prop

asChild

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read the Composition guide for more details.

false | true

children

ReactNode

className

string

gap

Set the element’s gap CSS property

ResponsiveValue<typeof styling.gap>

Default: 0

orientation

The orientation/layout of the buttons inside the group.

"horizontal" | "vertical"

Default: horizontal

#

Accessibility

#

Labels

  • Give an icon only button an aria-label, since it has no visible text. Button logs a console error when the label is missing.
  • A disabled button leaves the tab order, so keyboard and screen reader users can’t reach a tooltip on it. Explain why it’s disabled in visible text nearby.

#

Loading

loading marks the button aria-busy and keeps it focusable and clickable. Ignore repeat clicks in your handler when the action shouldn’t run twice.

#

Changelog

#

0.1.0

  • Added component
Last updated on