feat(toolbar): manual theme editor with presets#77
Merged
sarahdayan merged 29 commits intomainfrom Mar 12, 2026
Merged
Conversation
- 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>
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>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 8 curated theme presets (Default, Minimal, Bold, Soft, Warm, Nature, Elegant, Brutalist) with a preset selector UI in the theme editor. Each preset provides distinct light and dark overrides for colors, typography, borders, shadows, spacing, and more. - Add ThemePreset type and preset definitions in theme package - Add PresetSelector component with color swatch previews - Wire preset application through panel and app components - Move autocomplete files under autocomplete/ subfolder - Remove redundant theme switcher from examples - Fix hexToRgbTriplet spacing, shadow field double label, generateThemeCss null safety, and onSave dependency array Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove the redundant `themeMode` field from the API payload and
ExperienceApiResponse type. The mode is now inferred from the
cssVariables shape: flat object means fixed, `{ light, dark }` means
adaptive.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Theme CSS is now injected once from the top-level experience config instead of per-widget. Remove the onCssVariableChange callback chain, CssVariablesEditor component, and cssVariables from widget parameters. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Show an empty state with a link to the manual tab when no autocomplete widget is present in the experience. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Show a paintbrush icon in the autocomplete block card header (next to locate and delete) that navigates to the Theme tab. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4e4f3ba to
7728b4a
Compare
Neutral gray, compact preset for unbranded site search that blends into any page. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
# Conflicts: # examples/react/src/App.tsx # packages/runtime/src/experiences/middleware.ts # packages/runtime/src/experiences/widget.tsx # packages/runtime/tsdown.config.ts # packages/theme/package.json # packages/theme/src/lib/__tests__/create-theme-overrides-schema.test.ts # packages/theme/src/lib/__tests__/generate-theme-css.test.ts # packages/theme/src/lib/generate-theme-css.ts # packages/theme/src/types.ts
✅ 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. |
The merge brought in main's flat `autocomplete.ts` and `autocomplete.css` which are superseded by the subdirectory structure (`autocomplete/variables.ts`, `autocomplete/presets.ts`, `autocomplete/autocomplete.css`). Remove the duplicates and update the shared example import. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The toolbar's Theme tab replaces the dev theme switcher. The React example was cleaned up during the merge but the JS example was missed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Missed search.html and product.html in the previous cleanup. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…mponent The toolbar's Theme tab replaces the dev theme switcher. Remove examples/shared/, the Vite alias, and the unused React ThemeSwitcher component. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
dhayab
requested changes
Mar 12, 2026
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Loading an experience with a custom theme no longer marks variables as dirty. "Reset all" now restores the initially loaded theme rather than switching to the Default preset. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a full visual theme editor to the toolbar's Theme tab, driven by the variable catalog from
@experiences/theme. Users can customize all autocomplete CSS variables through type-appropriate controls, preview changes live, toggle between light and dark mode, and reset to defaults. Eight curated presets provide distinct starting points across different aesthetics.Enregistrement.de.l.ecran.2026-03-11.a.08.53.13.mov
This PR also cleans up the theme data model:
cssVariablesmoves from per-widget params to the experience level, and the redundantthemeModeAPI field is removed (the mode is inferred from the data shape).See the Manual Theme Editor workstream for full context.
Note
This PR depends on https://github.com/algolia/experience-management-api/pull/405 being merged and deployed
Exit criteria (workstream)
All autocomplete variables are rendered as interactive controls in the Theme tab. The editor reads the variable catalog and renders the appropriate control for each type.
Variables are folded under collapsible groups. Each header shows a badge with the count of modified variables.
CSS custom properties update in real time via a
<style>element injected on:root.A mode switcher is always visible at the top of the editor, with light/dark tabs to edit each mode independently:
Modified variables show an inline reset button. A global "Reset all" button restores every variable to catalog defaults. Modified state is visually indicated per-variable.
Overrides are stored at the experience level as
cssVariables. The theme mode (adaptive vs. fixed) is inferred from the data shape rather than stored as a separate field.Beyond exit criteria
cssVariablesmoved from per-widget params to experience level, redundantthemeModeAPI field removed, example theme switcher removed.