`** carries the class for nested cascade scoping
+ inside the app tree. Redundant with the html-level class but harmless — both elements match the
+ same rule and declare the same values.
### Enable locally
diff --git a/projects/84-ui-ux-design/NEXT-STEPS.md b/projects/84-ui-ux-design/NEXT-STEPS.md
index 83740aa72..d27a8f4e3 100644
--- a/projects/84-ui-ux-design/NEXT-STEPS.md
+++ b/projects/84-ui-ux-design/NEXT-STEPS.md
@@ -65,20 +65,13 @@ This is a _living_ document. Update it as decisions land and PRs ship. Cross-ref
In order:
-- [ ] Commit and open PR from `feat/84-pr1-theme-system` — code is complete, tests green, typecheck
- clean. See commit messages in the session log. No visible UI changes; verification via
- DevTools.
-- [ ] Merge `feat/84-layout-mockups` (planning artifacts) as its own PR so the docs are on `main`.
- Can happen in parallel with PR 1 review.
-- [ ] Re-scope and open PR from `feat/84-pr2-navbar` (branched off `feat/84-pr1-theme-system`, will
- be rebased onto `main` once PR 1 merges) — **post-pivot**: docs capture the `V1_REDESIGN`
- boundary-read pivot; navbar component, theme-toggle rewrite, icons, and CSS ship as
- **dormant** code (no consumer); `App.tsx` and `main.tsx` flag wiring reverted. Tests green,
- typecheck clean.
-- [ ] Open PR 2b (`feat/84-pr2b-v1-scaffolding`) — introduce `src/v1/`, write a minimal `
`
- mounting the dormant navbar + footer, move v1 chrome from `src/components/layout/` into
- `src/v1/components/layout/`, and add the single boundary read in `src/App.tsx`. First PR where
- the redesign is reachable on `feat/84-*` preview deploys.
+- [x] PR 1 (#377), PR 4 (#455), PR 2 (#453) — all merged on `main`.
+- [ ] Open PR 2b (`feat/84-pr2b-v1-scaffolding`) — branch off `main`, introduce `src/v1/`, extract
+ `
` into `src/LegacyApp.tsx`, write `
` mirroring legacy routes (renders
+ existing page components under v1 chrome until Phases 2-5 swap them), move dormant navbar +
+ theme-toggle + icons + CSS into `src/v1/`, and add the single `isEnabled("V1_REDESIGN")`
+ boundary read in `src/App.tsx`. First PR where the redesign is reachable on `feat/84-*`
+ preview deploys.
- [ ] Start PR 3 (`feat/84-pr3-subnav`) once PR 2b is in review.
---
@@ -91,18 +84,18 @@ boundary read in `src/App.tsx`, not per-component sprawl; v1 chrome and pages li
the existing `netlify.toml` `feat/84-*` pattern selects which sub-app each Netlify deploy bundles.
Reviewable by one person.
-| # | PR | Scope | Blocks | Status |
-| --- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------- | --------------------------- |
-| 0 | Add `V1_REDESIGN` flag | One line in `src/lib/feature-flags.ts`. Ships as a no-op. | All other foundation PRs | ✅ Done (on `main`) |
-| 1 | Theme system | `src/styles/` folder (modular CSS partials). Light + dark + auto switching. No-flash init script in `index.html`. Reconcile dark surface tokens. Persist to `localStorage["td-color-theme"]`. `
` authored (not rendered). **Note:** dark-surface reconciliation is global (no `V1_REDESIGN` gate); light theme, persistence, and toggle are additive with no consumer until PR 2. | PR 2 (toggle lives in NavBar) | 🚧 Implemented — pending PR |
-| 2 | NavBar v1 | **Re-scoped 2026-05-13 (pivot):** navbar component, theme-toggle rewrite, icons, and CSS ship as **dormant** code in `src/components/`; `App.tsx`/`main.tsx` flag wiring reverted; docs capture the pivot. opentelemetry.io-style chrome (always-dark): single "Docs" link, "OpenTelemetry" brand text + `OtelLogo` placeholder, `
`. Search and language switcher deferred. | PR 2b | 🚧 Re-scoped — pending PR |
-| 2b | v1 scaffolding | Introduce `src/v1/`; move dormant navbar into `src/v1/components/layout/`; add minimal `
` mounting the navbar + a placeholder home (chrome-only until Phase 2 ships a real one); `src/App.tsx` adds the single boundary read swapping `
` for `
`. Canonical paths (no `/v1/*` prefix); per-deploy bundle via existing `netlify.toml` pattern. | PR 3 (SubNav sits beneath it) | — |
-| 3 | SubNav | Breadcrumb component + optional right-side actions slot. Used by inner pages. Lives in `src/v1/components/layout/`. | Phases 2-5 | — |
-| 4 | StatusPill + GlowBadge `secondary` + `error` variants | Add `
` covering all six OTel stability levels (development / alpha / beta / stable / deprecated / unmaintained). Leave legacy `StabilityBadge` untouched; migrate in a follow-up cleanup PR. | Phases 3, 4 | — |
-| 5 | TypeStripe + Card primitive update | 4px left-edge stripe primitive (5 colors) + extend `DetailCard` with the stripe slot (not `NavigationCard` — too specialized). | Phases 3, 4 | — |
-| 6 | FooterV1 + CncfCallout | Two-cluster Docsy-style footer + CNCF callout above it. Inline SVGs for Bluesky / Mastodon / Stack Overflow icons (assuming we go with the recommended icon strategy). Both live in `src/v1/components/layout/`. | — | — |
-| 7 | Playwright visual regression baseline | Configure Playwright. Snapshot each primitive in light + dark. Add `axe-core` for a11y. | Phase 1 cleanup | — |
-| 8 | Cleanup | Remove the `V1_REDESIGN` boundary read in `src/App.tsx`; delete the `` branch and the legacy `Header` / `Footer` plus replaced `src/features/...` content; remove the `V1_REDESIGN` entry from `lib/feature-flags.ts` and the `feat/84-*` pattern from `netlify.toml`; update `DESIGN.md` to reflect as-built. | Phase 2 | — |
+| # | PR | Scope | Blocks | Status |
+| --- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | --------------------------- |
+| 0 | Add `V1_REDESIGN` flag | One line in `src/lib/feature-flags.ts`. Ships as a no-op. | All other foundation PRs | ✅ Done (on `main`) |
+| 1 | Theme system | `src/styles/` folder (modular CSS partials). Light + dark + auto switching. No-flash init script in `index.html`. Reconcile dark surface tokens. Persist to `localStorage["td-color-theme"]`. `` authored (not rendered). **Note:** dark-surface reconciliation is global (no `V1_REDESIGN` gate); light theme, persistence, and toggle are additive with no consumer until PR 2. | PR 2 (toggle lives in NavBar) | 🚧 Implemented — pending PR |
+| 2 | NavBar v1 | **Re-scoped 2026-05-13 (pivot):** navbar component, theme-toggle rewrite, icons, and CSS ship as **dormant** code in `src/components/`; `App.tsx`/`main.tsx` flag wiring reverted; docs capture the pivot. opentelemetry.io-style chrome (always-dark): single "Docs" link, "OpenTelemetry" brand text + `OtelLogo` placeholder, ``. Search and language switcher deferred. | PR 2b | ✅ Done (#453) |
+| 2b | v1 scaffolding | Introduce `src/v1/`; move dormant navbar/theme-toggle/icons into `src/v1/`; extract `` into `src/LegacyApp.tsx`; add `` mirroring legacy routes (rendering existing page components under v1 chrome until Phase 2-5 swap them); `src/App.tsx` reduces to a single `isEnabled("V1_REDESIGN")` boundary read. v1 chrome reuses legacy `` as a placeholder until PR 6. CSS scoped via `.v1-app` class wrapper. Canonical paths; per-deploy bundle via existing `netlify.toml` pattern. | PR 3 (SubNav sits beneath it) | 🚧 Pending PR |
+| 3 | SubNav | Breadcrumb component + optional right-side actions slot. Used by inner pages. Lives in `src/v1/components/layout/`. | Phases 2-5 | — |
+| 4 | StatusPill + GlowBadge `secondary` + `error` variants | Add `` covering all six OTel stability levels (development / alpha / beta / stable / deprecated / unmaintained). Leave legacy `StabilityBadge` untouched; migrate in a follow-up cleanup PR. | Phases 3, 4 | — |
+| 5 | TypeStripe + Card primitive update | 4px left-edge stripe primitive (5 colors) + extend `DetailCard` with the stripe slot (not `NavigationCard` — too specialized). | Phases 3, 4 | — |
+| 6 | FooterV1 + CncfCallout | Two-cluster Docsy-style footer + CNCF callout above it. Inline SVGs for Bluesky / Mastodon / Stack Overflow icons (assuming we go with the recommended icon strategy). Both live in `src/v1/components/layout/`. | — | — |
+| 7 | Playwright visual regression baseline | Configure Playwright. Snapshot each primitive in light + dark. Add `axe-core` for a11y. | Phase 1 cleanup | — |
+| 8 | Cleanup | Remove the `V1_REDESIGN` boundary read in `src/App.tsx`; delete the `` branch and the legacy `Header` / `Footer` plus replaced `src/features/...` content; remove the `V1_REDESIGN` entry from `lib/feature-flags.ts` and the `feat/84-*` pattern from `netlify.toml`; update `DESIGN.md` to reflect as-built. | Phase 2 | — |
PR 8 is the **go-live** moment — once it merges, Phase 1 is done and the new chrome ships to
production.
@@ -214,34 +207,35 @@ Surface early so it's not blocking when PR 04b is ready.
## Decision log
-| Date | Decision | Notes |
-| ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| 2026-04-30 | Direction: "The Catalog" with borrowed elements from Atlas + Dashboard | See design brief. v1 spine: searchable, comparable, version-aware database. |
-| 2026-04-30 | Align visual chrome with opentelemetry.io | Same nav, footer, hero, stats, theme system, brand colors. Sub-product, not a separate microsite. |
-| 2026-05-05 | Stage Phase 1 into 9 PRs gated by `V1_REDESIGN` flag | See "Phase 1 PR sequence" above. Avoids one big-bang PR. |
-| 2026-05-05 | Reuse existing feature-flag system at `src/lib/feature-flags.ts` | Already in production use; no new infrastructure. |
-| 2026-05-05 | Migration strategy: feature-flagged side-by-side, swap in cleanup PR | Per Vitor's choice in our sync. |
-| 2026-05-05 | Set up `CLAUDE.local.md` (gitignored) with handling rules for `projects/` during the refactor | Personal session context for Claude; not shared with the project. Ensures continuity across sessions. |
-| 2026-05-06 | Netlify previews enable `V1_REDESIGN` automatically for `feat/84-*` branches via build-command pattern matching in `netlify.toml` | Reviewers see the flag-on view per PR with no manual env-var setup. Production stays off. |
-| 2026-05-06 | Keep `data-theme` (not `data-bs-theme`) on `` for the theme attribute | Foundation audit Q1. opentelemetry.io uses `data-bs-theme` because Hugo Docsy is Bootstrap-based; the explorer is on Tailwind v4 with no Bootstrap. Visual alignment is driven by colors / layout / patterns, not the attribute name. Smaller PR diff and more honest naming. |
-| 2026-05-06 | Stick with the local `OtelLogo` component for the navbar lockup | Foundation audit Q2. Self-contained, no extra fetch dependency, already used elsewhere in the codebase. |
-| 2026-05-06 | Footer icons: inline SVGs for missing brand marks (Bluesky, Mastodon, Stack Overflow); Lucide for everything else | Foundation audit Q3 — option (c). Avoids adding ~75kb of Font Awesome for a handful of icons; keeps the bundle lean. |
-| 2026-05-06 | `` ships in PR 4 alongside ``; migrate the configuration builder to `` in a follow-up cleanup PR after Phase 1 | Foundation audit Q4. `` is narrow (one state, specific to the Java config builder). Building `` without churning the configuration builder keeps PR 4 small and decouples the visual-decision risk. |
-| 2026-05-06 | Status terminology follows the [OTel collector stability spec](https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md) — six levels: development / alpha / beta / stable / deprecated / unmaintained | Foundation audit Q5. Color mapping: development=secondary (gray), alpha=warning (orange), beta=info (blue), stable=success (green), deprecated=danger (red), unmaintained=danger (red). Mirrors the collector's vocabulary so anyone reading both sources sees the same terms. |
-| 2026-05-06 | PR 0 confirmed done — `V1_REDESIGN` is already in `src/lib/feature-flags.ts` on `main` | Added alongside `JAVA_RELEASE_COMPARISON` in a prior merge. `netlify.toml` was also already wired for `feat/84-*` previews. Flag is a no-op until PR 2 wires it into `App.tsx`. First real work is PR 1. |
-| 2026-05-06 | PR 5 will extend `DetailCard`, not `NavigationCard` | Verified by reading both components. `DetailCard` is a general-purpose wrapper (`children` + `className` passthrough) — clean fit for a `typeStripe` prop. `NavigationCard` is specialized (hardcoded icon box, arrow, corner accent); restructuring it for the stripe slot is not worth the churn. |
-| 2026-05-06 | Branch `feat/84-pr1-theme-system` created from `feat/84-layout-mockups` | PR 1 stacks on the planning branch so planning artifacts and first code PR can ship together (separate reviews). |
-| 2026-05-06 | No SCSS — use pure CSS partials in `src/styles/` (Tailwind v4 is the preprocessor) | Tailwind v4 [explicitly recommends against SCSS/Less/Stylus](https://tailwindcss.com/docs/compatibility#sass-less-and-stylus); it ships nesting, `@import` bundling, and vendor prefixing via Lightning CSS. All architecture goals (declared variables, folder structure, separation of concerns) achieved with plain CSS. |
-| 2026-05-06 | Brand realignment (`primary = blue`, `secondary = orange`) confirmed already on `main`; PR 1 does not flip these values | Re-reading `src/index.css` during the session revealed the canonical hues are already in place. PR 1 only reconciles the five remaining dark surface tokens (card/muted/border) and adds the light theme block. |
-| 2026-05-06 | PR 1 `theme-context.tsx` API: `{ mode, resolved, setMode }` — `mode` is the user preference (`light`/`dark`/`auto`), `resolved` is what's applied to the document | Cleaner than the old `{ themeId, setThemeId }` API. CSS owns values via `[data-theme]`; JS only sets the attribute. `useTheme` has zero non-test production consumers so the API reshaping is free. |
-| 2026-05-07 | PR 1 dark-surface reconciliation lands globally on `main`; `V1_REDESIGN` gates UI components/layout, not the base palette | Brand hues already on `main`; only the secondary surface tokens shift, and only for dark-theme users. Keeps PR 1 small and avoids a CSS indirection that PR 8 cleanup would have to unwind. |
-| 2026-05-07 | Drop `dark-blue` alias from `themes.ts` — the prior theme code never wrote to `localStorage`, so the alias was dead code with no real users behind it | The `td-color-theme` storage key is brand-new in PR 1; no migration needed. |
-| 2026-05-11 | Hero restored to orange-dominant after primary/secondary swap | Compass glow + ambient radial use `--otel-orange-hsl`; text gradient runs blue→orange. Addresses Jay's PR review feedback that "all the oranges turned blue except for the compass center dot." |
-| 2026-05-11 | PR 2 scope cut to a minimal Docs-only navbar; search input, language switcher, and the opentelemetry.io multi-link strip deferred to later phases | Per Vitor: visual parity with opentelemetry.io's chrome matters, exact link list doesn't. Single "Docs" link → `https://opentelemetry.io/docs/`. Brand text "OpenTelemetry"; logo mocked with existing `OtelLogo` until upstream horizontal SVG is provided. Always-dark surface tokens added to `src/styles/tokens.css`. |
-| 2026-05-11 | PR 2 navbar metrics re-anchored to the opentelemetry.io source (local clone at `/Users/vasconcellos/projetos/opentelemetry/opentelemetry.io`) instead of the static mockup | Mockup colors and heights diverged from the live site. Tokens now mirror `_navbar.scss`/`navbar.html` verbatim: bg `#3d4c86`, logo SVG 48px (white via `currentColor`), no border-bottom, nav-link 16px/600, min-height 104px (pixel-anchored because the explorer uses 14px rem). New `OpenTelemetryWordmark` component bundles the upstream SVG (mark + wordmark in one piece). |
-| 2026-05-11 | `` rebuilt as a 3-option Radix dropdown to mirror opentelemetry.io's Bootstrap theme-toggler (Light · Dark · Auto rows visible at once, circle-half trigger) | Was a click-to-cycle button in PR 1; opentelemetry.io ships a dropdown so users can see all options. Radix `react-dropdown-menu` added as a dep alongside the existing Radix primitives. Storage contract (`td-color-theme`, `mode`/`resolved`/`setMode`) is unchanged. |
-| 2026-05-11 | Future redesign work treats the local `opentelemetry.io` clone as source of truth for shared chrome — see the new section in `CLAUDE.local.md` | The mockup is a sketch; the live site is authoritative for navbar/footer/theme-toggle/CNCF/brand metrics. Always grep `assets/scss/_navbar.scss`, `themes/docsy/layouts/_partials/`, and quote actual values. |
-| 2026-05-11 | PR 2 navbar implementation switched from Tailwind utilities to **scoped CSS partials** (`src/styles/navbar.css`, `src/styles/theme-toggle.css`) that mirror the upstream SCSS verbatim | Tailwind utilities couldn't express `text-decoration-thickness` / `text-underline-offset` and the growing arbitrary-value soup was hard to keep in sync with opentelemetry.io. Pixel-anchored at 16px-rem inside `.td-navbar` to neutralise the explorer's global 14px rem. Restored `position: fixed` + `min-height: 64px` (was 104px, which is mobile-stacked metrics misapplied to desktop). Right-alignment now via `.td-navbar-nav-scroll { margin-left: auto }` wrapper, mirroring upstream. Hover renders a 3px orange underline at 0.5em offset. Theme-toggle icons switched from Lucide to inline Bootstrap-Icons SVGs (`sun-fill`, `moon-stars-fill`, `circle-half`); active row indicated by background colour only (no checkmark, matching upstream). Trigger icon mirrors current mode. |
-| 2026-05-12 | Pivot: `V1_REDESIGN` gates at the router boundary (single read in `App.tsx` swapping `` for ``), not per-component. New `src/v1/` directory owns chrome + page-level features; primitives stay in `src/components/ui/`. Per-deploy bundle via existing `netlify.toml` pattern. | Decided on the OpenTelemetry Communications SIG call ([Zoom recording](https://zoom.us/rec/play/6w6ij69psp17Vo3GaZeaarr7mDGOfrUNE2m7HuIDb1XCwKvmnBWzWkcli9lU3Q3xMyqeFa3aNxyFWJs.WcZZoY03UygQ-toH)); refined via grilling on 2026-05-13. See [`v1-routing-pivot.md`](./v1-routing-pivot.md). Supersedes the 2026-05-05 rows "Stage Phase 1 into 9 PRs gated by V1_REDESIGN" and "Migration strategy: feature-flagged side-by-side". PR 2 (#453) re-scoped to docs + dormant code; new PR 2b adds the scaffolding. |
+| Date | Decision | Notes |
+| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| 2026-04-30 | Direction: "The Catalog" with borrowed elements from Atlas + Dashboard | See design brief. v1 spine: searchable, comparable, version-aware database. |
+| 2026-04-30 | Align visual chrome with opentelemetry.io | Same nav, footer, hero, stats, theme system, brand colors. Sub-product, not a separate microsite. |
+| 2026-05-05 | Stage Phase 1 into 9 PRs gated by `V1_REDESIGN` flag | See "Phase 1 PR sequence" above. Avoids one big-bang PR. |
+| 2026-05-05 | Reuse existing feature-flag system at `src/lib/feature-flags.ts` | Already in production use; no new infrastructure. |
+| 2026-05-05 | Migration strategy: feature-flagged side-by-side, swap in cleanup PR | Per Vitor's choice in our sync. |
+| 2026-05-05 | Set up `CLAUDE.local.md` (gitignored) with handling rules for `projects/` during the refactor | Personal session context for Claude; not shared with the project. Ensures continuity across sessions. |
+| 2026-05-06 | Netlify previews enable `V1_REDESIGN` automatically for `feat/84-*` branches via build-command pattern matching in `netlify.toml` | Reviewers see the flag-on view per PR with no manual env-var setup. Production stays off. |
+| 2026-05-06 | Keep `data-theme` (not `data-bs-theme`) on `` for the theme attribute | Foundation audit Q1. opentelemetry.io uses `data-bs-theme` because Hugo Docsy is Bootstrap-based; the explorer is on Tailwind v4 with no Bootstrap. Visual alignment is driven by colors / layout / patterns, not the attribute name. Smaller PR diff and more honest naming. |
+| 2026-05-06 | Stick with the local `OtelLogo` component for the navbar lockup | Foundation audit Q2. Self-contained, no extra fetch dependency, already used elsewhere in the codebase. |
+| 2026-05-06 | Footer icons: inline SVGs for missing brand marks (Bluesky, Mastodon, Stack Overflow); Lucide for everything else | Foundation audit Q3 — option (c). Avoids adding ~75kb of Font Awesome for a handful of icons; keeps the bundle lean. |
+| 2026-05-06 | `` ships in PR 4 alongside ``; migrate the configuration builder to `` in a follow-up cleanup PR after Phase 1 | Foundation audit Q4. `` is narrow (one state, specific to the Java config builder). Building `` without churning the configuration builder keeps PR 4 small and decouples the visual-decision risk. |
+| 2026-05-06 | Status terminology follows the [OTel collector stability spec](https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md) — six levels: development / alpha / beta / stable / deprecated / unmaintained | Foundation audit Q5. Color mapping: development=secondary (gray), alpha=warning (orange), beta=info (blue), stable=success (green), deprecated=danger (red), unmaintained=danger (red). Mirrors the collector's vocabulary so anyone reading both sources sees the same terms. |
+| 2026-05-06 | PR 0 confirmed done — `V1_REDESIGN` is already in `src/lib/feature-flags.ts` on `main` | Added alongside `JAVA_RELEASE_COMPARISON` in a prior merge. `netlify.toml` was also already wired for `feat/84-*` previews. Flag is a no-op until PR 2 wires it into `App.tsx`. First real work is PR 1. |
+| 2026-05-06 | PR 5 will extend `DetailCard`, not `NavigationCard` | Verified by reading both components. `DetailCard` is a general-purpose wrapper (`children` + `className` passthrough) — clean fit for a `typeStripe` prop. `NavigationCard` is specialized (hardcoded icon box, arrow, corner accent); restructuring it for the stripe slot is not worth the churn. |
+| 2026-05-06 | Branch `feat/84-pr1-theme-system` created from `feat/84-layout-mockups` | PR 1 stacks on the planning branch so planning artifacts and first code PR can ship together (separate reviews). |
+| 2026-05-06 | No SCSS — use pure CSS partials in `src/styles/` (Tailwind v4 is the preprocessor) | Tailwind v4 [explicitly recommends against SCSS/Less/Stylus](https://tailwindcss.com/docs/compatibility#sass-less-and-stylus); it ships nesting, `@import` bundling, and vendor prefixing via Lightning CSS. All architecture goals (declared variables, folder structure, separation of concerns) achieved with plain CSS. |
+| 2026-05-06 | Brand realignment (`primary = blue`, `secondary = orange`) confirmed already on `main`; PR 1 does not flip these values | Re-reading `src/index.css` during the session revealed the canonical hues are already in place. PR 1 only reconciles the five remaining dark surface tokens (card/muted/border) and adds the light theme block. |
+| 2026-05-06 | PR 1 `theme-context.tsx` API: `{ mode, resolved, setMode }` — `mode` is the user preference (`light`/`dark`/`auto`), `resolved` is what's applied to the document | Cleaner than the old `{ themeId, setThemeId }` API. CSS owns values via `[data-theme]`; JS only sets the attribute. `useTheme` has zero non-test production consumers so the API reshaping is free. |
+| 2026-05-07 | PR 1 dark-surface reconciliation lands globally on `main`; `V1_REDESIGN` gates UI components/layout, not the base palette | Brand hues already on `main`; only the secondary surface tokens shift, and only for dark-theme users. Keeps PR 1 small and avoids a CSS indirection that PR 8 cleanup would have to unwind. |
+| 2026-05-07 | Drop `dark-blue` alias from `themes.ts` — the prior theme code never wrote to `localStorage`, so the alias was dead code with no real users behind it | The `td-color-theme` storage key is brand-new in PR 1; no migration needed. |
+| 2026-05-11 | Hero restored to orange-dominant after primary/secondary swap | Compass glow + ambient radial use `--otel-orange-hsl`; text gradient runs blue→orange. Addresses Jay's PR review feedback that "all the oranges turned blue except for the compass center dot." |
+| 2026-05-11 | PR 2 scope cut to a minimal Docs-only navbar; search input, language switcher, and the opentelemetry.io multi-link strip deferred to later phases | Per Vitor: visual parity with opentelemetry.io's chrome matters, exact link list doesn't. Single "Docs" link → `https://opentelemetry.io/docs/`. Brand text "OpenTelemetry"; logo mocked with existing `OtelLogo` until upstream horizontal SVG is provided. Always-dark surface tokens added to `src/styles/tokens.css`. |
+| 2026-05-11 | PR 2 navbar metrics re-anchored to the opentelemetry.io source (local clone at `/Users/vasconcellos/projetos/opentelemetry/opentelemetry.io`) instead of the static mockup | Mockup colors and heights diverged from the live site. Tokens now mirror `_navbar.scss`/`navbar.html` verbatim: bg `#3d4c86`, logo SVG 48px (white via `currentColor`), no border-bottom, nav-link 16px/600, min-height 104px (pixel-anchored because the explorer uses 14px rem). New `OpenTelemetryWordmark` component bundles the upstream SVG (mark + wordmark in one piece). |
+| 2026-05-11 | `` rebuilt as a 3-option Radix dropdown to mirror opentelemetry.io's Bootstrap theme-toggler (Light · Dark · Auto rows visible at once, circle-half trigger) | Was a click-to-cycle button in PR 1; opentelemetry.io ships a dropdown so users can see all options. Radix `react-dropdown-menu` added as a dep alongside the existing Radix primitives. Storage contract (`td-color-theme`, `mode`/`resolved`/`setMode`) is unchanged. |
+| 2026-05-11 | Future redesign work treats the local `opentelemetry.io` clone as source of truth for shared chrome — see the new section in `CLAUDE.local.md` | The mockup is a sketch; the live site is authoritative for navbar/footer/theme-toggle/CNCF/brand metrics. Always grep `assets/scss/_navbar.scss`, `themes/docsy/layouts/_partials/`, and quote actual values. |
+| 2026-05-11 | PR 2 navbar implementation switched from Tailwind utilities to **scoped CSS partials** (`src/styles/navbar.css`, `src/styles/theme-toggle.css`) that mirror the upstream SCSS verbatim | Tailwind utilities couldn't express `text-decoration-thickness` / `text-underline-offset` and the growing arbitrary-value soup was hard to keep in sync with opentelemetry.io. Pixel-anchored at 16px-rem inside `.td-navbar` to neutralise the explorer's global 14px rem. Restored `position: fixed` + `min-height: 64px` (was 104px, which is mobile-stacked metrics misapplied to desktop). Right-alignment now via `.td-navbar-nav-scroll { margin-left: auto }` wrapper, mirroring upstream. Hover renders a 3px orange underline at 0.5em offset. Theme-toggle icons switched from Lucide to inline Bootstrap-Icons SVGs (`sun-fill`, `moon-stars-fill`, `circle-half`); active row indicated by background colour only (no checkmark, matching upstream). Trigger icon mirrors current mode. |
+| 2026-05-12 | Pivot: `V1_REDESIGN` gates at the router boundary (single read in `App.tsx` swapping `` for ``), not per-component. New `src/v1/` directory owns chrome + page-level features; primitives stay in `src/components/ui/`. Per-deploy bundle via existing `netlify.toml` pattern. | Decided on the OpenTelemetry Communications SIG call ([Zoom recording](https://zoom.us/rec/play/6w6ij69psp17Vo3GaZeaarr7mDGOfrUNE2m7HuIDb1XCwKvmnBWzWkcli9lU3Q3xMyqeFa3aNxyFWJs.WcZZoY03UygQ-toH)); refined via grilling on 2026-05-13. See [`v1-routing-pivot.md`](./v1-routing-pivot.md). Supersedes the 2026-05-05 rows "Stage Phase 1 into 9 PRs gated by V1_REDESIGN" and "Migration strategy: feature-flagged side-by-side". PR 2 (#453) re-scoped to docs + dormant code; new PR 2b adds the scaffolding. |
+| 2026-05-13 | PR 2b shape locked via grilling: PR 6 stays separate; `` mirrors legacy routes rendering existing page components inside v1 chrome (each phase swaps its route's component); boundary read uses `isEnabled("V1_REDESIGN")` and both branches ship in both bundles (computed-key env access skips Vite's constant-fold); `` lives at `src/LegacyApp.tsx`; v1 reuses legacy `` as placeholder until PR 6; CSS scoped via `.v1-app` class applied both to `` (via a single carve-out flag read in `main.tsx`, restoring the body-bg behavior reverted by PR 453) and to ``'s wrapper div. | Trade-offs: convention consistency for the boundary read over per-deploy bundle separation (~5KB JS + ~11KB CSS unused per build, acceptable). The `main.tsx` carve-out exists so body bg paints against v1 surface tokens from the first paint — body itself lives outside ``'s wrapper subtree, so the cascade only reaches body when `.v1-app` is on ``. PR 8 cleanup removes both the carve-out and the App.tsx boundary read. Each Phase 2-5 PR edits `V1App.tsx`'s route table to swap in its v1 component; `LegacyApp.tsx`'s table is frozen until PR 8 deletes it. Resolves the foundation-audit "PR 2b decides CSS scoping" open question. |
Add a row whenever a decision lands. Keeps the doc honest.
diff --git a/projects/84-ui-ux-design/v1-routing-pivot.md b/projects/84-ui-ux-design/v1-routing-pivot.md
index 97f528012..ec2a9d319 100644
--- a/projects/84-ui-ux-design/v1-routing-pivot.md
+++ b/projects/84-ui-ux-design/v1-routing-pivot.md
@@ -53,27 +53,44 @@ Concretely:
top-level component `` defines its own ``.
- **`src/App.tsx` reduces to a single boundary read:**
`isEnabled("V1_REDESIGN") ? : `. That is the only place `V1_REDESIGN` is
- referenced in runtime code. No flag reads in `main.tsx`, no flag reads inside components, no
- `data-v1-redesign` attribute on ``.
+ referenced for application routing decisions. No `data-v1-redesign` attribute on `` (the
+ class-based scoping below replaces it).
+- **One narrow carve-out in `main.tsx` for early-paint styling.** `main.tsx` reads the flag once to
+ add the `.v1-app` class to `` before React mounts. This keeps body bg painted against v1
+ surface tokens from the first paint (zero navy-to-v1 flash during the React mount window). The
+ check uses the same `isEnabled("V1_REDESIGN")` API as the App.tsx boundary read, so it's a runtime
+ check that fires once at module load, not a build-time constant. CSS variables declared on
+ `.v1-app` cascade through `` via `body { background-color: hsl(var(--background-hsl)) }` in
+ `src/styles/base.css`. PR 2b implements this; PR 8 cleanup removes it along with the App.tsx
+ boundary read.
- **No URL prefix.** v1 mounts at the canonical paths (`/`, `/java-agent/...`, etc.). Both sub-apps
own the same path space; the boundary read decides which one is reachable.
- **Per-deploy bundle selection.** The existing `netlify.toml` pattern (`feat/84-*` branches set
- `VITE_FEATURE_FLAG_V1_REDESIGN=true`) is unchanged. Tree-shaking strips the unreachable branch
- from each build: `feat/84-*` previews ship v1 only; `main` and production ship legacy only.
- Reviewers compare a PR's preview to the production URL side-by-side in two tabs.
+ `VITE_FEATURE_FLAG_V1_REDESIGN=true`) is unchanged. The boundary read is a runtime check, not a
+ build-time switch: `isEnabled("V1_REDESIGN")` reads `import.meta.env` via a computed key, which
+ Vite's static-replacement pass cannot constant-fold. Both `` and `` ship in
+ both bundles (~5KB JS + ~11KB CSS unused per build); the runtime check picks which one mounts.
+ Tree-shaking the unreachable branch is aspirational and would require either switching the
+ boundary to literal-key `import.meta.env.VITE_FEATURE_FLAG_V1_REDESIGN` or using `React.lazy()`
+ for explicit code-splitting. Accepted trade-off for convention consistency with the rest of the
+ codebase's flag reads. Reviewers compare a PR's preview to the production URL side-by-side in two
+ tabs.
**Shared-primitives placement.** Cross-cutting primitives stay in `src/components/ui/` — that
includes `StatusPill`, `GlowBadge`, `ThemeToggle`, and future `TypeStripe` / `Card` work. Chrome and
page-level features that exist only for v1 live under `src/v1/`. No retroactive moves of code
already merged on `main` (PR 1 theme system, PR 4 StatusPill).
-**Cutover model.** The cleanup PR (PR 8) does four things in one diff:
+**Cutover model.** The cleanup PR (PR 8) does five things in one diff:
1. Removes the `isEnabled("V1_REDESIGN")` read in `src/App.tsx`.
-2. Deletes the `` branch.
-3. Deletes legacy chrome (`src/components/layout/header.tsx`, the legacy `Footer`) and legacy
+2. Removes the `main.tsx` carve-out that adds `.v1-app` to `` pre-mount (after cutover, v1 is
+ unconditional, so the class can move to a static `` in `index.html` — or the
+ v1 surface tokens can move back to `:root` since they're the only palette).
+3. Deletes the `` branch.
+4. Deletes legacy chrome (`src/components/layout/header.tsx`, the legacy `Footer`) and legacy
feature directories that v1 has replaced.
-4. Removes the `V1_REDESIGN` entry from `src/lib/feature-flags.ts` and the `feat/84-*` pattern from
+5. Removes the `V1_REDESIGN` entry from `src/lib/feature-flags.ts` and the `feat/84-*` pattern from
`netlify.toml`.
After cutover, v1 is the only app. `src/v1/` stays in place; a future flattening (hoisting
@@ -94,7 +111,10 @@ After cutover, v1 is the only app. `src/v1/` stays in place; a future flattening
- **PRs 4 (StatusPill — already shipped), 5 (TypeStripe + Card), 7 (Playwright)** continue to use
`src/components/ui/`. Cross-cutting primitives stay shared.
- **CSS scoping that depended on the `data-v1-redesign` attribute** moves into v1-only stylesheets
- imported by `src/v1/`, or gets scoped via a class set by ``. PR 2b decides which.
+ imported by `src/v1/` under the `.v1-app` class. `main.tsx`'s one-line carve-out (above) sets the
+ class on `` pre-mount so the cascade reaches ``. ``'s wrapper
+ `` also carries the class for nested scoping. **Locked in PR 2b's grilling
+ session (2026-05-13).**
## Supersedes
@@ -104,7 +124,9 @@ This decision supersedes three rows in the NEXT-STEPS.md decision log:
of small PRs (now ten including PR 2b), and still gated by `V1_REDESIGN` — but "gated" now means a
single boundary read, not per-component sprawl.
- **2026-05-05 — "Migration strategy: feature-flagged side-by-side, swap in cleanup PR."** Now:
- directory-separated; per-deploy bundle via tree-shaking; swap is still in the cleanup PR but is a
+ directory-separated; per-deploy bundle via the runtime boundary read (tree-shaking the unreachable
+ branch isn't currently in play because `isEnabled()` uses computed-key env access that Vite can't
+ constant-fold; both branches ship in both bundles); swap is still in the cleanup PR but is a
delete-the-other-half diff rather than a flag flip.
- **2026-05-07 — "PR 1 dark-surface reconciliation lands globally on `main`; V1_REDESIGN gates UI
components/layout, not the base palette."** Still accurate; the gate just moved from per-component