feat: bundle management in the Tracker UI, collection dialog redesign and browser UX fixes - #99
Merged
simoncodes-ca merged 13 commits intoSep 17, 2026
Conversation
- Initialize collection cache status as `not-started` - Add coverage for the pending cache status request
- Default compact mode to the base locale - Persist compact locale selections and update filter labels - Simplify compact row annotations and styling
Replace the flat stack of outlined fields with three labelled groups (Source, Locales, Options). Locales become pill chips with a BASE tag; clicking a chip sets the base while creating, and the base is locked while editing, including a base inherited from the global config. Read-only is a switch row with the node_modules auto-detection explained inline, and tags and protected terms sit behind a disclosure row with counts. Header, top rule and footer match the translation editor. Adds 17 collections.dialog.* resources via the CLI; other locales are left as new entries for translation. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Add the first token-bearing DESIGN.md with its design.json sidecar, derived from the shipped tokens and components, plus the surface brief holding the collection dialog's direction contract. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Bundle type generation lets the caller name the generated token constant, which has to be a valid JavaScript identifier. The check is a pure regex over a string, so it belongs in domain where the API, the CLI and the Tracker UI can all reach it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Bundles were generate-only and CLI-shaped. Three additions open them up to the API and the Tracker UI without changing what the CLI does: - planBundle: a dry run that never writes. Returns the files it would produce, whether each already exists, keys per locale, key conflicts and one worked example key, so a form can show the consequences of a definition before it is saved. - validateBundleDefinition: returns every problem with a definition rather than throwing on the first, so a form can mark all of its fields at once. - addBundleDefinition / updateBundleDefinition / deleteBundleDefinition: config-file CRUD that validates inside the updater and preserves key order. generateBundle grows an optional onProgress callback and reports keysPerLocale, which is what lets a caller drive a progress bar and a result summary. generateBundleTypes now accepts the definition it should use instead of always reading it back out of the config, so a dry run can type-check a definition that has not been saved. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contracts for the bundle endpoints, shared by the API and the Tracker UI: the definition itself, create/update payloads, the dry-run request and result, and the generation job snapshot. Plain interfaces with locally declared unions, so the browser never has to reach into core. LingoTrackerConfigDto also gains bundles and projectName; the config mapper was dropping bundles entirely and the UI has no other source for the served project's name. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
POST/PUT/DELETE /api/bundles for the definitions, POST /api/bundles/dry-run for a plan of an unsaved definition, and POST /api/bundles/:name/generate which answers 202 with a job id that GET /api/bundles/jobs/:jobId polls. Generation writes files and can take a while, so it follows the same job-and-poll shape as translation, with a promise queue that keeps runs sequential and eviction of finished jobs. GET /api/config now carries bundles, which the mapper used to drop, and projectName from the API process's working directory. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The collections page becomes a split view: collections on the left, a sticky column of bundle cards on the right. A bundle can be created, edited, deleted, generated on its own or with every other one, and its run reports progress and then a result strip inside its own card, so the developer never leaves the page to find out what was written. Hovering or focusing a bundle draws a coral connector from each collection it consumes into a single port on the bundle card, so several inputs visibly converge on one output. The connector layer sits behind the cards, which lets a line cross the inner column and re-emerge rather than scribbling over another card's content; the lines stand down once the layout stacks and there is no gutter to route through. The bundle form is a master-detail dialog: a sections rail, the form itself, and a live preview column driven by a debounced dry run that shows the files the definition would write, the counts, and one worked example key. Under 1200px the preview folds into a disclosure at the bottom of the pane and under 800px the rail becomes a horizontal strip. Run state is mirrored to session storage. Generating the tracker bundle rewrites the Tracker's own i18n assets, which reloads the dev server page mid-run, and without the mirror the result strip vanished the moment it was earned. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Surface briefs for the collections page and the bundle form dialog, plus the DESIGN.md entries the build settled: the bundle card and its result strip, the segmented control, the master-detail dialog, and the rules that came out of the polish pass. The Connector Rule replaces the Hover-Link Rule: a relationship is drawn from each input's edge into one port on the output rather than stated by dimming everything it excludes. Buttons gain a quiet third rung, because frequency should set prominence and a section's create action is not automatically its loudest. Collection cards move to equal rows, since a card is an identity rather than a measurement. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ning the editor Double-click on a translation row opened the edit dialog from anywhere on the card, which collided with the OS word-select gesture people use before Cmd+C. Values in both densities (compact value, base and locale values in full view, and the note) are now plain selectable text with a text cursor and a palette-tinted selection. Double-click on the header, drag glyph or labels still opens the editor, as do E, long-press and the actions menu. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
simoncodes-ca
approved these changes
Sep 17, 2026
|
🎉 This PR is included in version 0.19.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
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
Bundles become a first-class object across core, API and the Tracker UI, the collection dialogs get a redesign, and a handful of browser UX fixes land alongside. Twelve commits, all conventional-commit style.
Bundles end to end
core — Bundles were generate-only and CLI-shaped. New
planBundleruns a dry run that never writes and reports the files it would produce, keys per locale, key conflicts and one worked example key.validateBundleDefinitionreturns every problem at once instead of throwing on the first. Config-file CRUD (add/update/deleteBundleDefinition) validates inside the updater and preserves key order.generateBundlegains anonProgresscallback andkeysPerLocale;generateBundleTypesaccepts an unsaved definition.domain — Pure JavaScript identifier validation for the generated token constant name, reachable from CLI, API and UI.
data-transfer — Bundle DTOs: definition, create/update payloads, dry-run request and result, and the generation job snapshot.
LingoTrackerConfigDtonow carriesbundlesandprojectName, which the config mapper used to drop.api —
POST/PUT/DELETE /api/bundles,POST /api/bundles/dry-run, andPOST /api/bundles/:name/generate, which answers 202 with a job id polled viaGET /api/bundles/jobs/:jobId. Runs are sequential through a promise queue with eviction of finished jobs, mirroring the translation job shape.tracker — The collections page becomes a split view with a sticky column of bundle cards. A bundle can be created, edited, deleted and generated alone or all together; progress and a result strip render inside the card. Hover or focus draws a coral connector from each consumed collection into one port on the bundle. The bundle form is a master-detail dialog with a live preview column driven by a debounced dry run, folding responsively under 1200px and 800px. Run state is mirrored to session storage so a result survives the dev-server reload that generating the tracker's own bundle triggers.
Collection dialogs
Create and edit dialogs move from a flat stack of fields to three labelled groups (Source, Locales, Options). Locales are pill chips with a BASE tag; the base is set by clicking while creating and locked while editing. Read-only is a switch row with the
node_modulesauto-detection explained inline. Tags and protected terms sit behind a disclosure with counts. Adds 17collections.dialog.*resources.Browser fixes
E, long-press and the actions menu.Design records
DESIGN.mdwith adesign.jsonsidecar derived from shipped tokens, plus surface briefs for the collection dialog, collections page and bundle form. Records the Connector Rule, the quiet third button rung, and equal-row collection cards. Impeccable mock and review captures are gitignored.Testing
🤖 Generated with Claude Code