mcpField
F
fluent2-design-system

fluent2-design-system

github.com/fefogarciaデザイン・UI277 回インストール37 週間前に更新
リポジトリ

fluent2-design-system について

fluent2-design-system は、@fluentui/react-components v9 を使う React 開発者向けの Fluent 2 リファレンススキルです。テーマ、トークンベースのスタイル、コンポーネント、レイアウト、アクセシビリティを扱います。

主な機能

  1. 01Fluent 2 と独自ブランドのテーマ
  2. 02Griffel のスタイルガイド
  3. 03デザイントークンの分類と使い方
  4. 04v9 のコンポーネントパターンと一覧
  5. 05レイアウト、タイポグラフィ、色の指針
  6. 06キーボードとハイコントラスト対応

活用シーン

  1. 01React アプリにライト、ダーク、ブランドテーマを設定
  2. 02デザイントークンを使ったコンポーネントのスタイル設定
  3. 03入力、ナビゲーション、フィードバックを含む画面の構築
  4. 04キーボード操作とハイコントラスト対応の確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/fefogarcia/approved-skills --skill fluent2-design-system

インストール後、Claude Code で/fluent2-design-systemを入力して読み込まれたか確認します。

同梱ファイルreferences/components.mdreferences/tokens.md

詳細

Fluent 2 デザインシステム

@fluentui/react-components(v9)を使用して、Microsoft の Fluent 2 デザインシステムに基づく本番環境品質のインターフェイスを構築します。

クイックスタート

すべての Fluent 2 React アプリでは、テーマを指定してコンポーネントツリーを囲む FluentProvider が必要です。

import {
  FluentProvider,
  webLightTheme,
  webDarkTheme,
  Button,
  tokens,
  makeStyles,
  mergeClasses,
} from "@fluentui/react-components";

export default function App() {
  return (
    <FluentProvider theme={webLightTheme}>
      <Button appearance="primary">Hello Fluent 2</Button>
    </FluentProvider>
  );
}

インストール:npm install @fluentui/react-components

コアアーキテクチャ

テーマ設定
  • 組み込みテーマ:webLightTheme、webDarkTheme、teamsLightTheme、teamsDarkTheme、teamsHighContrastTheme
  • カスタムブランディング:BrandVariants オブジェクト(キーは 10~160)を指定して、createLightTheme(brandRamp)/createDarkTheme(brandRamp) を使用します
  • ネスト:FluentProvider をネストして、サブツリーに異なるテーマを適用できます
  • テーマの値は、プロバイダー要素の CSS カスタムプロパティとして出力されます
Griffel によるスタイリング

makeStyles(@fluentui/react-components からインポート)を使用してください。トークンを使用したスタイリングでは、インラインスタイルや外部 CSS は使用しないでください。

const useStyles = makeStyles({
  root: {
    backgroundColor: tokens.colorNeutralBackground1,
    color: tokens.colorNeutralForeground1,
    display: "flex",
    gap: tokens.spacingHorizontalM,
    padding: tokens.spacingVerticalM,
  },
  active: {
    backgroundColor: tokens.colorBrandBackground,
    color: tokens.colorNeutralForegroundOnBrand,
  },
});

function MyComponent({ isActive }) {
  const styles = useStyles();
  return (
    <div className={mergeClasses(styles.root, isActive && styles.active)}>
      Content
    </div>
  );
}

重要なルール:

  • makeStyles はコンポーネントの外(モジュールスコープ)で定義します
  • クラスを組み合わせるには mergeClasses() を使用します。文字列を連結しないでください
  • 色、間隔、タイポグラフィ、角丸、影にはすべて tokens.* を使用します。16進数やpxの値を直接指定しないでください
  • CSS のショートハンド(border、borderRadius、padding など)はサポートされていません。shorthands.* ヘルパーまたはロングハンドプロパティを使用してください
  • 疑似セレクターにはネストしたオブジェクトを使用します:":hover": { color: tokens.colorBrandForeground1 }
  • メディアクエリーにはネストしたオブジェクトを使用します:"@media (min-width: 768px)": { flexDirection: "row" }
コンポーネントモデル

