@ada-cx/lovelace
v1.22.0
Published
Ada's messaging design system primitives: React Aria Components behavior, vanilla-extract styling, Figma-generated design tokens.
Readme
@ada-cx/lovelace
Ada's messaging design system primitives. Behavior comes from React Aria Components. Styling comes from vanilla-extract. Every design value comes from Figma-generated tokens.
Requirements
- React 19 and React DOM 19 as peer dependencies. Earlier React versions are not supported.
- A bundler or dev server that can import plain
.cssfiles.
Install
npm install @ada-cx/lovelace react react-domSetup
You must import both stylesheets once at your app entry. The library build extracts all component CSS to one file, so a JS-only import renders unstyled components.
import "@ada-cx/lovelace/tokens.css";
import "@ada-cx/lovelace/style.css";tokens.css defines the --lovelace-* custom properties inside @layer lovelace.tokens. style.css holds the component styles, which only reference those properties through var(). Both imports are required.
Then wrap your app in LovelaceProvider. It is the prescribed entry point for consuming Lovelace.
import { LovelaceProvider, Button } from "@ada-cx/lovelace";
export function App() {
return (
<LovelaceProvider theme="auto">
<Button variant="primary">Send</Button>
</LovelaceProvider>
);
}LovelaceProvider resolves the color scheme (light, dark, or auto), stamps data-theme on its wrapper, applies token overrides, and keeps React Aria overlay portals (Dialog, Sheet, Tooltip) inside the theme boundary. Components render without the provider — data-theme defaults to light — but then you own theme switching and portal scoping yourself.
Theming with token overrides
Re-point tokens per brand through the override prop. Keys are the overridable semantic and component tokens. Values are CSS values, typically built with the typed t() helper from @ada-cx/lovelace/tokens.
import { LovelaceProvider } from "@ada-cx/lovelace";
import { t } from "@ada-cx/lovelace/tokens";
<LovelaceProvider
override={{
"color-background-accent": "#0f62fe",
"font-size-body": t("font-size-14"),
}}
>
{children}
</LovelaceProvider>;Overrides ride above the token layer as inline CSS variables, so they always win over the shipped defaults. Any unlayered --lovelace-* rule you write yourself wins the same way. Set an accent fill and the text on it through override as hex colors, not in a stylesheet. The provider reads that pair to pick the hover, focus, and pressed state layer that keeps the text at 4.5:1. If the pair is not complete, or a value is not a hex color, the provider keeps the default state layer and does not check its contrast. If you need tokens without component styles, for example to build a custom theme, import @ada-cx/lovelace/tokens.css alone.
Brand overrides
createBrandOverrides(settings, scheme) maps Ada dashboard brand settings to a token override map. It is the same function the Ada widget runs, so a custom UI that calls it applies a brand exactly the way the widget does. The scheme argument is the resolved "light" or "dark" scheme; resolve "auto" through useResolvedTheme first.
import {
createBrandOverrides,
LovelaceProvider,
useResolvedTheme,
} from "@ada-cx/lovelace";
function BrandedChat({ children }) {
const scheme = useResolvedTheme("auto");
return (
<LovelaceProvider
theme="auto"
override={createBrandOverrides({ tintColor: "#0f62fe" }, scheme)}
>
{children}
</LovelaceProvider>
);
}The mapping paints the accent fill, picks a readable black or white for text on the accent, darkens or lightens the tint as accent text until it holds 4.5:1 on the rendered surface, and repairs a header text color that falls below the WCAG AA 4.5:1 contrast floor against its background. Corner style and text size presets re-point the radius and type-scale tokens. Every BrandSettings field is optional, and createBrandOverrides({}, scheme) returns {}. Legibility guards measure hex colors only, and they do not repair other values. A tint the guards cannot read is the exception. It still paints the accent fill as configured, but its accent text is the default accent #4e53d1, darkened or lightened until it holds 4.5:1.
The colorimetry behind the mapping is also exported: contrastRatioBetween, isLegibleAgainst, isLegibleOnSurface, LOVELACE_SURFACES, and readableTextOnAccent.
Entry points
| Import | Contents |
| --- | --- |
| @ada-cx/lovelace | Components, hooks, LovelaceProvider (ESM + types) |
| @ada-cx/lovelace/tokens | t(), tokenName(), token types (ESM + types) |
| @ada-cx/lovelace/tokens.css | Token definitions (required stylesheet) |
| @ada-cx/lovelace/style.css | Component styles (required stylesheet) |
These four imports are the whole public surface. The package has no per-component subpaths and no supported deep imports into dist/. Import every component and hook from the package root.
Components compose in one of two shapes:
- Dot-namespaced members for the parts of one widget:
Dialog.Title,Sheet.Header,Input.Field,MenuItem.Checkbox,MessageRow.Content,Header.Title. - Flat sibling components for a container and its repeated children:
MenuwithMenuItem,RadioGroupwithRadio.
Scope of this release
- Primitives only. This package ships design system primitives: buttons, inputs, chips, dialogs, sheets, survey controls, icons, and similar building blocks. Domain composites from the Ada product, such as the CSAT survey form and the file-upload flow, are not included.
- React 19 is a hard requirement. The peer range is
^19.0.0by design and will not be widened. - Pixel parity with the Ada widget is not guaranteed. The shipped Ada messaging app blends Lovelace with a legacy component system during an incremental migration. A UI you build from these primitives can differ visually from the hosted Ada widget.
Accessibility
Components target WCAG 2.2 Level AA. React Aria Components provide keyboard operability, roles, and focus management. Interactive states are styled through data-* attributes (data-hovered, data-pressed, data-focus-visible, data-disabled), so you can extend styling the same way.
Versioning
This package is fully versioned: the implementation you install is the implementation you run. Pin a version and upgrade deliberately. This differs from Ada's web messaging runtime, which resolves from the CDN at load time.
