Skip to content

feat(configurator): unified validated import + mobile preview dropdown (UX redesign, phase 7) - #697

Merged
jackgranatowski merged 4 commits into
mainfrom
ux/configurator-mobile-import
Aug 20, 2026
Merged

jackgranatowski merged 4 commits into
mainfrom
ux/configurator-mobile-import

Conversation

@jackgranatowski

Copy link
Copy Markdown
Contributor

Phase 7 of the configurator UX redesign — unified import & mobile preview

Stacked on #691#692#693#694#695#696. Merge those first; this branch includes their commits.

1. Unified, validated import

The header import had two silent, inconsistent paths: a .json file replaced the whole state with no validation, a .css file merged via a loose regex, and a file with nothing recognisable did nothing, with no feedback.

src/lib/importOverrides.ts is now one pipeline for both formats:

  1. detect JSON (flat map or a theme-file { tokens }) vs CSS,
  2. sanitise every value and drop keys that aren't a real --sf-* name or are empty/unsafe after sanitising,
  3. migrate renamed/removed tokens and flag unknown ones (reusing themeFile.migrateOverrides),
  4. return a report.

App.handleImport now merges the result (predictable and non-destructive for both formats) and shows a transient status banner"Imported N tokens · M migrated · K skipped" — so an import can never fail silently again. Header tooltip corrected to "Import overrides (CSS or JSON)".

2. Mobile preview template selector

The horizontal template tab strip was clipped in the narrow mobile viewport. It's now a compact <select> dropdown on mobile and the full tab strip on sm+.

Verification

  • npm run check: 0 errors · npm run lint: clean · build OK
  • npm run test: 282/282 (importOverrides 10) · shell e2e green
  • Screenshot-verified: import merge (a pre-seeded override survived, the imported one was added, banner "Imported 1 token · 1 skipped") and the mobile preview dropdown.

Scope / follow-ups

Lands the validated/merged import + mobile preview dropdown. A full mobile category drawer and an explicit merge-vs-replace chooser modal remain follow-ups — replace + rename migration is already available through the Install & export panel's theme-file import.

@coderabbitai

coderabbitai Bot commented Aug 19, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@jackgranatowski, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 8 minutes

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

Wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2c42fc1f-ca28-4251-b171-8c1cf406c0fd

📥 Commits

Reviewing files that changed from the base of the PR and between e36d416 and b482679.

📒 Files selected for processing (5)
  • configurator/src/App.svelte
  • configurator/src/components/shell/PreviewPanel.svelte
  • configurator/src/components/shell/StudioHeader.svelte
  • configurator/src/lib/importOverrides.ts
  • configurator/tests/importOverrides.test.ts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Aug 19, 2026

Copy link
Copy Markdown

Greptile Summary

The PR redesigns the configurator around metadata-driven token domains, token relationships, a Changes panel, unified value editing, validated imports, improved navigation, undo coalescing, and a mobile preview selector.

  • Replaces substring domain matching with a shared namespace map used by runtime classification and curation checks.
  • Adds token role, dependency, override-state, and generated-scale modeling with corresponding editing and Changes-panel UI.
  • Unifies CSS and JSON imports behind sanitization, migration, merging, and a transient status report.
  • Expands command-palette navigation and token deep-linking, and switches mobile preview templates to a dropdown.
  • Introduces time-based undo coalescing for repeated single-token updates.

Confidence Score: 2/5

The PR should not merge until Escape cancellation, interaction-aware undo grouping, and collision reporting for imported overrides are corrected.

The new editor persists values when users press Escape, rapid but separate same-token edits lose an undo boundary, and migration collisions can discard an imported override without appearing in the promised status report.

Files Needing Attention: configurator/src/components/inputs/ValueField.svelte, configurator/src/App.svelte, configurator/src/lib/importOverrides.ts

Important Files Changed