すべての v9 コンポーネントは、一貫したパターンに従います。

  • スロット:名前付きのサブパーツ(例:root、icon、content)で、プロパティまたは JSX を受け取ります
  • 外観のバリエーション:"primary"、"secondary"、"subtle"、"transparent"、"outline"
  • サイズのバリエーション:"small"、"medium"、"large"
  • 形状のバリエーション:"rounded"、"circular"、"square"

makeStyles/mergeClasses を使って作成した className で、コンポーネントのスタイルを上書きします。

デザイントークン

トークンは、デザインの意図とコードをつなぐものです。常に tokens.* を使用し、生の値を直接指定しないでください。

色、タイポグラフィ、間隔、エレベーション、線幅、角丸のトークン一覧については、 references/tokens.md を参照してください。

トークンカテゴリーの概要
カテゴリープレフィックス例
ニュートラルカラーcolorNeutral*tokens.colorNeutralBackground1
ブランドカラーcolorBrand*tokens.colorBrandBackground
ステータスカラーcolorPalette{Color}*tokens.colorPaletteRedForeground1
タイポグラフィfontFamily*、fontSize*、fontWeight*、lineHeight*tokens.fontSizeBase300
間隔spacingHorizontal*、spacingVertical*tokens.spacingHorizontalM
角丸borderRadius*tokens.borderRadiusMedium
線幅strokeWidth*tokens.strokeWidthThin
影shadow*tokens.shadow4
継続時間duration*tokens.durationNormal
イージングcurve*tokens.curveEasyEase
2層のトークンシステム
  1. グローバルトークン — コンテキストに依存しない生の値(例:colorBlue60、fontSize300)
  2. エイリアストークン — グローバルトークンに適用されるセマンティックな意味(例:colorBrandBackground → 青、colorNeutralForeground1 → 濃いグレー)

コードでは、tokens オブジェクトを介してエイリアストークンを使用します。

レイアウト

  • グリッド:CSS Grid/Flexbox を使用します。Fluent 2 v9 には Stack コンポーネントがありません
  • 間隔のスケール:基本単位は4pxです。値:XXS(2)、XS(4)、S(8)、M(12)、L(16)、XL(20)、XXL(24)、XXXL(32)
  • カラムグリッド:Web では12カラムのフレームワークが推奨されます。CSS Grid を使用してください
  • 配置:一貫した間隔を保つため、tokens.spacingHorizontal* と tokens.spacingVertical* を使用します

タイポグラフィ

  • プライマリ書体:Segoe UI(Web)、Segoe UI Variable(Windows)、SF Pro(macOS/iOS)、Roboto(Android)
  • フォントスタック:tokens.fontFamilyBase = Segoe UI → システムフォールバック → sans-serif
  • 等幅フォント:tokens.fontFamilyMonospace
  • テキストプリセット:プリセットバリアント(Caption1、Body1、Body1Strong、Subtitle1、Subtitle2、Title1、Title2、Title3、LargeTitle、Display)を指定して、<Text> コンポーネントを使用します
  • 配置:LTR では左揃えにします。Fluent は Griffel によって RTL を自動的に処理します

カラーシステム

3 つのパレットがあります。

  1. ニュートラル — サーフェス、テキスト、レイアウトに使用する黒、白、グレー
  2. ブランド — ブランドのアイデンティティを強調するアクセントカラー(Microsoft のデフォルトのブランドカラーは青)
  3. 共通/ステータス — 製品間で共通のカラー:赤(危険)、緑(成功)、黄(警告)、青(情報)

インタラクション状態:通常 → ホバー(より濃い色)→ 押下(最も濃い色)。フォーカス時は色を変えず、より太いストロークを追加します。

アクセシビリティ

  • すべてのコンポーネントに、ARIA ロール、キーボードナビゲーション(Tabster 経由)、フォーカス管理が含まれます
  • ハイコントラスト:teamsHighContrastTheme を使用するか、システムカラー(ButtonText、Highlight など)を使って @media (forced-colors: active) を処理します
  • フォーカスインジケーターはデフォルトで表示されます。削除しないでください
  • セマンティックトークンの組み合わせ(例:colorNeutralBackground1 上の colorNeutralForeground1)を使って、WCAG のコントラスト要件を満たしてください

