FnHCI.UI Token Model
This note captures the first durable token-model direction for FnHCI.UI and the narrower FnUI visual system line.
The goal is to keep the token model:
- compatible with what Penpot is already doing well
- useful across multiple runtime targets
- structured enough to support later deterministic tooling
- separate from business meaning while still close enough to UI semantics to matter
Why This Note Exists
The current Penpot evidence is now strong enough to justify a first explicit token-model note.
Real .penpot exports now show:
- first-class
tokens.jsonin some files design-tokens/v1feature support even in files that have not yet emitted a populatedtokens.json- token sets
- theme groups
- active theme selection metadata
- responsive breakpoint themes
- semantic token names such as
buttonPrimary.background.default
That means we should stop treating tokens as just "some colors" and instead start treating them as a structured part of the FnHCI.UI and FnUI architecture.
Boundary
Tokens are not:
- business events
- domain commands
- the owner of path meaning
- the owner of cross-platform interaction primitives
Tokens are:
- named reusable visual values
- named reusable visual meanings
- themeable inputs to runtime projection
- a bridge between Penpot and
FnUI
So the general layering remains:
- business and path semantics
FnHCIinteraction primitives and view composition- token model
- design and runtime projections
Token Layers
The current best split is:
- foundation tokens
- semantic UI tokens
- theme axes
- active theme composition
Foundation Tokens
Foundation tokens are the raw reusable building blocks.
Examples:
- base colors and palettes
- spacing values
- size scales
- typography families and weights
- radius values
- opacity values
- shadow values
- line widths
- breakpoint sizes
These should be reusable without already implying one specific component role.
In Penpot evidence, these show up as sets like:
FoundationsScale/LinearScale/ModularTypographyShadows
Semantic UI Tokens
Semantic UI tokens sit above foundations and express visual meaning closer to components and layout roles.
Examples already visible in Penpot:
buttonPrimary.background.defaultbuttonSecondary.border.focusedlayerBase.textinput.borderheading.text
This is the most important bridge layer for FnUI, because these tokens are closer to interaction and layout meaning without being tied to one renderer.
Theme Axes
Theme axes are orthogonal dimensions that activate different token sets.
The current evidence strongly suggests we should keep these axes separate instead of flattening them into huge combined names.
Current likely axes include:
- breakpoint
- color mode
- color theme
- density
- later brand
- later contrast or accessibility modes
This means we should prefer:
- breakpoint:
mobile,tablet,desktop - color mode:
light,dark - density:
compact,comfortable,spacious
instead of combined preset names like:
light-mobiledark-desktop
Active Theme Composition
The active UI style should come from composing multiple theme axes at once.
That is already how Penpot models themes in the current examples.
So the working rule is:
- one active configuration may involve several enabled theme groups simultaneously
- the final visual values come from combining shared defaults plus axis-specific overrides
This is much closer to CSS-like composition than to one giant preset switch.
Responsive Design Direction
Laura Kalbag's breakpoint explanation and the Tokens and breakpoints.penpot file both point toward the same responsive design pattern:
- keep shared defaults in a global set
- apply one breakpoint set as an override
- let that breakpoint theme combine with other themes such as light/dark
That means responsive design in our future model should likely treat breakpoint as:
- a theme axis
- not a separate parallel UI system
Examples of what a breakpoint axis might influence:
- viewport board width
- max-width values
- typography scale multipliers
- spacing scale choices
- component layout thresholds
What Belongs In FnHCI Versus Tokens
The rough boundary should be:
FnHCIowns the interaction primitive and the semantic role of the control- tokens own the named visual-value and visual-meaning layer used to render that primitive
So:
Buttonas an interaction primitive belongs inFnHCIbuttonPrimary.background.defaultbelongs in the token model
This keeps visual styling flexible without losing semantic UI structure.
Penpot Mapping Direction
Penpot should be treated as:
- one strong design-token authoring and inspection surface
- one source of real token examples
- one place where theme composition can be validated visually
But Penpot should not be the only owner of the token model.
The future NEXUS and FnTools direction should likely be:
- define a stable internal token model
- import and export Penpot token structures
- preserve Penpot-compatible naming where it helps
- keep enough structure to support other runtimes too
The first concrete proving-ground note for this direction now lives in LaundryLog FnHCI.UI Token Vocabulary.
Runtime Mapping Direction
The token model should be renderer-neutral enough to project into multiple runtime targets.
Examples:
- Blazor or HTML: CSS custom properties, classes, inline styles, generated stylesheets, or mixed approaches
- Android: theme resources, Compose tokens, or generated constants
- iOS: SwiftUI/environment tokens or generated constants
- Web Components: custom properties and component styling contracts for a browser-specific runtime target
Web Components are relevant here as a possible browser runtime packaging target, not as the owner of the token model.
Suggested First Internal Shapes
The first internal model likely wants to distinguish:
- token id
- token layer
foundationorsemantic - token type
color,dimension,font-size,spacing,shadow, and similar - token value
- references to other tokens
- theme axis membership
- theme group membership
- runtime projection hints where necessary
That model should be explicit enough for later F# code generation, validation, and testing.
What We Should Not Do
We should avoid:
- collapsing every token into one flat string bag
- treating all tokens as just colors
- hard-wiring token names to one renderer
- forcing responsive behavior into duplicated combined theme names
- relying on Penpot GUI state without preserving the structured token data
Near-Term Next Steps
The most useful next moves are probably:
- define a first explicit token vocabulary for LaundryLog
- separate LaundryLog foundation tokens from semantic tokens
- pick the first orthogonal theme axes we actually need
- sketch the first F# token-model types in
FnTools - later test projection of the same token set into Penpot and
FnUI
Evidence
Key sources for this direction include: