Quick Start
Start with style(), useCss(), css prop composition, and reusable style files.
Fluentic Style starts small. Write styles with style(), resolve them with
useCss(), and pass the resolved result to the css prop.
1. Write a style
Section titled “1. Write a style”/** @jsxImportSource @fluentic/style */import { style, useCss } from '@fluentic/style';
const styles = { button: style({ display: 'inline-flex', alignItems: 'center', border: 0, borderRadius: 6, padding: '8px 12px', backgroundColor: '#2563eb', color: 'white', cursor: 'pointer', }).hover({ backgroundColor: '#1d4ed8', }),};
export function Button() { const css = useCss(styles);
return <button css={css.button}>Save</button>;}That is the core loop:
style(...)creates a typed style builder.useCss(styles)resolves the builders for React.css={css.button}puts the generated class on the element.
2. Combine styles
Section titled “2. Combine styles”Keep related styles in one object, resolve that object once, and combine resolved items with arrays.
const styles = { button: style({ display: 'inline-flex', alignItems: 'center', border: '1px solid rgb(15 23 42 / 0.14)', borderRadius: 6, padding: '8px 12px', backgroundColor: 'white', color: '#0f172a', }), primary: style({ borderColor: '#2563eb', backgroundColor: '#2563eb', color: 'white', }), fullWidth: style({ width: '100%', }),};
export function Button(props: { primary?: boolean; fullWidth?: boolean }) { const css = useCss(styles);
return ( <button css={[ css.button, props.primary && css.primary, props.fullWidth && css.fullWidth, ]} > Save </button> );}The css prop accepts items, arrays, nested arrays, and falsy values. This makes
conditional styling feel like ordinary React composition.
3. Forward the css prop
Section titled “3. Forward the css prop”Reusable components should let callers add element-level styles. Accept
CssProp, then place it last in the css array so the caller can add layout or
one-off adjustments.
/** @jsxImportSource @fluentic/style */import { style, useCss } from '@fluentic/style';import type { CssProp } from '@fluentic/style';import type { ReactNode } from 'react';
const styles = { button: style({ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8, border: '1px solid rgb(15 23 42 / 0.14)', borderRadius: 6, padding: '8px 12px', backgroundColor: 'white', color: '#0f172a', }),};
type ButtonProps = { children: ReactNode; css?: CssProp;};
export function Button(props: ButtonProps) { const css = useCss(styles);
return <button css={[css.button, props.css]}>{props.children}</button>;}Callers can pass another resolved style:
const pageStyles = { wideAction: style({ minWidth: 160, }),};
export function Page() { const css = useCss(pageStyles);
return <Button css={css.wideAction}>Publish</Button>;}4. Reuse styles across files
Section titled “4. Reuse styles across files”Style builders are normal values. Define common styles once, export them, and combine them wherever you resolve CSS.
import { style } from '@fluentic/style';
export const focusRing = style().focusVisible({ outline: '2px solid #2563eb', outlineOffset: 2,});
export const inlineControl = style({ display: 'inline-flex', alignItems: 'center', justifyContent: 'center',});import { style } from '@fluentic/style';import { focusRing, inlineControl } from './styles/common';
export const buttonStyles = { root: style({ border: '1px solid rgb(15 23 42 / 0.14)', borderRadius: 6, padding: '8px 12px', backgroundColor: 'white', color: '#0f172a', }) .merge(inlineControl) .merge(focusRing), primary: style({ borderColor: '#2563eb', backgroundColor: '#2563eb', color: 'white', }),};/** @jsxImportSource @fluentic/style */import { useCss } from '@fluentic/style';import type { CssProp } from '@fluentic/style';import type { ReactNode } from 'react';import { buttonStyles } from './Button.styles';
type ButtonProps = { children: ReactNode; css?: CssProp; primary?: boolean;};
export function Button(props: ButtonProps) { const css = useCss(buttonStyles);
return ( <button css={[css.root, props.primary && css.primary, props.css]}> {props.children} </button> );}This is enough for many app components: define styles, reuse style builders,
resolve once per component, and compose through css.
5. Add tokens when values become shared
Section titled “5. Add tokens when values become shared”When a value becomes part of your design language, make it a token.
import { createToken } from '@fluentic/style';
export const color = { accent: createToken('#2563eb'), accentText: createToken('#ffffff'),};import { style } from '@fluentic/style';import { color } from './tokens';
export const buttonStyles = { root: style({ backgroundColor: color.accent, color: color.accentText, }),};Tokens keep a stable identity, so later themes can retarget the same design value without rewriting every component.
Next steps
Section titled “Next steps”Use plain style() for styles that belong to one rendered element.
Use style.slot(...) when a component wants to publish a supported styling
target, such as root, icon, label, or panel.
Use style.scope(...) when you want to encapsulate a group of overrides for a
theme, variant, state, media query, or subtree.
Continue with Slots and Scopes when you are ready to design a public component styling API.