コンポーネント一覧

使用上の注意を含む、カテゴリ別の全コンポーネント一覧については、 references/components.md を参照してください。

よく使われるコンポーネント

アクション:Button、CompoundButton、SplitButton、ToggleButton、MenuButton、Link 入力:Input、Textarea、Select、Combobox、Dropdown、Checkbox、RadioGroup、Switch、Slider、SpinButton、DatePicker、TimePicker レイアウト:Card、Divider、Drawer、Dialog、Popover、Tooltip データ表示:Table、DataGrid、Tree、Accordion、Badge、Avatar、AvatarGroup、Tag、Persona ナビゲーション:TabList、Breadcrumb、Nav(プレビュー) フィードバック:Toast、MessageBar、ProgressBar、Spinner、Skeleton サーフェス:Menu、Toolbar、Overflow

一般的なパターン

アプリシェルのレイアウト
const useStyles = makeStyles({
  app: {
    backgroundColor: tokens.colorNeutralBackground1,
    display: "grid",
    gridTemplateColumns: "1fr",
    gridTemplateRows: "auto 1fr auto",
    height: "100vh",
    width: "100%",
  },
  header: {
    borderBottom: `${tokens.strokeWidthThin} solid ${tokens.colorNeutralStroke1}`,
    paddingTop: tokens.spacingVerticalS,
    paddingBottom: tokens.spacingVerticalS,
    paddingLeft: tokens.spacingHorizontalM,
    paddingRight: tokens.spacingHorizontalM,
  },
  content: {
    display: "grid",
    gridTemplateColumns: "280px 1fr",
    overflow: "hidden",
  },
  nav: {
    borderRight: `${tokens.strokeWidthThin} solid ${tokens.colorNeutralStroke1}`,
    overflowY: "auto",
  },
  main: {
    overflowY: "auto",
    paddingLeft: tokens.spacingHorizontalL,
    paddingRight: tokens.spacingHorizontalL,
    paddingTop: tokens.spacingVerticalL,
    paddingBottom: tokens.spacingVerticalL,
  },
});
カスタムブランドテーマ
import { createLightTheme, createDarkTheme } from "@fluentui/react-components";

const myBrand = {
  10: "#020305", 20: "#111723", 30: "#16263D",
  40: "#193253", 50: "#1B3F6A", 60: "#1B4C82",
  70: "#18599B", 80: "#1267B4", 90: "#3174C2",
  100: "#4F82C8", 110: "#6790CF", 120: "#7F9ED5",
  130: "#96ADDC", 140: "#ADBCE3", 150: "#C4CBE9",
  160: "#DBDBF0",
};

const lightTheme = createLightTheme(myBrand);
const darkTheme = createDarkTheme(myBrand);
ダークモードの切り替え
function App() {
  const [isDark, setIsDark] = useState(false);
  return (
    <FluentProvider theme={isDark ? webDarkTheme : webLightTheme}>
      <Switch
        label="Dark mode"
        checked={isDark}
        onChange={(_, data) => setIsDark(data.checked)}
      />
    </FluentProvider>
  );
}

アンチパターン

  • ❌ 色のハードコード(color: "#333")— tokens.colorNeutralForeground1 を使用してください
  • ❌ makeStyles での CSS の短縮プロパティ(border: "1px solid red")— ロングハンドまたは shorthands.* を使用してください
  • ❌ classNames の文字列連結 — mergeClasses() を使用してください
  • ❌ トークンベースの値にインラインの style プロパティを使用する — tokens を指定した makeStyles を使用してください
  • ❌ v9 プロジェクトで @fluentui/react(v8)からインポートする — @fluentui/react-components を使用してください
  • ❌ v8 の Stack を使用する — CSS Grid または Flexbox を使用してください
  • ❌ CSS でカラーシステムの CSS カスタムプロパティを直接オーバーライドする — アダプティブカラーシステムは JS によって制御されます
  • ❌ フォーカスインジケーターを削除する — アクセシビリティ要件です

コメント