Co-authored-by: Dewi Roberts <dewi@goauthentik.io> Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
6.8 KiB
title, sidebar_label, description
| title | sidebar_label | description |
|---|---|---|
| CSS architecture | CSS architecture | Proposed runtime CSS and design token architecture for authentik's Lit web components. |
authentik's UI is currently a customized PatternFly 4 system wrapped by Lit web components. Treat PatternFly as the compatibility substrate, not the future public API.
Current state
web/package.jsondepends on@patternfly/patternfly4.x and@patternfly/elements.web/src/elements/Base.tsinjects PatternFly base CSS, component CSS, and authentik base CSS into each Lit element.web/src/common/stylesheets.tscentralizesCSSStyleSheetcreation and adopted stylesheet updates.web/src/styles/authentik/base/*.cssoverrides PatternFly global variables and already contains light and dark theme branches.- Brand custom CSS is appended to component style roots, including nested shadow roots.
- Components mix PatternFly class markup, PatternFly per-component imports, global CSS, inline styles,
partattributes, and local--ak-*variables.
This gives good incremental control, but no stable external theming contract. Users have to inspect --pf-* and internal --ak-c-* names, then hope those names survive upgrades.
Direction
Split the design system into two independent layers:
- Runtime CSS architecture: browser-native CSS variables, Shadow DOM inheritance, CSS parts, slots, container queries, media queries, and eventually cascade layers.
- Token pipeline: DTCG-format JSON as interchange data, compiled to CSS variables and other outputs by a build tool.
Do not couple runtime styling to DTCG. The browser should consume CSS variables. DTCG should remain source data for tooling, Figma sync, validation, and docs.
Public token tiers
Use three token tiers:
| Tier | Prefix | Stability | Use |
|---|---|---|---|
| Primitive | internal or generated | private | palette stops, raw scales, build input |
| Semantic | --ak-* |
public | custom CSS, component styles, docs |
| Component-local | --_ or --ak-c-* |
private by default | implementation detail inside one component |
Prefer short semantic names:
:root {
--ak-color-primary: #3b82f6;
--ak-color-surface: white;
--ak-color-text: #18181b;
--ak-space-md: 1rem;
--ak-radius-sm: 3px;
}
Avoid exposing component property names as the main customization API:
/* Avoid */
--ak-c-button-primary-background-color-hover-padding-left: 1rem;
Runtime layering
Target cascade order:
@layer reset, base, tokens, components, utilities, overrides;
Use layers only after the active CSS entrypoints can establish a single layer order. PatternFly CSS and existing unlayered rules should stay outside layers until their order is audited. In CSS, unlayered normal declarations override layered normal declarations, so partially layering token files can silently lose to legacy declarations.
Recommended meaning:
reset: minimal browser normalization.base: document, typography, default color scheme, accessibility defaults.tokens: semantic--ak-*values and theme variants.components: reusable component class and shadow styles.utilities: narrow one-purpose utilities.overrides: brand custom CSS and targeted escape hatches.
Shadow DOM API
Use custom properties for configuration:
ak-flow-executor {
--ak-color-primary: oklch(62% 0.2 260);
}
Use ::part() only for exposed structure:
ak-flow-executor::part(locale-select) {
display: none;
}
Use slots for composition, not styling. A component should expose stable parts only when a user or brand can reasonably style that substructure without coupling to internal DOM.
Accessibility defaults
New component CSS should support:
color-scheme: light darkaccent-color: var(--ak-color-accent)prefers-color-schemeprefers-reduced-motionprefers-contrastforced-colors- logical properties for localization and right-to-left layouts
Avoid baking accessibility variants into separate theme files. Prefer semantic tokens that media queries can adjust.
Token pipeline
DTCG 2025.10 is the right interchange target, but not yet a frictionless runtime source. The spec uses token objects with $value and $type, recommends .tokens or .tokens.json, and supports token references such as {colors.blue}. Style Dictionary has DTCG support in v4, but its own docs currently note that full support for the 2025.10 format is still work in progress for v5.
Recommended build pipeline:
DTCG tokens
-> validation
-> Style Dictionary or equivalent compiler
-> generated CSS variables
-> imported runtime token CSS
-> Lit component styles and brand custom CSS
Start with handwritten runtime CSS tokens. Add generated files only when token ownership, review workflow, and Figma sync are defined.
Migration phases
- Establish public
--ak-*semantic tokens mapped to current PatternFly values. - Update custom CSS docs to prefer
--ak-*over--pf-*. - Migrate new or touched authentik components to consume semantic tokens first, PatternFly globals second.
- Add token metadata docs generated from the public token list.
- Introduce DTCG source files and a compiler when the public token list is stable.
- Add cascade layers after global, shadow, and custom CSS order are audited.
- De-PatternFly component markup incrementally, starting with components whose styling is already mostly custom.
Guardrails
- Public semantic tokens should stay near 30 to 60 names until real user needs justify more.
- Do not expose every CSS property as a public token.
- Do not document
--ak-c-*as stable unless it is intentionally promoted. - Do not generate tokens directly from PatternFly variable names.
- Keep component part names short and structural, for example
control,label,icon,content,footer. - Keep direct custom CSS injection as an advanced escape hatch, not the primary theming API.