Button
Button は、ユーザーのアクションを起動するための基本コンポーネントです。 variant(見た目の役割)と size(高さ)の 2 軸を cva で組み合わせて表現します。標準の ButtonHTMLAttributes をすべて受け取るため、 onClick、type、disabled などはそのまま使えます。
import { Button } from "@willink-labs/react";
<Button variant="outline" size="sm" onClick={handleSave}>
Save
</Button>variant
ボタンの視覚的な役割を選びます。デフォルトは default です。1 画面の中で主要アクション(default)は 1 つに絞り、副次的なアクションには outline / ghost / link を使い分けてください。
| variant | 用途 |
|---|---|
default | 主要アクション。ブランド背景 + shadow + hover を持つ塗りつぶしボタン。 1 つの文脈につき 1 つに絞る。 |
outline | 副次アクション。border + 背景を持ち、主要ボタンと並べても主張しすぎない。 |
ghost | テキストのみ(hover 時のみ背景)。ツールバーや密度の高い UI での控えめなアクション。 |
link | 下線付きの text-brand テキスト。インラインのナビゲーション的なアクション。 |
size
高さを選びます。デフォルトは md です。すべての size は rounded-full の pill 形状で統一されています。
| size | 高さ / タイポ | 用途 |
|---|---|---|
sm | h-8 / text-sm | 密度の高い UI、テーブル行内、ツールバーなどのコンパクトな文脈。 |
md | h-10 / text-base | 既定。フォームや一般的な画面のアクション。 |
lg | h-14 / text-base | ヒーローや CTA など、視認性とタップ領域を優先したい場面。 |
asChild で合成する
asChild を指定すると、Button は自前の <button> を描画せず、Radix の Slot を通して子要素にスタイルと挙動を合成します。Next の <Link> や <a> をボタンの見た目で描画したいときに使います。
import Link from "next/link";
import { Button } from "@willink-labs/react";
// asChild にすると <button> を描画せず、子要素に
// Button のスタイルとセマンティクスを合成する
<Button asChild>
<Link href="/dashboard">ダッシュボードへ</Link>
</Button>子側がレンダリングを担うため、子は単一の要素である必要があります。 asChild を使わずに className だけ合成したい場合は、エクスポートされている buttonVariants を非 button 要素に直接適用できます。
import { buttonVariants } from "@willink-labs/react";
// 非 button 要素(<a> 等)に className として合成する
<a href="/docs" className={buttonVariants({ variant: "link" })}>
ドキュメント
</a>プロパティ
| prop | 型 | 説明 |
|---|---|---|
variant | "default" | "outline" | "ghost" | "link" | 視覚的な役割。既定は default。 |
size | "sm" | "md" | "lg" | 高さ。既定は md。 |
asChild | boolean | 子要素に Slot 経由で合成する。既定は false。 |
...ButtonHTMLAttributes | React.ButtonHTMLAttributes | onClick / type / disabled など標準の button 属性をすべて透過する。 |
アクセシビリティ
Button は標準の <button> セマンティクスをそのまま使います( role の上書きはしません)。キーボードフォーカス時は focus-visible:ring-2 で ring-ring のリングが ring-offset-2 付きで表示され、フォーカス位置が明確になります。 disabled のときは pointer-events-none と opacity-50 が適用され、操作不能であることが視覚・挙動の両面で伝わります。アイコンのみのボタンには aria-label を必ず付与してください。
実際の見た目とインタラクションは Storybook の Button で確認できます。次は アクセシビリティ で focus / disabled を含む a11y 契約の全体像を確認する。