› ButtonA native button in four variants and two sizes, with a loading state.
import { Button } from "@meowerse/ui"; · source packages/ui/src/components/Button.tsx
variants and states save
primary — the one main action cancel
secondary more options
ghost delete account
danger copy all
small — 36 px drawn, 44 px hit area saving
loading save
disabled props prop type default required variant"primary" | "secondary" | "ghost" | "danger" the button's tone; use primary for the one main action per view. "secondary"no size"sm" | "md" the button's size; both keep a 44 px hit area. "md"no loadingboolean shows a spinner and disables the button. falseno
…plus all ButtonHTMLAttributes<HTMLButtonElement>.
css custom properties variable dark light --c-accent-fill#00ff82same --c-danger#ff6b63#b42318--c-fg#ededeb#1a1a1c--c-fg-muted#b3b3af#46464a--c-fg-subtle#8c8c88#5e5e5b--c-line#232326#cfcec8--c-line-strong#404044#a9a8a2--c-on-accent#06170dsame --c-on-danger#1a0605#ffffff--c-surface#151517#dfded9--control-height44pxsame --d-fast120mssame --disabled-opacity0.5same --easecubic-bezier(.16,1,.3,1)same --font-mono"JetBrains Mono", "JetBrains Mono Fallback", ui-monospace, "SFMono-Regular", Menlo, monospacesame --fs-20.8125remsame --fs-30.875remsame --r-m4pxsame --sp-28pxsame --sp-312pxsame --sp-416pxsame
Classes: .mw-btn. Set any of these variables on an ancestor (or wrap a subtree in .mw-theme--dark / .mw-theme--light) to restyle just that part of a page.
usage primary tsx copy
import { Button } from "@meowerse/ui";
<Button variant="primary">save</Button>
html (needs @meowerse/ui/tokens.css) copy
<button class="mw-btn mw-btn--primary mw-btn--md"><span>save</span></button>
secondary tsx copy
import { Button } from "@meowerse/ui";
<Button>cancel</Button>
html (needs @meowerse/ui/tokens.css) copy
<button class="mw-btn mw-btn--secondary mw-btn--md"><span>cancel</span></button>
ghost tsx copy
import { Button } from "@meowerse/ui";
<Button variant="ghost">more options</Button>
html (needs @meowerse/ui/tokens.css) copy
<button class="mw-btn mw-btn--ghost mw-btn--md"><span>more options</span></button>
danger tsx copy
import { Button } from "@meowerse/ui";
<Button variant="danger">delete account</Button>
html (needs @meowerse/ui/tokens.css) copy
<button class="mw-btn mw-btn--danger mw-btn--md"><span>delete account</span></button>
small tsx copy
import { Button } from "@meowerse/ui";
<Button size="sm">copy all</Button>
html (needs @meowerse/ui/tokens.css) copy
<button class="mw-btn mw-btn--secondary mw-btn--sm"><span>copy all</span></button>
loading tsx copy
import { Button } from "@meowerse/ui";
<Button variant="primary" loading>saving</Button>
disabled tsx copy
import { Button } from "@meowerse/ui";
<Button variant="primary" disabled>save</Button>
html (needs @meowerse/ui/tokens.css) copy
<button disabled="" class="mw-btn mw-btn--primary mw-btn--md"><span>save</span></button>
accessibility A native <button>: Enter and Space work, and focus shows the 2 px ring. loading disables it and adds a spinner; keep the label saying what is happening. It sets no default type (audit U-20): inside a form, set type="button" on buttons that must not submit. key does Tab focuses the button Enter or Space presses it
do and don't [ ok ] doUse one primary (green) button per view, for the main action. Explain a disabled button next to it. [fail] don'tDon't put two green buttons in one view. Don't enable a button and then refuse the click with "not ready".