Skip to content

Unify Docs and Cockpit sidebar control planes - #892

Merged
blove merged 2 commits into
mainfrom
blove/sidebar-control-plane
Aug 31, 2026
Merged

Unify Docs and Cockpit sidebar control planes#892
blove merged 2 commits into
mainfrom
blove/sidebar-control-plane

Conversation

@blove

@blove blove commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Summary

  • introduce shared rail, context-pane, action, utility, and preference primitives
  • refactor Docs and Cockpit around one stable Docs / Run / Code / API control plane
  • add icon-led actions, modern Lucide icons, rounded interaction states, and a polished page-actions overflow menu
  • preserve analytics, routing, runtime continuity, mobile focus behavior, and accessible nested interactions

Verification

  • npx nx test ui-react
  • npx nx test website
  • npx nx test cockpit
  • npx nx lint ui-react
  • npx nx build ui-react
  • npx nx lint website
  • npx nx build website
  • npx nx build cockpit
  • real-browser QA at desktop and 320px for Docs and Cockpit

@vercel

vercel Bot commented Aug 31, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
threadplane Ready Ready Preview Aug 31, 2026 5:02pm

Request Review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Automated approval: this PR received an intelligent (AI) code review. See the review comments on this PR.

@github-actions

github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Claude finished @blove's task in 0s —— View job


I'll analyze this and get back to you.

@blove
blove force-pushed the blove/sidebar-control-plane branch from 0b7e057 to 5df3ace Compare August 31, 2026 16:26
@github-actions

github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Claude finished @blove's task in 0s —— View job


I'll analyze this and get back to you.

@blove
blove force-pushed the blove/sidebar-control-plane branch from 5df3ace to 8376bc2 Compare August 31, 2026 16:59
@github-actions

github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Claude finished @blove's task in 0s —— View job


I'll analyze this and get back to you.

@blove
blove enabled auto-merge (squash) August 31, 2026 17:01
@blove
blove merged commit 3666eb3 into main Aug 31, 2026
60 checks passed
blove added a commit that referenced this pull request Sep 1, 2026
The picker's title and description have been colliding into a single
run-on line in production ("LangGraphLangChain/LangGraph adapter for
Angular UI"). #892 moved the JSX off Tailwind onto semantic class names
and never ported the `flex flex-col`, so `.docs-sidebar-lib-item-text`
carried only `min-width: 0` and both spans fell back to `display:
inline`.

Repairs that, and gives the control the design pass the rest of the
sidebar got in #892:

- Split the menu into labelled Adapters / Libraries groups. Two of the
  seven entries are adapters; flattening them made the picker read as a
  library index rather than an adapter choice.
- Add a short `tagline` for the two adapters and drop the long
  `description` from the menu, so rows stop wrapping ragged (heights
  were 66/66/66/138/66/66/90, now 52/52/39/39/39/39/39). `description`
  itself is untouched — it is still the fallback for each page's meta
  description via resolveDocDescription().
- Cap the open menu to the room left below the trigger. It opens ~342px
  down the pane, so it ran 182px past the fold at a 720px viewport; a
  CSS `vh` cap cannot fix that (60vh still overflows a 600px window by
  102px), so the cap is measured on open and on resize.
- Menu entries become real links, restoring cmd-click and new-tab, and
  `menuitemradio` + `aria-checked` to match the single-select they are.
- Drop the duplicate Library row from Environment now the picker owns it.

The CSS-level guard is the notable test: jsdom does not apply the
stylesheet, so no component test could have caught the collision that
shipped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
blove added a commit that referenced this pull request Sep 1, 2026
* docs: spec for the docs adapter picker refresh

Records the design agreed for the library picker in the docs control
plane: keep it in Learn, group Adapters vs Libraries, taglines on the
two adapters only, real links, and the lost flex-column rule that is
currently colliding title and description in production.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(website): repair and redesign the docs adapter picker

The picker's title and description have been colliding into a single
run-on line in production ("LangGraphLangChain/LangGraph adapter for
Angular UI"). #892 moved the JSX off Tailwind onto semantic class names
and never ported the `flex flex-col`, so `.docs-sidebar-lib-item-text`
carried only `min-width: 0` and both spans fell back to `display:
inline`.

Repairs that, and gives the control the design pass the rest of the
sidebar got in #892:

- Split the menu into labelled Adapters / Libraries groups. Two of the
  seven entries are adapters; flattening them made the picker read as a
  library index rather than an adapter choice.
- Add a short `tagline` for the two adapters and drop the long
  `description` from the menu, so rows stop wrapping ragged (heights
  were 66/66/66/138/66/66/90, now 52/52/39/39/39/39/39). `description`
  itself is untouched — it is still the fallback for each page's meta
  description via resolveDocDescription().
- Cap the open menu to the room left below the trigger. It opens ~342px
  down the pane, so it ran 182px past the fold at a 720px viewport; a
  CSS `vh` cap cannot fix that (60vh still overflows a 600px window by
  102px), so the cap is measured on open and on resize.
- Menu entries become real links, restoring cmd-click and new-tab, and
  `menuitemradio` + `aria-checked` to match the single-select they are.
- Drop the duplicate Library row from Environment now the picker owns it.

The CSS-level guard is the notable test: jsdom does not apply the
stylesheet, so no component test could have caught the collision that
shipped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
blove added a commit that referenced this pull request Sep 1, 2026
…#920)

* docs: spec for library-neutral docs pages

Records the design for /docs/choosing-an-adapter and the control plane's
missing "no library selected" state. Also records that one of the two
follow-ups behind this work was already fixed by #892, and that /docs is
a landing page rather than a page missing its shell.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(website): give library-neutral docs pages an honest control plane

On /docs/choosing-an-adapter the mobile drawer's Scope card read
"LangGraph / Getting Started / Documentation" — three fabrications in
the one card whose job is saying where you are. Nav derives the library
from the second path segment, which on that URL is
"choosing-an-adapter"; getLibraryConfig returns undefined and the code
fell back to 'langgraph', so the drawer showed LangGraph's picker and
its whole section tree.

The cause is that the control plane had no "no library selected" state,
so every caller had to invent one. Adds it:

- activeLibrary is now LibraryId | null through DocsControlPlane and
  DocsNavigation. Neutral pages show "Docs / <page>" in Scope, a
  "Choose a library" picker with nothing checked, and no section tree.
- Nav stops defaulting to langgraph and resolves special-page titles,
  which corrects the drawer on every library-neutral route.

/docs/choosing-an-adapter was also bespoke, and that drift is what
produced the rest of its symptoms. It now uses the same shell as every
other docs page, which:

- gives it the control plane it never had,
- deletes an empty hero Section that opened a measured 144px gap above
  the H1 and whose empty div was the target of aria-labelledby, leaving
  the section with no accessible name,
- replaces ~60 duplicated lines of MDX pipeline with MdxRenderer.

MdxRenderer's library/section/slug/title props were accepted and never
read — four of the website's lint warnings. Dropped. The blog route was
passing library="langgraph" for blog posts, which only ever looked
harmless because the value was discarded.

/docs keeps its landing-page treatment; it is the front door, not a
page missing its shell.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
blove added a commit that referenced this pull request Sep 1, 2026
…ntracts (#926)

Two follow-ups from #923.

json-render on marketing surfaces
---------------------------------
#923 renamed the docs picker label but deliberately left the marketing
surfaces. They now agree: the homepage FeatureBlock eyebrow, the footer
link, and the three solutions architecture layers all read json-render.

Two hazards this surfaced:

- The footer derives cta_id from the visible label, so renaming the link
  would have silently split PostHog's footer_render into a new
  footer_json_render series. trackFooterCta now takes an optional
  explicit CtaId and the render link pins the original.
- The solutions page maps library name to href through a
  Record<string, string>. Renaming the data without the key returns
  undefined and renders the card unlinked — no error, no type failure.
  solutions-links.spec.ts asserts every layer resolves; mutation-tested
  by renaming one side only.

Style contracts
---------------
docs-sidebar-styles.spec.ts guarded two CSS declarations whose loss is
invisible to jsdom, but it was a one-off with an inline parser. It is
replaced by style-contract.ts plus a registry in style-contracts.spec.ts,
so adding a guard is one entry rather than a new file.

Seeded with four live rules, each mutation-tested by deleting the
declaration and by renaming the selector wholesale:

- .docs-sidebar-lib-item-text     flex column (the #892 collision)
- .docs-sidebar-lib-menu          max-height + overflow-y
- .docs-control-plane             position sticky + align-self
- [data-control-plane-pane]       overflow-y

Writing the registry found a bug in the extracted parser: a CSS comment
above a rule lands inside the selector capture, so the exact match never
fires and a guarded rule reports as missing. Comments are stripped first.

Also removes the DocsSidebar wrapper and its .docs-sidebar rule, dead
since #892 moved the docs nav into the control plane — only
DocsNavigation is imported, and the sole class usage was inside the dead
component. Its comment documented the same align-self hazard now held by
the .docs-control-plane contract.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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.

1 participant