Restructure docs sidebar: always-visible topics, full-width filter, anchored toggle#962
Conversation
… anchored toggle Layout changes - Replace the topic dropdown with an always-visible topics list at the top of the sidebar. - Move the filter input directly below the topics list and stretch it to full width. - Remove sticky positioning from the topics + filter wrappers so the whole sidebar scrolls as one unit. Collapse/expand toggle - Anchor the floating collapse/expand toggle to the sidebar's right edge as a projecting tab (no margin gap, flat left edge, rounded right corners). - Make the toggle banner-aware via a JS-measured --aspire-banner-height CSS variable on <html>, kept in sync via MutationObserver + ResizeObserver + window resize. - Fully collapse the sidebar (--sl-sidebar-width: 0rem) when the toggle is engaged so no leftover strip remains; the floating toggle stays visible because it lives outside the pane in the DOM. Visual polish - Align topic icon left edges with the filter icon position so they read as a single column. - Tune topic link padding/line-height for a denser, but still comfortable, vertical rhythm. - Size the toggle at 2.5rem with 0.55rem internal padding. Stability - Give the sidebar its own view-transition-name and disable its cross-fade animation to eliminate the white-border flash that briefly appeared on dark theme during topic navigation. - Drop the border-color transition from topic links for the same reason. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Topic buttons return to the original starlight-sidebar-topics plugin look: no card background or border, color-only active/hover, accent-filled icon boxes. Both the global rules in site.css and the scoped rules in Sidebar.astro now align on this OG behaviour. The collapse/expand toggle was buried under the main content's stacking context (flex paint order put .main-pane on top of .sidebar-pane despite z-index). Teleport the four toggle buttons to <body> on mount and after every astro:after-swap so they live in the root stacking context and real mouse clicks reach them. TopicHero icon container is now 3rem with 0.5rem padding (was 4rem with no padding). The SVG fills the content area; responsive overrides drop the now-redundant explicit svg sizing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Topics list now lives in a bordered card whose color matches the filter input (gray-5 border, 0.5rem radius, 0.25rem padding). - Active topic gets an 18% accent bg + 45% accent border; non-selected topic icons drop their border/bg so they only stand out when active. - Topic <a> padding equalised on all sides. - Floating sidebar toggle: bumped to 3rem, removed border, no bg change on hover, opacity crossfade keyed off the [data-*-collapsed] attributes so it slides in sync with the sidebar width transition. - Reserve 3.5rem inline-start padding on the content panel when the topics sidebar is present so the floating toggle no longer overlaps the page H1. - Light theme: use --sl-color-accent-high (not --sl-color-accent) for the active topic text — boosts contrast from 4.01:1 to ~11:1 and fixes a WCAG 1.4.3 AA color-contrast violation. - Removed sidebar-filter auto-focus on page load (steals focus, was annoying). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace full-collapse with a 3.5rem rail that keeps the topics card visible (icons only, labels hidden). The filter, sidebar entries, divider, and mobile footer all hide in rail mode. Topic icons get a title= attribute so hover shows the topic name as a tooltip. The expand toggle still floats off the rail's right edge thanks to left: var(--sl-sidebar-width). Both data-api-ref and data-topic-nav variants are supported, in light and dark themes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Subtle blur-in (filter+opacity, 280ms) when expanding from rail mode; respects prefers-reduced-motion - Floating toggle no longer overlaps H1 when the mobile TOC pill is showing (added --sl-mobile-toc-height to top calc) - HeroSection logo shrunk 4rem -> 3rem to match TopicHero icon proportions - Fix invisible mobile hamburger: move view-transition-name from nav.sidebar to #starlight__sidebar so its stacking context no longer traps the menu button behind the fixed header - Update e2e regression tests + waitForTopicSidebarReady helper to drop the removed topic dropdown trigger/panel and assert the always-visible topics list instead Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Code review findings (blocking): * Guard collapse/expand button bindings with dataset.bound so handlers aren't re-registered when the script re-runs (e.g. view transitions). * Disconnect any prior banner MutationObserver/ResizeObserver before recreating them and null the refs when no banner is present. * Add aria-expanded + aria-controls=starlight__sidebar on all four collapse/expand toggle buttons; sync the value with the data-collapsed attribute set by Head.astro pre-paint. * Move focus to the activating toggle when collapse state flips (with preventScroll where supported) so keyboard users don't get stranded. * Tag each topic link with aria-current=page and aria-label so the always-visible topic list announces the current location to AT users. Review findings (warning): * Wrap localStorage writes in a safeSetItem() helper that catches QuotaExceeded / private-mode SecurityErrors instead of throwing. * Clear any pending sidebar-expanding timer + remove the blur-in flag on init so a fresh navigation can't keep the animation flag pinned. * Empty-state messages now flow through updateStatus() so the live region announces zero-match filter results. * Strengthen waitForApiSidebarReady / waitForTopicSidebarReady helpers to also wait for .starlight-sidebar-topics to render before asserting toggle button visibility. Review findings (info): * Capture wasCollapsed BEFORE mutating data-*-collapsed so the blur-in animation only fires on real collapsed → expanded transitions. * Add will-change: filter, opacity hint scoped to the brief blur-in window so the compositor can promote the layer without long-term memory pressure. E2E test fixes: * The 3 failing ui-regressions tests asserted that the inactive toggle button reports isVisible()=false. The previous CSS hid it with opacity:0 + pointer-events:none, which Playwright still counts as visible. Add visibility: hidden (with a delayed transition so the opacity fade still plays) on each inactive variant; the active variant flips visibility instantly so it remains focusable. This resolves all three failures without modifying the tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Tooltip on the GitHub icon in the sidebar bottom now shows the full repo path instead of just 'aspire.dev' so the destination is obvious on hover (including when the rail is collapsed and only the icon shows). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Restructures the docs sidebar so topics render as an always-visible list (replacing the previous dropdown), promotes the filter input to its own full-width row, and re-implements the collapse/expand toggle as a floating button anchored to the sidebar's right edge (teleported to <body> to escape the sidebar's stacking context). Adds banner-height tracking, focus management, a blur-in expand animation gated on prefers-reduced-motion, and a view-transition opt-out for the sidebar pane. Also tightens hero icon sizing and updates e2e tests/helpers to match the new DOM (no more #topic-sidebar-trigger/dropdown panel).
Changes:
- Replace topic dropdown with an always-visible
<ul>of topic cards, restyle current/hover states, and move the filter into its own row below the list - Reimplement collapse/expand as twin floating buttons with
position: fixed, opacity crossfade, view-transition handling, banner-height offset, and DOM teleport to<body> - Update e2e tests/helpers to target the new topics list locators and drop the dropdown trigger/panel checks; remove auto-focus on the sidebar filter input
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/frontend/src/components/starlight/Sidebar.astro | Removes dropdown markup, adds always-visible topics list, adds floating toggle buttons, teleport + banner-height + animation scripts, focus & aria-expanded sync, safeSetItem helper |
| src/frontend/src/styles/site.css | Restyles .starlight-sidebar-topics as a card with accent-tinted active state; adds rail-mode (collapsed) layout, blur-in keyframes, view-transition group for sidebar, content-panel inline-start padding |
| src/frontend/src/components/TopicHero.astro | Shrinks the topic hero icon from 4rem→3rem and uses padding + svg { width/height: 100% } instead of fixed svg sizes at each breakpoint |
| src/frontend/src/components/HeroSection.astro | Matches the smaller hero logo sizing (3rem base, 2.75rem at narrow breakpoint) |
| src/frontend/tests/e2e/ui-regressions.spec.ts | Replaces dropdown trigger/panel assertions with topics-list assertions; mostly Prettier reformatting elsewhere |
| src/frontend/tests/e2e/helpers.ts | waitForApiSidebarReady/waitForTopicSidebarReady now wait for the topics list instead of #topic-sidebar-trigger |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <a | ||
| href={topic.link} | ||
| title={topic.label} | ||
| aria-label={topic.label} |
| data-tour-target="topics-dropdown" | ||
| data-tour-step="topics-dropdown" |
| <button | ||
| type="button" | ||
| class="sidebar-collapse-btn" | ||
| id="sidebar-collapse-btn" | ||
| data-tour-target="sidebar-toggle" | ||
| aria-label="Collapse sidebar" | ||
| title="Collapse sidebar" | ||
| aria-expanded="true" | ||
| aria-controls="starlight__sidebar" | ||
| > | ||
| <svg | ||
| viewBox="0 0 24 24" | ||
| fill="none" | ||
| stroke="currentColor" | ||
| stroke-linecap="round" | ||
| stroke-linejoin="round" | ||
| stroke-width="2" | ||
| aria-hidden="true" | ||
| > | ||
| <> | ||
| <rect width="18" height="18" x="3" y="3" rx="2" /> | ||
| <path d="M9 3v18m7-6l-3-3l3-3" /> | ||
| </> | ||
| </svg> | ||
| </button> | ||
| <button | ||
| type="button" | ||
| class="sidebar-expand-btn" | ||
| id="sidebar-expand-btn" | ||
| data-tour-target="sidebar-toggle" | ||
| aria-label="Expand sidebar" | ||
| title="Expand sidebar" | ||
| aria-expanded="false" | ||
| aria-controls="starlight__sidebar" | ||
| > | ||
| <> | ||
| <rect width="18" height="18" x="3" y="3" rx="2" /> | ||
| <path d="M9 3v18m5-12l3 3l-3 3" /> | ||
| </> | ||
| </svg> | ||
| </button> | ||
| <svg | ||
| viewBox="0 0 24 24" | ||
| fill="none" | ||
| stroke="currentColor" | ||
| stroke-linecap="round" | ||
| stroke-linejoin="round" | ||
| stroke-width="2" | ||
| aria-hidden="true" | ||
| > | ||
| <> | ||
| <rect width="18" height="18" x="3" y="3" rx="2" /> | ||
| <path d="M9 3v18m5-12l3 3l-3 3" /> | ||
| </> | ||
| </svg> | ||
| </button> |
| function teleportSidebarToggles() { | ||
| const ids = [ | ||
| 'sidebar-collapse-btn', | ||
| 'sidebar-expand-btn', | ||
| 'topic-sidebar-collapse-btn', | ||
| 'topic-sidebar-expand-btn', | ||
| ]; | ||
| for (const id of ids) { | ||
| const btn = document.getElementById(id); | ||
| if (btn && btn.parentElement !== document.body) { | ||
| document.body.appendChild(btn); | ||
| } | ||
| } | ||
| } |


Restructure the docs sidebar so topics are always discoverable and the filter/toggle layout works better at every breakpoint.
Summary
Layout changes (rendered on every page that has the topics sidebar — both API-reference pages and topic-nav pages):
left: 0when collapsed), teleported to<body>to escape stacking-context issues, and slides in sync with the sidebar'swidthtransition via an opacity crossfade keyed off[data-sidebar-collapsed]/[data-topic-sidebar-collapsed]on<html>.≥ 72rem) so the floating toggle never overlaps the page<h1>.Polish
gray-5border (matches filter input),0.5remradius,0.25rempadding, distinct--sl-color-bgso it visually elevates from the sidebar.18%accent background,45%accent border, filled accent icon box,--sl-color-accent-hightext in light theme (fixes a WCAG 1.4.3 AA color-contrast issue — text-on-tint contrast jumps from 4.01:1 to ~11:1).<a>padding equalised on all sides for a balanced visual rhythm.Verified
≥ 72remand< 72rem).sidebar-collapse-btn,sidebar-expand-btn,topic-sidebar-collapse-btn,topic-sidebar-expand-btn).Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com