テーマ
このライブラリは何が違うのか
Section titled “このライブラリは何が違うのか”多くのUIライブラリは「コンポーネントごとに color propsを渡す」か「CSSを丸ごと上書きする」かの二択になりがちです。web-ui は3層のトークンを1関数で再計算することで、ブランド1色を差し替えるだけで、ボタンの hover 色からダイアログの背景まで、意味的に正しい形で全部品に伝わる設計にしています。
import { createTheme } from "@hirasaki1985/web-ui";
const brandTheme = createTheme({ colors: { primary: { /* 50〜900の10段 */ } },});これだけで semantic.bg.brand / semantic.border.focus / components.button.primaryBg など、Primaryに連なるすべてのSemantic/Componentトークンが再計算されます。色の計算はここで一度も発生しません。10段スケールという十分な情報を最初から受け取り、各トークンはその中のどれかを指すだけだからです(ブランドを差し替える 参照)。
Primitive(colors.primary.500 等) ↓ buildSemanticColors(palette) が変換Semantic(semantic.bg.brand 等) ↓ buildComponentColors(palette) が変換Component(components.button.primaryBg 等)createTheme() は colors の上書きを受け取ると、buildSemanticColors / buildComponentColors を呼び直して Semantic / Component を再計算します(src/theme/CreateTheme.ts)。上書きしなかった部分は既定のテーマ(defaultTheme)の値をそのまま使います。
semantic / components を直接上書きすることもできますが、その場合は再計算結果の上から上書きが乗ります。Primitiveの差し替えで足りる場合は、そちらを優先してください(意味の一貫性が保たれます)。
useTheme() は常に実値を返す
Section titled “useTheme() は常に実値を返す”import styled from "styled-components";
const BrandText = styled.span<{ $color: string }>` color: ${(props) => props.$color};`;
const MyComponent = () => { const theme = useTheme(); return <BrandText $color={theme.semantic.text.brand}>...</BrandText>; // theme.semantic.text.brand は "#2563EB" のような実値の文字列};useTheme() は常に解決済みの実値(hexカラー等)を返します。CSSカスタムプロパティの参照文字列("var(--wui-text-brand)"のような値)を返すことはありません。JS側で色の計算(コントラスト判定・スウォッチ生成・テストでの比較等)をそのまま書けるようにするための設計です。
使い方の入り口
Section titled “使い方の入り口”- ブランド色だけ変えたい → ブランドを差し替える
- ダークモードに対応したい → ダークモード
- 1画面に複数ブランドを並べたい → 複数テーマの並置
- 実際に触って確認したい → テーマ Playground