Skip to content

Button

Button is the main way to trigger an action. The variants primary, secondary, tertiary and destructive are the Figma Button types; inverse is the dark button and link is an inline text action.

import { Button } from '@beyul/sulmu-ui'

Source · Figma

import { Button, Flex } from '@beyul/sulmu-ui'
export default function Example() {
return (
<Flex gap={3} align="center" wrap>
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="tertiary">Tertiary</Button>
<Button variant="destructive">Destructive</Button>
<Button variant="inverse">Inverse</Button>
<Button variant="link">Link</Button>
</Flex>
)
}
import { Button, Flex } from '@beyul/sulmu-ui'
export default function Example() {
return (
<Flex gap={3} align="center" wrap>
<Button size="sm">Small, 40px</Button>
<Button size="md">Medium, 44px</Button>
<Button size="lg">Large, 52px</Button>
</Flex>
)
}

Pass an icon component to leftIcon or rightIcon. Icons are 16px by default.

import { AddIcon, ArrowRightIcon, Button, Edit2Icon, Flex } from '@beyul/sulmu-ui'
export default function Example() {
return (
<Flex gap={3} align="center" wrap>
<Button leftIcon={<AddIcon />}>Add client</Button>
<Button variant="secondary" rightIcon={<ArrowRightIcon />}>
View more
</Button>
<Button variant="tertiary" leftIcon={<Edit2Icon />}>
Edit
</Button>
</Flex>
)
}

loading shows a spinner in place of the left icon, disables the button and sets aria-busy.

import { Button, Flex } from '@beyul/sulmu-ui'
export default function Example() {
return (
<Flex gap={3} align="center" wrap>
<Button loading>Saving</Button>
<Button variant="secondary" loading>
Saving
</Button>
<Button disabled>Disabled</Button>
<Button variant="secondary" disabled>
Disabled
</Button>
</Flex>
)
}
import { Button, Stack } from '@beyul/sulmu-ui'
export default function Example() {
return (
<Stack gap={3} style={{ maxWidth: 320 }}>
<Button fullWidth>Log In</Button>
<Button variant="secondary" fullWidth>
Create account
</Button>
</Stack>
)
}

asChild renders the child element with the button’s styles. Use it for an <a> or a router link.

import { Button } from '@beyul/sulmu-ui'
export default function Example() {
return (
<Button variant="secondary" asChild>
<a href="#accounts">Open accounts</a>
</Button>
)
}
PropTypeDefaultDescription
variant"link" | "primary" | "secondary" | "tertiary" | "destructive" | "inverse"primaryVisual style. Default: primary. primary, secondary, tertiary and destructive are the Figma Button types; inverse is the dark button; link is an inline text action.
size"sm" | "md" | "lg"mdsm 40px, md 44px, lg 52px. Default: md.
leftIconReactNode-Icon before the label. Pass an icon component, e.g. <Edit2Icon />.
rightIconReactNode-Icon after the label.
loadingboolean-Shows a spinner before the label, disables the button and marks it busy.
fullWidthboolean-Stretch to the width of the container.
disabledboolean-
asChildboolean-Use the provided child element as the default rendered element, combining their props and behavior.

Button also accepts every button attribute (onClick, type, form, aria-* and so on).

  • The default type is "button", so a Button inside a form does not submit it. Set type="submit" on the submit button.
  • With asChild, only the child is rendered: leftIcon, rightIcon and the loading spinner are not added, and type is not set.
  • A page should have one primary action. Use secondary or tertiary for the others, and destructive for actions that delete.
  • For a button with only an icon, use Icon Button: it requires an aria-label.