Skip to main content

Button

import { Button } from '@jbpark/ui-kit';

<Button type="primary" onClick={() => console.log('clicked')}>
Click me
</Button>;

Props

PropTypeDefault
variant'solid' | 'outlined' | 'dashed' | 'filled' | 'text' | 'link' (plus the shadcn words below)'outlined'
type'primary' | 'default' | 'dashed' | 'text' | 'link'-
size'small' | 'middle' | 'large' (plus the shadcn words below)'middle'
shape'default' | 'circle' | 'round''default'
colorpreset color name (see below) | 'default' | 'primary' | 'danger''default'
iconReactNode-
loadingboolean | { icon: ReactNode }-
blockboolean-
dangerboolean-
disabledboolean-
htmlType'button' | 'submit' | 'reset''button'
renderReactElement | (props, state) => ReactElement-
nativeButtonbooleantrue
classNamestring-

type is syntactic sugar for a (color, variant) pair — it follows variant and color when those are provided, filling in only the axes you leave unset.

typeequivalent to
primarycolor="primary" variant="solid"
defaultcolor="default" variant="outlined"
dashedcolor="default" variant="dashed"
textcolor="default" variant="text"
linkcolor="primary" variant="link"

So <Button type="primary"> renders the same as <Button color="primary" variant="solid">, while <Button type="primary" variant="filled"> keeps the primary color and renders filled instead. danger overrides the resolved color either way.

shadcn's vocabulary

variant and size also accept shadcn's own words, so a snippet copied from the shadcn docs renders as the nearest thing on this library's scale instead of erroring. They are sugar in exactly the sense type is — each expands to a (color, variant) pair, and an explicit color still wins over the one the word implies.

shadcn variantequivalent to
defaultcolor="primary" variant="solid"
destructivecolor="danger" variant="solid"
outlinecolor="default" variant="outlined"
secondarycolor="default" variant="filled"
ghostcolor="default" variant="text"

link is shared: it is already one of this library's own variants and already renders what shadcn's link renders, so it is left alone.

shadcn sizerenders as
xs, sm, icon-xs, icon-smsmall
default, iconmiddle
lg, icon-lglarge

There is no separate xs step on this scale, so xs renders as small. The icon* sizes additionally force the icon-only (square, unpadded) treatment, which this component otherwise infers from icon being set with no children — so the shadcn idiom of passing the icon as children works too:

<Button size="icon">
<Trash />
</Button>
variant="default" and type="default" are opposites

shadcn's variant="default" is a filled primary button; antd's type="default" is a plain outlined one. They are different props, so nothing collides at runtime — but don't read one as the other.

Preset color names follow Tailwind's own palette names: blue, purple, cyan, green, fuchsia, pink, red, orange, yellow, indigo, lime, amber, in addition to default, primary, danger. Each resolves from the matching --color-* Tailwind theme variable, so a colour word renders the same hue on Button and Tag.

Use Base UI's render prop to compose Button with another component:

<Button render={<CustomButton />}>Save</Button>

The custom component must forward its ref and spread the received props. When rendering a non-button element, also pass nativeButton={false}. Native <button> attributes are forwarded.