Filename Overview
configurator/src/App.svelte Integrates import reporting, search deep-links, and undo coalescing; time-only grouping merges distinct rapid edits into one undo step.
configurator/src/components/inputs/ValueField.svelte Adds explicit inherit, literal, and expression modes, but Escape triggers the blur commit it is intended to cancel.
configurator/src/lib/importOverrides.ts Adds the unified validated import pipeline, but omits migration collisions from its user-visible report.
configurator/src/lib/tokenModel.ts Centralizes token roles, dependency relationships, scale-shadow detection, validation, and change classification with extensive unit coverage.
configurator/src/lib/domains.ts Replaces overlapping substring patterns with deterministic manifest namespace classification and explicit exceptions.
configurator/src/components/shell/PreviewPanel.svelte Provides a compact mobile template selector while retaining desktop template tabs.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  F[CSS or JSON file] --> P[parseImport]
  P --> S[Sanitize names and values]
  S --> M[Migrate renamed and removed tokens]
  M --> R[Import report]
  M --> O[Validated overrides]
  O --> G[Merge into current overrides]
  G --> H[Undo and persistence state]
  R --> B[Transient status banner]
Loading

Reviews (1): Last reviewed commit: "feat(configurator): unified validated im..." | Re-trigger Greptile

onblur={(e) => { editing = false; commit((e.target as HTMLInputElement).value); }}
onkeydown={(e) => {
if (e.key === "Enter") (e.currentTarget as HTMLInputElement).blur();
if (e.key === "Escape") { editing = false; draft = overrideValue ?? token.value ?? ""; (e.currentTarget as HTMLInputElement).blur(); }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Escape commits cancelled edits

When a user edits a value and presses Escape, the handler immediately calls blur(), whose unconditional blur handler commits the input's still-edited DOM value. The value the user attempted to discard therefore becomes an active override.

Comment thread configurator/src/App.svelte Outdated
Comment on lines +123 to +125
// current single-token gesture.
if (!shouldCoalesce(coalesce, keys, now)) {
past = [...past.slice(-49), prev];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Undo merges separate interactions

When two separate edits to the same token complete within 600 milliseconds, shouldCoalesce suppresses the second history snapshot because grouping uses only the key and elapsed time. Undo then skips the intermediate value and reverses both interactions instead of only the latest edit.

Comment on lines +103 to +110
overrides: migrated.overrides,
report: {
format: isJson ? "json" : "css",
accepted: Object.keys(migrated.overrides).length,
renamed: migrated.renamed.length,
removed: migrated.removed.length,
unknown: migrated.unknown.length,
invalid,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Import collisions remain silent

When two legacy token names migrate to the same current token, migration drops one value and records a collision, but this report omits that collision. The import banner consequently reports success without telling the user that one override was discarded.

…e dropdown

Two phase-7 fixes.

1) Unified import (src/lib/importOverrides.ts). The header import had two silent,
   inconsistent paths — a .json REPLACED the whole state with no validation, a
   .css MERGED via a loose regex, and an unrecognisable file did nothing with no
   feedback. Now one pipeline handles both: detect JSON (flat map or a
   theme-file { tokens }) vs CSS, sanitise every value, drop keys that aren't a
   real --sf-* name or are empty/unsafe after sanitising, migrate renamed/
   removed tokens and flag unknown ones, and return a report. App.handleImport
   MERGES the result (predictable, non-destructive for both formats) and shows a
   transient status banner ("Imported N tokens · M migrated · K skipped"), so an
   import can no longer fail silently. Header tooltip fixed to "Import overrides
   (CSS or JSON)". parseImport/summarizeImport are unit-tested (10 tests).

2) Mobile preview template selector. The horizontal tab strip was clipped in the
   narrow mobile viewport; it's now a compact <select> dropdown on mobile and the
   full tab strip on sm+.

check + lint clean; 282 unit tests and the shell e2e suite pass; import merge +
banner and the mobile dropdown screenshot-verified.

Scope: lands the validated/merged import + mobile preview dropdown. A full
mobile category drawer and an explicit merge-vs-replace chooser modal remain
follow-ups (replace + rename migration is already available via the Install &
export panel's theme-file import).
@jackgranatowski
jackgranatowski force-pushed the ux/configurator-mobile-import branch from c952a7d to b482679 Compare August 20, 2026 12:50
@jackgranatowski
jackgranatowski merged commit f9311a4 into main Aug 20, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants