Skip to content

テーマ

このライブラリは何が違うのか

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の差し替えで足りる場合は、そちらを優先してください(意味の一貫性が保たれます)。

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側で色の計算(コントラスト判定・スウォッチ生成・テストでの比較等)をそのまま書けるようにするための設計です。