mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-08-27 04:07:05 +00:00
* 🎨 feat: Color the Context Gauge by Category and Collapse its Breakdown The context window bar becomes a stacked meter — one hue per category — and the breakdown collapses behind a disclosure so the gauge alone is the default view. The collapse choice persists per user. Adds a categorical series scale (`rgb-series-1`…`rgb-series-7`) to the versioned theme registry, so themes and `REACT_APP_THEME_SERIES_*` can retint it. Hues are anchored on LibreChat's own brand tokens; every step was computed rather than picked, by enumerating slot orderings and snapping each step until all gates passed in both modes: worst adjacent CVD ΔE 12.4 light / 13.0 dark (target 8) worst adjacent normal-vision 19.0 light / 19.0 dark (floor 15) contrast all 14 steps ≥ 3:1 on both the popover surface and the meter track Slot order is the colour-vision-deficiency safety mechanism, not cosmetics. Reserved status colors are never reused for series identity, and the circular composer gauge is deliberately untouched — it answers "how close am I to the limit", which stays a status question. - `SegmentedMeter` + `MeterSwatch` land beside `Progress` in `@librechat/client`, owning the 2px surface gaps, rounded ends, the min-width floor, and the hatch. The category-to-slot mapping stays feature-local: the palette is theme data, the mapping is not. - Every present category gets a 2px floor so a 251-token row cannot render as 0.09px; the shortfall comes out of free space, never another category. - Deferred tools keep their family's hue and add a 135° hatch, so a hue never means two things. Segments are reordered to put each deferred pair beside its parent, which is also the adjacency the palette was validated on. - Messages is drawn as a translucent fill with a solid edge: it is the only category the user grows, and the form difference doubles as secondary encoding. - A row carries a swatch if and only if it is a segment. The estimate path knows the total but not the composition, so it keeps a single unsegmented fill. - Usage totals gain a "Totals" heading, and row text lifts to primary ink on hover/focus. - The popover widens 256px → 288px to absorb the chevron and the legend swatches. Guardrails: the series scale is held to the 3:1 mark floor on both surfaces, the app CSS defaults are held in step with the runtime themes, and each slot is asserted to resolve to a Tailwind utility backed by its CSS variable. * 🐛 fix: Address Codex Review on the Segmented Context Gauge Three P2 findings, all confirmed. **Gaps inflated the fill.** Segment widths were percentages of the whole track while `gap-[2px]` was added on top, so the gaps ate into the free-space remainder instead of living inside the filled region. Measured on the real component: a window at 47.2% painted 55.6% full, and the bar read full at ~94%. Each segment now surrenders its share of the gap budget, so fills plus gaps span exactly the used fraction. Same case now paints 50.2%. The residual 3.0pp is the `SEGMENT_MIN` floor doing its job — five sub-pixel categories rounded up to 2px each. That overshoot is deliberate and bounded, it comes out of free space rather than a neighbouring category, and the doc comment now states the magnitude instead of leaving it implicit. **No reference-theme test.** The suite only exercised the bundled token tables, so it could not detect the shared component becoming coupled to LibreChat's values. Adds a deliberately different reference `ThemeDefinition` and asserts the registry accepts it, the values reach the applied CSS variables, and every rendered mark takes its colour from those variables — no literal colours in the tree. `SegmentedMeter.tsx` also joins the shared-primitive colour guardrail. **Series tokens missing from the public maps.** `IThemeVariables` and `IThemeColors` are exported for downstream consumers to type their CSS-variable and Tailwind maps, and would have rejected the new keys. Adds the series entries to both, plus a compile-time guard in the registry so a slot added to one map and missed in another fails the build. The guard deliberately lives in `registry.ts`, not the spec: `tsconfig.json` excludes `*.spec.ts`, so an assertion there is never checked by the build — verified by removing a key from each map in turn and confirming the error. * ✅ fix: Expand the Breakdown in the Context Gauge e2e Specs `e2e/specs/mock/usage.spec.ts` asserts on rows that now sit behind the disclosure, so four tests failed on the collapsed default. My miss — I updated the component spec and never grepped for e2e coverage. `openBreakdown` now expands the detail after opening, so every caller that reads a row keeps working; the helper is idempotent, since a reload restores an already-expanded preference. The one inline `gauge.click()` that duplicated the helper now uses it. Adds the case the regression should have been caught by, and which only e2e can reach: the popover opens to the gauge alone with no detail mounted, expanding reveals the labelled Totals section, and the choice survives a real reload through localStorage without a second click. `e2e/specs/real/usage.spec.ts` reads the totals the same way. It also hovered rather than clicked, which never opened the popover at all — hover surfaces only the compact snapshot tooltip, as the mock spec asserts. |
||
|---|---|---|
| .. | ||
| agent-handoff-mcp.spec.ts | ||
| subagent-results.spec.ts | ||
| tool-intents.spec.ts | ||
| usage.spec.ts | ||