Writing a Bridge
Copy MarkdownA bridge is a plain CSS file that maps your host application's design-system tokens onto Aurora UIX's --auix-* variables. The library ships one bridge for daisyUI (auix-bridge-daisyui.css); this guide explains how to write one for any other design system.
What a bridge does
Aurora UIX components are styled exclusively via --auix-* custom properties defined in auix-variables.css. A bridge overrides a subset of those properties at :root level, pointing them at equivalent tokens from the host framework. When the host's theme changes — by switching a daisyUI theme, toggling dark mode, or updating a Tailwind @theme value — the --auix-* vars resolve to the new values automatically, and every Aurora UIX component follows.
/* Minimal bridge structure */
@layer auix.bridge {
:root, :host {
--auix-color-bg-default: var(--my-framework-background);
--auix-color-text-primary: var(--my-framework-on-background);
/* … */
}
}When you need one
The default auix-bridge-daisyui.css covers Phoenix apps using Tailwind v4 + daisyUI. Write a custom bridge if you use:
- A different UI library (Shoelace, Material, Radix)
- A hand-crafted design token set (e.g.,
--color-brand-*from your style guide) - Bootstrap CSS variables
- Any system that exposes theme values as CSS custom properties
Finding the right variables
Aurora UIX side — open assets/css/auix-variables.css (generated by mix auix.gen.stylesheet). Every --auix-* property declared there is a candidate for bridging. Properties in --auix-color-* categories are the most impactful; dimension variables (--auix-border-radius-*, --auix-border-width-*) help align shape and density.
Host framework side — inspect your app's CSS in the browser DevTools or read the framework's theming docs to find the token names it exposes at :root.
Example: custom design token set
Suppose your design system defines these tokens:
:root {
--ds-surface: #ffffff;
--ds-on-surface: #1a1a1a;
--ds-primary: #0056d2;
--ds-on-primary: #ffffff;
--ds-danger: #cc0000;
--ds-radius-sm: 4px;
--ds-radius-md: 8px;
}A bridge mapping the most visible --auix-* variables:
/* my-bridge.css
Import AFTER auix-variables.css and BEFORE auix-rules.css. */
@layer auix.bridge {
:root, :host {
--auix-color-bg-default: var(--ds-surface);
--auix-color-text-primary: var(--ds-on-surface);
--auix-color-text-secondary: var(--ds-on-surface);
--auix-color-text-label: var(--ds-on-surface);
--auix-color-text-on-accent: var(--ds-on-primary);
--auix-color-border-focus: var(--ds-primary);
--auix-color-focus-ring: var(--ds-primary);
--auix-color-error: var(--ds-danger);
--auix-color-error-text: var(--ds-danger);
--auix-color-error-ring: var(--ds-danger);
--auix-border-radius-default: var(--ds-radius-md);
--auix-border-radius-small: var(--ds-radius-sm);
}
}You don't have to bridge every variable. Anything left unmapped falls back to Aurora UIX's own defaults from auix-variables.css.
Import order
Place the bridge between the two Aurora UIX imports in app.css:
@import "auix-variables.css"; /* Aurora UIX defaults — must come first */
@import "my-bridge.css"; /* your overrides */
:root { /* any extra one-off tweaks */ }
@import "auix-rules.css"; /* component rules — must come last */No mix task is needed. Drop the file anywhere that your bundler (esbuild) can resolve it — assets/css/ is the conventional location.
Tips
- Always wrap in
@layer auix.bridge { … }. Aurora UIX uses CSS cascade layers (auix.variables → auix.bridge → auix.rules). Without the layer wrapper, the bridge's plain:rootselector (specificity 0,1,0) loses to the themes'[data-theme-name="…"]selectors (specificity 0,2,0), so your overrides are silently ignored. Anything written outside all layers (in your ownapp.css) still wins over everything, so host one-off tweaks work as expected. - Bridge only what differs. Fewer overrides mean less to maintain when either side updates its token names.
- Use
var(…, fallback). If a host token might not always be defined, provide a sensible fallback:var(--ds-radius-md, 0.5rem). - Check dark mode. If your design system uses attribute or class selectors for dark mode (e.g.,
[data-theme="dark"],.dark), scope your dark overrides the same way your design system does inside the@layer auix.bridgeblock. - Keep the file in version control. The bridge is part of your application's styling, not a generated artefact.