Skip to content
TopClass UI

Button

Five variants across six tones, rendered on the server with no JavaScript. Through render it becomes a real link that looks the same.

server - 0 KB

Button

server - 0 KB

Five variants across six tones, rendered on the server with no JavaScript. Through render it becomes a real link that looks the same.

Install

Try it

variant
tone
size
loading
fullWidth

The code

button.tsx
import { Button } from 'topclassui/button'

<Button>Save</Button>

loading blocks clicks and announces itself with aria-busy, but keeps full colour, so it never reads as disabled.

Every state

5 states

Import from the package

topclassui/button
import { Button } from 'topclassui/button'

Install once:npm i topclassui@beta zod

Examples

  • For anything the user does on the page: submit, save, confirm, open a dialog.
  • To go somewhere else, keep Button and pass render={<Link href="/docs" />}: it stays a real anchor, so middle-click and "open in new tab" still work.
  • loading keeps full colour and shows a spinner; a disabled button dims. Both block it, and a blocked render={<a href />} loses its href, so it cannot be followed.
  • A long label ends in an ellipsis and never pushes the page wider; fullWidth stretches the button to its container.
  • size="custom" emits no size classes, so your own className sets the height and padding.
variants
tones
sizes
with-icon
as-link
full-width
long-label
custom-size
skeleton
In Arabic, right to left

Props

The props of Button
PropTypeDefaultLimitsDescription
childrenReactNode--The label, and any icon beside it.
fullWidthbooleanfalse-Stretches the button to the width of its container.
loadingbooleanfalse-Shows a spinner, marks the button busy and blocks clicks.
renderReactElement--Render as another element, such as a framework link, and keep the button look.
sizexs | sm | md | lg | xl | custom"md"-The shared control scale; custom emits no size classes.
toneprimary | neutral | success | warning | danger | info"primary"-The meaning it signals, which picks its colour ramp.
variantsolid | soft | outline | ghost | link"solid"-How much weight the button carries on the page.

Keyboard and accessibility

The keyboard of Button
KeysWhat it does
TabMoves the focus to the button.
EnterActivates the button, or follows the link it renders.
SpaceActivates a native button.
  • A native <button type="button"> by default, named by its own text; an icon beside the text is hidden from screen readers.
  • While blocked, a native button carries the disabled attribute and leaves the tab order; any other element gets aria-disabled and tabindex="-1".
  • At least 24 by 24 px, 44 under a touch pointer, with a visible focus ring.

Right to left

Nothing to set: the padding and the gap are logical, so the icon and the text swap sides together, and a directional icon such as an arrow flips.

Server and client

Renders on the server and ships no JavaScript.

Files: index.tsx.

On the chip: server - 0 KB.