Button
Trigger an action or navigate. Renders as a native button, anchor, or input, or as any custom component via the component prop.
Examples
<Button> renders a native <button type="button"> by default, styled with the color prop for one of Chassis's context colors.
import { Button } from '@chassis-ui/react'
export const Example = () => {
return <Button color="primary">Save</Button>
}Colors
Set color to one of Chassis's context colors to change a button's background and foreground.
import { Button } from '@chassis-ui/react'
import { COLORS } from '../../utils'
export const Example = () => {
return (
<>
{COLORS.map((color) => (
<Button key={color} color={color}>
{color}
</Button>
))}
</>
)
}Color alone doesn't convey meaning to assistive technology. Pair a context color with visible
text describing the action, or add hidden text via the .visually-hidden class when the color
itself carries information.
Style variants
Layer variant on top of color to change a button's fill instead of its palette.
Outline
Set variant="outline" for a transparent background with a colored border and text — a
lower-emphasis alternative to a solid button in the same color.
import { Button } from '@chassis-ui/react'
import { COLORS } from '../../utils'
export const Example = () => {
return (
<>
{COLORS.map((color) => (
<Button key={color} color={color} variant="outline">
{color}
</Button>
))}
</>
)
}Some outline colors use a light foreground meant for a dark background — check contrast before using them on a light surface.
Smooth
Set variant="smooth" for a subdued, tinted background in the button's color, softer than the
default solid fill.
import { Button } from '@chassis-ui/react'
import { COLORS } from '../../utils'
export const Example = () => {
return (
<>
{COLORS.map((color) => (
<Button key={color} color={color} variant="smooth">
{color}
</Button>
))}
</>
)
}Link
Set variant="link" to make a button look and behave like a hyperlink while keeping its color
and click behavior — a lower-emphasis action inside a toolbar or form. variant="link" is a
button-specific style, not a context color: pass it alongside color, not instead of it.
import { Button } from '@chassis-ui/react'
import { COLORS } from '../../utils'
export const Example = () => {
return (
<>
{COLORS.map((color) => (
<Button key={color} color={color} variant="link">
{color}
</Button>
))}
</>
)
}Root element
Set component to render <Button> as a different element — "a" for navigation, "input" for
legacy form markup, or any custom component. href implies component="a" automatically, so
setting href alone is enough for a link button.
import { Button } from '@chassis-ui/react'
export const Example = () => {
return (
<>
<Button type="submit" color="primary">
Button
</Button>
<Button component="a" href="#" color="primary" role="button">
Link
</Button>
<Button component="input" type="button" color="primary" value="Input" />
<Button component="input" type="submit" color="primary" value="Submit" />
<Button component="input" type="reset" color="primary" value="Reset" />
</>
)
}A button rendered as <a> for something other than navigation — collapsing content, for example —
needs an explicit role="button"; Chassis doesn't add it automatically, since not every
component="a" usage is a non-navigation action. type only affects <button> and <input>; it
has no effect when rendered as <a>.
A plain tag other than "button", "a", or "input" (for example "span") gets keyboard
activation, focus handling, and role="button" synthesized automatically, matching native button
behavior. A component reference (for example a router's Link) doesn't: it's trusted to bring its
own semantics, since stamping role="button" onto the <a> it renders would be wrong.
Router links with asChild
To render a router's link component with button styling, pass it as the child with asChild,
instead of passing it by reference to component. The button's classes, props and ref are merged
onto the child element, and the router link still handles navigation:
import Link from 'next/link'
import { Button } from '@chassis-ui/react/button'
<Button asChild variant="outline">
<Link href="/login">Log in</Link>
</Button>A disabled button treats the child as it treats component="a": the link gets
aria-disabled="true" and tabindex="-1", and its click is blocked.
This form also works from a React Server Component. component={Link} there fails to build with
"Functions cannot be passed directly to Client Components", because a component reference is a
function and can't cross the server-to-client boundary. A JSX element can. See
Server-side rendering.
Sizes
Set size to "sm" or "lg" to adjust a button's padding and font size; the default
renders at md size.
import { Button } from '@chassis-ui/react'
export const Example = () => {
return (
<>
<Button color="primary" size="sm">
Small
</Button>
<Button color="primary">Medium</Button>
<Button color="primary" size="lg">
Large
</Button>
</>
)
}Pressed state
Set pressed to mark a toggle-style button as active — e.g. a formatting toolbar button that
stays highlighted while its feature is on. It applies the .active class and sets aria-pressed,
so assistive technology announces "button, pressed" instead of treating the button as a navigation
link. A button that is a link (href, or an <a> as component or the asChild element) gets the
class alone: a link has no pressed state to announce. Give it role="button" if it acts as a
toggle, and it takes aria-pressed too.
import { useState } from 'react'
import { Button } from '@chassis-ui/react'
export const Example = () => {
const [pressed, setPressed] = useState(false)
return (
<Button color="primary" pressed={pressed} onClick={() => setPressed(!pressed)}>
Bold
</Button>
)
}Disabled state
Set disabled to make a button non-interactive. A native <button> or <input> uses the real
disabled attribute, which blocks keyboard and pointer interaction on its own.
import { Button } from '@chassis-ui/react'
export const Example = () => {
return (
<Button color="primary" size="lg" disabled>
Button
</Button>
)
}<a> has no disabled attribute, so a disabled link button sets aria-disabled="true" and
tabindex="-1" instead, and blocks its own click handler and navigation.
import { Button } from '@chassis-ui/react'
export const Example = () => {
return (
<Button component="a" href="#" color="secondary" size="lg" disabled>
Link
</Button>
)
}Scope
No automatic role="button" on non-navigation links. Rendering <Button> with
component="a" for an action rather than navigation (see Root element) still
needs an explicit role="button" — Chassis can't distinguish the two cases from href alone.
API
Button
| Prop | Type | Default |
|---|---|---|
asChild? | boolean | — |
Render the single child element in place of this component's own element, with this
component's classes, props and ref merged onto it: <Button asChild><Link href="/login">Log
in</Link></Button>. The alternative to component for React Server Components — an element
can be passed from the server to this package's client components, a component reference
(component={Link}) can't. | ||
className? | string | — |
| A string of all className you want applied to the base component. | ||
color? | ContextColor | — |
| Sets the color of the component to one of Chassis context colors. | ||
component? | ElementType | — |
| Component used for the root node. Either a string to use a HTML element or a component. | ||
disabled? | boolean | — |
| Toggle the disabled state for the component. | ||
href? | string | — |
| The href attribute specifies the URL of the page the link goes to. | ||
onClick? | MouseEventHandler<HTMLAnchorElement | HTMLButtonElement | HTMLInputElement> | — |
Fires on click. Typed for every element component can actually render (button, a,
input, or a custom component), rather than narrowed to HTMLButtonElement alone. | ||
pressed? | boolean | — |
Marks the button as pressed for toggle-style usage (e.g. a formatting toolbar button).
Applies the .active class and sets aria-pressed so assistive technology announces
"button, pressed" rather than treating the button as a navigation link. A link (href, or
an <a> as component or the asChild element) has no pressed state to announce: it gets
the class alone, unless you give it role="button". | ||
ref? | any | — |
shape? | Shapes | — |
| Select the shape of the component. | ||
size? | "sm" | "lg" | — |
| Size the component sm or lg. | ||
type? | "button" | "submit" | "reset" | — |
Specifies the type of button. Always specify the type attribute for the <button> element.
Different browsers may use different default types for the <button> element. | ||
variant? | "link" | "basic" | "outline" | "smooth" | — |
Set the button style variant. Same as ContextStyle, but solid (the unmodified default
look) doesn't apply as a class, and link — button-specific, not a context color — makes
the button look and behave like a hyperlink while keeping its color. | ||