fluent2-design-system
Fluent 2 Design System
Build production-grade interfaces using Microsoft's Fluent 2 design system with @fluentui/react-components (v9).
Quick Start
Every Fluent 2 React app requires a FluentProvider wrapping the component tree with a theme:
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>
);
}
Install: npm install @fluentui/react-components
Core Architecture
Theming
- Built-in themes:
webLightTheme,webDarkTheme,teamsLightTheme,teamsDarkTheme,teamsHighContrastTheme - Custom branding: Use
createLightTheme(brandRamp)/createDarkTheme(brandRamp)with aBrandVariantsobject (keys10–160) - Nesting:
FluentProvidercan nest for sub-trees with different themes - Theme values are emitted as CSS custom properties on the provider element
Styling with Griffel
Use makeStyles (from @fluentui/react-components) — never inline styles or external CSS for token-aware styling.
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>
);
}
Critical rules:
- Define
makeStylesoutside components (module scope) - Use
mergeClasses()to compose classes — never concatenate strings - Use
tokens.*for all colors, spacing, typography, radii, shadows — never hardcode hex/px values - CSS shorthands (
border,borderRadius,padding, etc.) are not supported — useshorthands.*helper or longhand properties - Pseudo-selectors use nested objects:
":hover": { color: tokens.colorBrandForeground1 } - Media queries use nested objects:
"@media (min-width: 768px)": { flexDirection: "row" }
Component Model
All v9 components follow a consistent pattern:
- Slots: Named sub-parts (e.g.,
root,icon,content) that accept props or JSX - Appearance variants:
"primary","secondary","subtle","transparent","outline" - Size variants:
"small","medium","large" - Shape variants:
"rounded","circular","square"
Override component styles via className with makeStyles/mergeClasses.
Design Tokens
Tokens are the bridge between design intent and code. Always use tokens.* — never raw values.
For complete token reference tables (color, typography, spacing, elevation, stroke, corner radius), see references/tokens.md.
Token Categories at a Glance
| Category | Prefix | Example |
|---|---|---|
| Neutral colors | colorNeutral* |
tokens.colorNeutralBackground1 |
| Brand colors | colorBrand* |
tokens.colorBrandBackground |
| Status colors | colorPalette{Color}* |
tokens.colorPaletteRedForeground1 |
| Typography | fontFamily*, fontSize*, fontWeight*, lineHeight* |
tokens.fontSizeBase300 |
| Spacing | spacingHorizontal*, spacingVertical* |
tokens.spacingHorizontalM |
| Border radius | borderRadius* |
tokens.borderRadiusMedium |
| Stroke width | strokeWidth* |
tokens.strokeWidthThin |
| Shadow | shadow* |
tokens.shadow4 |
| Duration | duration* |
tokens.durationNormal |
| Easing | curve* |
tokens.curveEasyEase |
Two-Layer Token System
- Global tokens — context-agnostic raw values (e.g.,
colorBlue60,fontSize300) - Alias tokens — semantic meaning applied to globals (e.g.,
colorBrandBackground→ blue,colorNeutralForeground1→ dark gray)
In code, consume alias tokens via the tokens object.
Layout
- Grid: Use CSS Grid/Flexbox — Fluent 2 v9 has no
Stackcomponent - Spacing scale: 4px base unit. Values:
XXS(2),XS(4),S(8),M(12),L(16),XL(20),XXL(24),XXXL(32) - Column grid: 12-column framework recommended for web; use CSS grid
- Alignment: Use
tokens.spacingHorizontal*andtokens.spacingVertical*for consistent spacing
Typography
- Primary typeface: Segoe UI (web), Segoe UI Variable (Windows), SF Pro (macOS/iOS), Roboto (Android)
- Font stack:
tokens.fontFamilyBase= Segoe UI → system fallbacks → sans-serif - Monospace:
tokens.fontFamilyMonospace - Text presets: Use
<Text>component with preset variants —Caption1,Body1,Body1Strong,Subtitle1,Subtitle2,Title1,Title2,Title3,LargeTitle,Display - Alignment: Left-align for LTR; Fluent handles RTL automatically via Griffel
Color System
Three palettes:
- Neutral — blacks, whites, grays for surfaces, text, layout
- Brand — accent colors reinforcing identity (default Microsoft brand = blue)
- Shared/Status — cross-product colors: red (danger), green (success), yellow (warning), blue (informational)
Interaction states: rest → hover (darker) → pressed (darkest). Focus adds a thicker stroke, not a color change.
Accessibility
- All components include ARIA roles, keyboard navigation (via Tabster), and focus management
- High contrast: use
teamsHighContrastThemeor handle@media (forced-colors: active)with system colors (ButtonText,Highlight, etc.) - Focus indicators are visible by default — never remove them
- Ensure WCAG contrast via semantic token pairing (e.g.,
colorNeutralForeground1oncolorNeutralBackground1)
Component Inventory
For the full categorized component list with usage notes, see references/components.md.
Most-Used Components
Actions: Button, CompoundButton, SplitButton, ToggleButton, MenuButton, Link Inputs: Input, Textarea, Select, Combobox, Dropdown, Checkbox, RadioGroup, Switch, Slider, SpinButton, DatePicker, TimePicker Layout: Card, Divider, Drawer, Dialog, Popover, Tooltip Data Display: Table, DataGrid, Tree, Accordion, Badge, Avatar, AvatarGroup, Tag, Persona Navigation: TabList, Breadcrumb, Nav (preview) Feedback: Toast, MessageBar, ProgressBar, Spinner, Skeleton Surfaces: Menu, Toolbar, Overflow
Common Patterns
App Shell Layout
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,
},
});
Custom Brand Theme
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);
Dark Mode Toggle
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>
);
}
Anti-Patterns
- ❌ Hardcoded colors (
color: "#333") — usetokens.colorNeutralForeground1 - ❌ CSS shorthand properties in
makeStyles(border: "1px solid red") — use longhand orshorthands.* - ❌ String concatenation of classNames — use
mergeClasses() - ❌ Inline
styleprops for token-based values — usemakeStyleswithtokens - ❌ Importing from
@fluentui/react(v8) in v9 projects — use@fluentui/react-components - ❌ Using v8
Stack— use CSS Grid or Flexbox - ❌ Overriding CSS custom properties from the color system directly in CSS — the adaptive color system is JS-driven
- ❌ Removing focus indicators — accessibility requirement
More from dodatech/approved-skills
tremor-design-system
Build dashboards, analytics interfaces, and data-rich UIs using the Tremor design system (React + Tailwind CSS + Recharts). Use when the user asks to create dashboard components, KPI cards, charts, data tables, analytics pages, monitoring interfaces, or any data visualization UI that should use Tremor. Triggers include mentions of "Tremor", "tremor.so", "@tremor/react", requests for dashboard UIs with charts and tables, or when the user's project already uses Tremor components. Supports both Tremor Raw (copy-and-paste, tremor.so) and Tremor NPM (@tremor/react) versions. Do NOT use for general frontend work unrelated to dashboards or data visualization, or when the user explicitly requests a different component library.
82playwright-local
|
58carbon-design-system
Build UIs using IBM's Carbon Design System. Use when the user requests Carbon-styled interfaces, IBM-style dashboards, enterprise UIs following Carbon conventions, or explicitly mentions Carbon, IBM design, or @carbon/react. Covers component usage, design tokens (color, typography, spacing, motion), theming (White, Gray 10, Gray 90, Gray 100), grid layout, and accessibility. Supports both artifact/HTML output (CDN-based) and full React project output (@carbon/react). Triggers include "Carbon", "IBM design system", "enterprise dashboard", "@carbon/react", "carbon components", or requests for IBM-style professional interfaces.
25business-intelligence
Expert business intelligence covering dashboard design, data visualization, reporting automation, and executive insights delivery.
9fixing-metadata
Ship correct, complete metadata.
9paid-ads
When the user wants help with paid advertising campaigns on Google Ads, Meta (Facebook/Instagram), LinkedIn, Twitter/X, or other ad platforms. Also use when the user mentions 'PPC,' 'paid media,' 'ad copy,' 'ad creative,' 'ROAS,' 'CPA,' 'ad campaign,' 'retargeting,' or 'audience targeting.' This skill covers campaign strategy, ad creation, audience targeting, and optimization.
8