feat(theme): introduce theme system for autocomplete widget#75
feat(theme): introduce theme system for autocomplete widget#75sarahdayan merged 15 commits intomainfrom
Conversation
✅ Deploy Preview for algolia-experiences-js ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for algolia-experiences-react ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
- Add `@experiences/theme` package with `ThemeVariable` types and `generateThemeCss()` for generating light/dark CSS custom property blocks - Integrate theme CSS generation into runtime middleware, replacing ad-hoc cssVariables injection - Replace bundled satellite.css + upstream autocomplete.css with a local autocomplete.css, dropping the unused satellite theme - Add `ThemeSwitcher` component to the React example for dev/demo theming - Add `examples/shared/` with reusable theme definitions across JS and React examples - Improve dev setup: local proxy serves dist files during development, file watching triggers HMR, `useAlgoliaExperiences` supports relative URLs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add createThemeOverridesSchema() that builds a Zod validation schema from the theme variable catalog. Number variables get min/max/step constraints, all fields include descriptions with units and defaults for AI agent consumption. ThemeOverrides now accepts string | number values with coercion at the CSS generation boundary. Reorganize packages/theme into types.ts, lib/, and widgets/ for clearer separation of concerns. Move autocomplete.css into packages/runtime/src/styles/. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Test createThemeOverridesSchema validation (type checking, numeric constraints, empty/partial objects), JSON Schema output (property keys, types, descriptions, constraints), and generateThemeCss (light/dark blocks, defaults, unit appending, unitless numbers, overrides, per-mode overrides, unknown keys ignored). Also add toJsonSchema() method and zod-to-json-schema dependency for AI tool definition generation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The stylesheet is a product of the theme variable catalog, not the runtime. Moving it to packages/theme/src/widgets/ co-locates it with the variable definitions it consumes. The runtime build config now reads the CSS from the theme package. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add "Format: R, G, B." to color variable descriptions so agents know to return RGB triplets. Add min/max constraints (0–1) to all alpha and opacity variables to prevent out-of-range values. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wrap the overrides schema in `{ light, dark }` so agents return per-mode
values in a single tool call. Add constraints to `base-unit` and change
`font-weight-medium` from text to number with valid CSS weight range.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Convert 7 variables from unvalidated text to number type with min/max/step constraints: font weights, header font size, item line height, transition duration, detached modal top offset, and scrollbar color mix. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace freeform text shadow variables with a constrained `shadow` type that stores an array of structured layer objects (offsetX, offsetY, blur, spread, color, opacity). This makes shadows validatable by the schema and easier for AI agents to produce correctly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…lations The `step` constraint is a UI hint for slider increments, not a validation rule. IEEE 754 rounding causes values like 0.15 to fail `multipleOf(0.1)`, rejecting valid agent output. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rrideValue Move isShadowLayers to its own predicates/ folder, strengthen the check to require both offsetX and blur, and add unit tests. Export ThemeOverrideValue from types.ts to remove the duplicate declaration in generate-theme-css.ts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move test files from a top-level __tests__/ directory to colocated __tests__/ folders within each source module (lib/, predicates/). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
62169c5 to
0dc5670
Compare
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| style.textContent = | ||
| __CHAT_CSS__ + __AUTOCOMPLETE_CSS__ + __SATELLITE_CSS__ + SKELETON_CSS; | ||
| style.textContent = __AUTOCOMPLETE_CSS__ + SKELETON_CSS; |
There was a problem hiding this comment.
Is it a change you forgot to undo? Chat is now unstyled for example.
There was a problem hiding this comment.
I removed it on purpose because the chat's CSS embarks a lot more styles than just the chat widget, it also comes with other InstantSearch styles including Autocomplete that were clashing with this new theme.
Since we're focusing on Autocomplete right now, we'll likely remove support for chat and other widgets for now, so I think it's okay to drop. When we introduce chat, we'll want to modularize its theming like we're doing with AC right now.
There was a problem hiding this comment.
Ok that's fine, we'll remove other widgets in another PR and reintroduce them progressively then.
Summary
This PR introduces
@experiences/theme, a new package that makes a Zod schema the single source of truth for all themeable CSS variables. The schema powers validation at the API boundary, AI tool definitions (via JSON Schema), and CSS generation from one place.This PR focuses on the
autocompletewidget.See the Themeable CSS + Zod Schema workstream for full context.
What changes
New
packages/themepackageA standalone package consumed by the runtime and toolbar.
autocompletewidget, declared with its key, type, default value (per light/dark mode), constraints, and description. ~80 variables organized by domain: colors, typography, shape & layout, and autocomplete-specific sub-domains (input, dropdown, results, section headers).autocompletewidget styles in thethemepackage so it owns both the variable definitions and the CSS that consumes them.ThemeVariable,ThemeVariableType,ShadowLayer,ThemeOverrides, andThemeOverrideValuetypes. Shadows use a structuredShadowLayer[]type instead of freeform CSS strings, each layer is an object with constrained fields.createThemeOverridesSchema(variables)turns the catalog into a Zod schema enforcing types, constraints, and light/dark mode structure..toJsonSchema()produces the AI tool definition so agents know exactly what to produce.generateThemeCss(variables, overrides)merges partial overrides with catalog defaults and outputs:root+ dark mode CSS blocks. Numbers get their unit appended, shadow layers serialize tobox-shadowsyntax. Every catalog variable is always present, no missing custom properties at runtime.Runtime integration
The middleware now uses
generateThemeCss()from the theme package instead of building CSS strings ad-hoc. This ensures themes always include defaults for missing variables and support light/dark mode.Example themes and theme switcher
Five themed override sets in all examples demonstrate the system across different aesthetics. A theme switcher UI lets you preview them in both demo apps.
Design decisions
stepis a UI hint, not validation: Slider step values (e.g.,step: 0.1) are not enforced viamultipleOfin the schema, because IEEE 754 floating point makes fractional multiples unreliable (0.15failsmultipleOf(0.1)). Min/max still constrain the range.0 0 0 1px rgba(23,23,23,0.05)are hard for humans and agents to produce and difficult to validate.ShadowLayer[]lets the schema validate each field individually while the system handles serialization.Exit criteria (workstream)
~80 autocomplete variables declared with types, per-mode defaults, min/max constraints, units, and descriptions. Every variable type has typed validation.
generateThemeCss(variables, overrides)merges partial overrides with catalog defaults and outputs:root+ dark mode CSS blocks with--ais-*custom properties.createThemeOverridesSchema(variables).toJsonSchema()produces a JSON Schema with per-variable types, constraints, format hints, defaults in descriptions, and light/dark mode structure.The middleware injects CSS generated by the theme package. Example themes demonstrate visual correctness across five aesthetics.