Fluentic
Style
Typed styling contracts for React component systems — fluent chains for authors, slots for public override points, scopes for themes, and atomic CSS for delivery.
npm install @fluentic/style import { style, token } from '@fluentic/style';
const button = {
root: style.slot({
display: 'inline-flex',
borderRadius: 8,
padding: '8px 12px',
}).hover({ opacity: 0.88 }),
label: style.slot({ fontWeight: 650 }),
};
// Compose a scope for variants & themes
const primary = style.scope([
button.root({ backgroundColor: token.accent }),
button.label({ fontWeight: 760 }),
]);
// Use it in your component
export function Button({ scope }) {
const css = useCss(button, scope);
return <button css={css.root} scope={css}>…</button>;
} Typed Contracts
Slots are TypeScript types. Every overridable part of a component has a name your IDE can check, autocomplete, and break-detect on rename.
Atomic CSS
One declaration = one class. Zero duplication, zero specificity wars. Order is deterministic whether you use the runtime or extract to CSS.
Fluent Chains
.hover(), .focus(), .media(),
.container() — selector variants chain directly on any slot,
keeping logic close to the component that owns it.
Static Extraction
Static chains compile to atomic CSS at build time. Switch from runtime to extracted output without touching a single line of source code.
Why Fluentic Style?
Styling a component library becomes messy when base styles, consumer overrides, theme layers, and build performance all pull in different directions. Fluentic Style separates the concerns so each one stays manageable.
Styling as a public API
With CSS Modules or plain class names, consumers override by guessing names that can change any release. Slots are a contract: named, typed, and stable across versions — like a prop surface for styles.
No specificity wars
Emotion, styled-components, and similar tools accumulate specificity as theme layers stack. Atomic CSS gives each property exactly one class; cascade order is explicit and predictable regardless of how many scopes are active.
Runtime first, compile when ready
Start in runtime mode — it works in Vitest, Storybook, SSR, and any framework. When you ship to production, extract the static subset to CSS files without changing the source and without running a separate codegen step.
Scoped themes, no Provider hell
Scopes carry overrides through a subtree via the scope prop.
No wrapper components, no CSS custom property gymnastics, no generated class
names leaking into consumer DOM.
How it compares
Most tools solve one problem well. Fluentic Style connects them into a single coherent model without asking you to give up TypeScript, atomic CSS, or runtime flexibility.
| Capability | Fluentic Style | CSS Modules | CSS-in-JS | Tailwind |
|---|---|---|---|---|
| Typed override targets (slots) | ✓ | ✗ | ✗ | ✗ |
| Atomic CSS output | ✓ | ✗ | varies | ✓ |
| Runtime-first (no build step) | ✓ | ✗ | ✓ | ✗ |
| Static CSS extraction | ✓ | ✓ | limited | ✓ |
| Subtree theme scoping | ✓ | ✗ | varies | ✗ |
| TypeScript-first authoring | ✓ | partial | partial | ✗ |
| Predictable cascade order | ✓ | manual | ✗ | ✓ |
Zero config to start
Install the package and write your first slot — runtime mode works immediately, no build plugin needed. Add Vite or webpack extraction when you're ready for static CSS output, without touching a line of source.