Actions / Button
Button
The hero sticker. Peels on hover, squishes on press, springs back with an ink burst. Add a buddy for the one action that matters most on a screen.
Client componentWCAG AASince v0.1
import { Button, ButtonLink } from "@plop-ui/react";
<Button variant="ink" size="lg" buddy>Send report</Button>
<ButtonLink href="/start" size="lg" buddy="peek">Get started</ButtonLink> {/* buddy pops up on hover or focus */}
<Button shadow="stripes">Crayon shadow</Button> {/* or "solid", "outline", "none"; default "soft" */}
<Button variant="tomato">Delete</Button> {/* tomato shakes off a poof of dust, never confetti */}
<Button>Save changes</Button>
<Button variant="periwinkle">Add note</Button>
<Button variant="mint">Mark resolved</Button>
<Button variant="tomato" loading={cancelling}>Cancel dispatch</Button>
<Button variant="plain">Skip for now</Button>
// Navigates instead: same sticker, rendered as a link
<ButtonLink href="/docs" as={Link}>Get started</ButtonLink>Change every prop live in the playground.
Props
Button
| Prop | Type | Default | What it does |
|---|---|---|---|
| children required | ReactNode | — | Short label; lettered in Sketchpop Bold Italic, uppercase. |
| buddy | boolean | "peek" | none | A little character peeking over the top. Use it on the one action that matters most on a screen. `"peek"` keeps it hidden behind the sticker until hover or keyboard focus, then it pops up. |
| buddyMood | "success" | "error" | "stale" | "congrats" | "preview" | "thinking" | none | Which character the buddy is: `success` (Pip, default), `error` (Bix) for a Retry, `congrats` (Confetti) for a finish line… |
| burst | boolean | BurstStyle | readonly string[] | none | What flies out on click. `true` picks for the variant: confetti for most, a `"poof"` of dust (and a little head-shake) for `tomato`, the cancel/delete color. Or force `"confetti"` / `"poof"`, pass your own colors, or `false` for nothing. Skipped under reduced motion. |
| iconLeft | ReactNode | none | An icon drawn before the label. |
| loading | boolean | false | Shows a busy state, sets `aria-busy` and ignores clicks. |
| loadingLabel | string | "Loading" | Screen reader text while loading. |
| seed | string | number | React's useId() | Seeds the default tilt so it never changes between renders. |
| shadow | "soft" | "solid" | "stripes" | "outline" | "none" | PlopProvider's stickerShadow, which defaults to soft | The shadow under the sticker: `soft` (a flat, quiet offset), `solid` (ink), `stripes` (crayon hatching), `outline` or `none`. |
| size | "sm" | "md" | "lg" | md | Sticker size: `sm` for dense rows, `lg` for the one hero action. |
| tilt | number | a small seeded tilt; pass 0 to sit straight | Rotation in degrees. |
| variant | "ink" | "periwinkle" | "mint" | "tomato" | "mustard" | "plain" | ink | Spot color printed under the ink. |
Also takes every attribute of <button> (287 more, e.g. onClick, className, aria-*).
ButtonLink
| Prop | Type | Default | What it does |
|---|---|---|---|
| children required | ReactNode | — | — |
| href required | string | — | — |
| as | ElementType | a | Your router's link component, e.g. Next.js `Link`. |
| buddy | boolean | "peek" | none | See Button: `true` always shows the buddy, `"peek"` pops it up on hover or keyboard focus. |
| buddyMood | "success" | "error" | "stale" | "congrats" | "preview" | "thinking" | none | See Button. |
| burst | boolean | BurstStyle | readonly string[] | none | What flies out on click. `true` picks for the variant: confetti for most, a `"poof"` of dust (and a little head-shake) for `tomato`, the cancel/delete color. Or force `"confetti"` / `"poof"`, pass your own colors, or `false` for nothing. Skipped under reduced motion. |
| iconLeft | ReactNode | none | — |
| seed | string | number | React's useId() | Seeds the default tilt so it never changes between renders. |
| shadow | "soft" | "solid" | "stripes" | "outline" | "none" | PlopProvider's stickerShadow, which defaults to soft | The shadow under the sticker: `soft` (a flat, quiet offset), `solid` (ink), `stripes` (crayon hatching), `outline` or `none`. |
| size | "sm" | "md" | "lg" | md | Sticker size: `sm` for dense rows, `lg` for the one hero action. |
| tilt | number | a small seeded tilt; pass 0 to sit straight | Rotation in degrees. |
| variant | "ink" | "periwinkle" | "mint" | "tomato" | "mustard" | "plain" | ink | Spot color printed under the ink. |
Also takes every attribute of <a> (284 more, e.g. onClick, className, aria-*).
Use it well
DoGive the buddy to one action per screen, the one people came to do.
Don'tLine up several tomato buttons. Destructive stands out because it's rare.
Accessibility
- A native button element, so it works with any keyboard and screen reader.
- Space and Enter both show the press, and focus draws a dashed cut-here line.
- Text on every color passes WCAG AA through its contrast role.
- Reduced motion turns off the peel, boil and ink burst; the state change still shows.