App nav dock and tool sidebar

The macOS-style icon dock that carries the app's top-level destinations, and the sidebar column that hosts it on every tool route.

  • Component: apps/debate-ai.com/components/layout/CategoryDock.tsx
  • Sidebar shell: packages/debate-webview/src/components/layout/AppSidebarShell.tsx
  • The one sidebar column: packages/debate-videos/src/ui/layout/ResizableSidebarLayout.tsx (hide/show state in sidebar-collapse.ts beside it), filled by packages/debate-webview/src/components/layout/app-sidebar/ off the video pages
  • The tree in it: VideoSidebarTree, mounted off the video pages through LibrarySidebarTree (packages/debate-videos/src/components/category-gallery/)
  • Route predicates: packages/debate-videos/src/components/category-gallery/sidebar-routes.ts (re-exported for app code as apps/debate-ai.com/lib/sidebar-routes.ts)
  • Dock primitive: apps/debate-ai.com/lib/ui/layout/dock.tsx

What it shows

Five destinations — Videos, Shared, Debate, Practice vs AI, Research — plus a gear-icon Settings menu, with Alt+1…Alt+5 shortcuts in dock order. The icons carry no hover labels — in the sidebar-hosted dock the tooltips crowded together over the nav tree — so each item's name lives in its aria-label (read by screen readers) and in the icon art itself.

Practice vs AI opens a menu instead of navigating. A plain click on that icon does not go to /practice/versus-ai — it opens the site-nav menu described below (NavMenu, in CategoryDock.tsx). The page itself is still one tap away, as the first tool listed under that menu's Practice section, and the Alt+4 shortcut still jumps straight there.

Tools are not dock icons. The tools catalog is reached from the sidebar nav tree's Research / Practice / Coaching / Insights sections, and the whole feature catalog from the Features row in the Settings menu's Site Links submenu — next to a Docs row for the help site. Holding the dock to five destinations is what lets it fit inside the sidebar column it is hosted in — see below.

The sidebar button (mobile)

The sidebar is md+ only, so the mobile bottom dock starts with a Sidebar button. It opens a left drawer (MobileSidebarDrawer) whose content follows the view in the centre (mobileSidebarKind, lib/mobile-sidebar.ts):

ViewDrawer
Video library (/videos, /lectures, glossary, rankings, statistics)The sidebar tree (Videos, tool sections) and footer
/research/cards, /reason-editorDocument panels above the sidebar tree
/debateIts own flows/rounds sidebar — the button dispatches debate:open-sidebar and the workspace opens its own sheet
Everything elseThe sidebar tree and footer

The drawer closes on navigation.

On md+ the column has no brand row at the top — it opens straight onto the dock. Its bottom row, pinned under the scrolling tree, is the account menu (on every page, the video library's included) with the hide button beside it — see Hiding the sidebar. The row shows your avatar and name only, never your email address, with a badge on the avatar counting unread notifications. The account menu holds Settings, a Notifications submenu (every unread notification: pick one to open its link and clear it, X to clear it in place, Clear all, and a link to /notifications; clearing is the page's mark-as-read), an Organizations submenu (switch between Personal and your organizations, or create one — see Contacts), a Theme submenu (Light / Dark / System and every colour theme, with swatches — the same picker as the dock's Settings menu, and synced to the account the same way), a Site links submenu (every FOOTER_LINKS entry: Docs, GitHub, Support, Privacy, Reddit…) and Sign out. Signed out, the row is a Sign in button with a globe button beside it that lists the same site links.

Docs and Settings are always on screen just above the account row, on every page, signed in or out and whatever is selected, so you never have to open a menu to reach them. The phone drawer ends with the same two links.

The other site links used to be a row of links above the account row; they live in the account menu now. The phone layouts below md, which have no account row, keep their footer.

Two menus, not one

The dock carries two independent dropdowns, each with its own DropdownMenu root — opening one does not affect the other, and either can be open at once:

  • The Practice vs AI icon opens the site-nav menu (NavMenu). Command Palette at the top, then a submenu per sidebar section — Videos, Research, Practice, Coaching, Insights — derived from the data the sidebar itself renders rather than restated:

    Menu submenuComes from
    VideosSIDEBAR_VIDEO_LINKS (components/category-gallery/sidebar-video-links.ts), minus the glossary and topic & video statistics, which are listed under Insights instead
    Research / Practice / Coaching / InsightsSIDEBAR_TOOL_SECTIONS

    On a phone, where the sidebar column below is md+ only, this menu is the only way to reach those links at all.

  • The gear icon opens SettingsMenu — Settings, the light/dark toggle and Theme submenu, Hide Dock (see Hiding the dock), one Site Links submenu listing every footer link (site and debate-community links together, from FOOTER_LINKS), and the account block.

There is no "Apps" submenu. The site-nav menu used to restate the dock's own five icons as text and then hang the whole feature catalog underneath, one nested submenu per category — a second, deeper copy of /practice/features hanging off the dock that was already showing those five icons. One Features row reaches the catalog instead, and a Docs row the help site; both are footer links, so the sidebar's link rows carry them too.

apps/debate-ai.com/lib/nav/dock-menu-sections.ts does the site-nav menu's composition, and lib/nav/__tests__/dock-menu-sections.test.ts fails if a sidebar destination is missing from it. That coupling is the point: the Videos links and the glossary/rankings pair below the tree were in the sidebar and in no mobile menu at all, because the menu was a hand-kept list.

Both menus scroll (max-h-[min(560px,80vh)]) — SettingsMenu's theme/links block above the account rows can still run past a phone viewport.

Wiring the Practice vs AI icon to a second DropdownMenu root, rather than sharing the gear's, means it sits inside Dock's children instead of wrapping the whole dock — so Dock's magnification props land on the wrapper component instead of the DockItem two levels down. PracticeVsAiTrigger forwards mousex/magnification/distance/iconSize by hand so that icon still resizes and tracks the cursor like its siblings.

/videos additionally prints the tree inline in its own md:hidden block, under the quick-link tiles: the tiles are the Videos section only, so ToolNavTree follows them with defaultExpanded={false} (its sections start collapsed there — expanded, forty rows would push the video grid off the screen).

Hiding the dock

Choose Hide Dock in the gear menu and the row of app icons folds away to a small arrow tab where it sat: hanging down from the top-left corner or the top of the sidebar, or rising from the bottom of the screen on a phone. Hover the tab (or Tab to it from the keyboard, or tap it on a touch screen) and the full dock slides back over it; move away and it folds up again. It stays out while one of its menus is open, so the same menu's Show Dock row puts it back for good. The choice holds on every page and is remembered in this browser (app-dock-hidden in localStorage, broadcast by packages/debate-webview/src/lib/nav/dock-hidden.ts so every dock instance agrees).

CollapsibleDock in CategoryDock.tsx does the folding. Shown, it renders the dock untouched. Hidden, it keeps the dock mounted inside an absolutely positioned, transparent panel over the tab, and reveals it with CSS alone: group-hover, keyboard focus inside (:focus-visible, so a mouse click that leaves focus on an icon does not pin it open), a tap on the tab, or a dock menu trigger with data-state=open.

Where it renders

The dock has two forms, and which one a route gets is decided by hasEmbeddedDock:

Sidebar-hosted (<CategoryDock embedded />). On /videos (whose own <aside> takes it through LecturesVideoGridView's dockSlot) and on every route the tool-nav tree links to (where AppSidebarShell wraps the page in the generic sidebar), the dock sits at the top of that column (300px wide until you drag it — see Resizing the sidebar).

/doc is the exception: the Docs button opens the research agent, which draws its own full-height workspace. Its sidebar — the files tree and the "Open Tabs" list — is the research agent's own, not the generic tool sidebar, and the dock sits at the top of that column (OWN_SIDEBAR_DOCK_HREFS, in packages/debate-videos/src/components/category-gallery/sidebar-routes.ts). The research agent's own app dock is never mounted here (it is the host's to draw), and on a phone the dock's Sidebar button opens the agent's sidebar (the OPEN_OWN_SIDEBAR_EVENT window event, the same one /debate listens for). Choosing Settings in the dock's menu from /doc opens /settings on the research agent's first tab (?category=research-account); from anywhere else it opens /settings on its first tab. Either way the agent's sections and the app's own share one sidebar.

The Research button was called Docs and lived at /doc until October 2026. Old /doc and /doc/<document> links answer with a permanent (308) redirect to /research/docs and /research/docs/<document>, from the same table as the other category moves (packages/debate-data-sync/src/routes/category-paths.ts). It sits under /research/docs rather than /research because /research is the Research Workspace hub.

That now includes /practice/rankings and /practice/glossary. Both are rows in the sidebar's own tree, and both used to answer with a bare page — no sidebar, and no fixed dock either, since every /videos path counts as already carrying a sidebar-hosted one. LecturesSidebarShell wraps them in the same column (dock, nav tree, footer), so clicking either link leaves the nav exactly where it was.

The sidebar is md+ only, though, and the same rule that hides the fixed dock hides its mobile bottom bar. So on a phone those two pages still answered with nothing to navigate by. LecturesSidebarShell now also renders the md:hidden block the grid renders — the quick-link tiles, the tool tree (collapsed) and the footer — so the pair has a way out of it at every width.

Fixed fallback. Everywhere else — the home page, /login, /legal/* — it renders fixed in the top-left corner on desktop and as a bottom bar on mobile. The two never show at once.

Route matching is by path prefix, so a nested route under a tree entry (/research/cards/awards under /research/cards, a document route under /research/docs) keeps the sidebar rather than dropping to the fixed dock. The trailing / in the comparison keeps /cardsy from matching /cards.

Search floats over the results

The search box, the season and style filters, the sort and the grid/rows toggle used to sit in the sidebar on a desktop and in a bar above the results on a phone — two copies, which is why a half-typed query seemed to disappear when a window was resized across the breakpoint.

There is one now, and it is not in the sidebar: a small magnifier in the top-right corner of the results, which follows them as you scroll. Hover it on a desktop, tap it on a phone, or Tab to it, and the whole control opens over the results. It stays open while you are typing in it or while a search is active, and closes on Escape or a click outside. Whatever you typed is still there the next time you open it.

That is also what lets the sidebar stay the same on /practice/glossary and /practice/rankings, which have nothing to search: the column is now the same column everywhere in the library.

Results open as rows

/videos opens as the dense row list rather than the thumbnail grid — about four times as many results per screen. The grid is one toggle away inside the search panel. The choice is not remembered between page loads.

One sidebar everywhere

Every view draws the same sidebar: the one the video pages always had — the dock, then Videos and the Research / Practice / Coaching / Insights sections, then the footer links. The tool and research pages, /admin, the legal pages and the help docs used to get a different column (shadcn's sidebar-07, tool sections only), and /docs showed Fumadocs' own sidebar beside that one. Now:

  • Off the video pages AppSidebarShell wraps the page in the same ResizableSidebarLayout the video pages use, and LibrarySidebarTree mounts the same VideoSidebarTree, reading the library's counts itself (useVideoMeta).
  • Page-specific panels are sections of it. The REASON document panels sit above the tree on /reason-editor and are the whole column on /research/cards, as before.
  • On /docs the docs' page tree is a section of it. debate-help-docs' layouts portal the page tree (app-sidebar-docs-tree.tsx) into a slot the column leaves for it (DOCS_SIDEBAR_SLOT_ID), at the bottom of the column below the Insights section, and styles/docs.css hides Fumadocs' desktop sidebar and closes its grid column. Below md Fumadocs' drawer is still the docs' navigation. Only the folders on the path to the current page start expanded, and the current page is scrolled into view when the docs open and after each navigation.
  • Off /docs the tree is not drawn; the Docs and Settings links pinned above the account row (SidebarPinnedLinks) reach it from every page.
  • The mobile drawer shows the same tree (MobileSidebarDrawer).

/debate and /research/docs keep their own workspace sidebars (ownsItsLayout) — see Known gaps.

Resizing the sidebar

On every page with the sidebar, drag the thin line on the sidebar's right edge to make the column wider or narrower (between 220px and 640px). The width you choose is remembered in this browser and every page opens the sidebar at that same width, so the column keeps its shape as you move between them. Double-click the line to put it back to its default 300px. The line also takes keyboard focus, and the arrow keys resize it.

Hiding the sidebar

Hide the sidebar with the panel button at its bottom-right, by pressing Ctrl+B (⌘B on a Mac), or by dragging its edge past half its minimum width. It collapses to nothing and the page takes the full width. A small tab on the left edge of the window brings it back, as do the same shortcut and dragging the edge back out. The choice holds on every page and is remembered in this browser (app-sidebar-collapsed in localStorage; sidebar-collapse.ts broadcasts it, so the column and the dock always agree).

Peeking. While the sidebar is hidden, move the pointer to the very left edge of the window (within 8px) and it slides out over the page — slightly translucent, at your usual width — without pushing the page aside. Move away from it and it slides back after a moment (or press Esc); it stays hidden until you pin it with the panel button at its foot, which reads Keep sidebar open while peeking. A menu opened from it (the account menu) keeps it out until the menu closes. Each time it comes or goes it plays one of ten animations at random (slide, elastic, wiggle, zoom, flip, bounce, swing, drop, blur or jelly), and none if your system asks for reduced motion. (ResizableSidebarLayout: a pointermove listener while collapsed restyles the same <aside> as a fixed overlay, so the content panel never resizes.)

Pages with their own sidebar. The flow workspace (/debate) and the research docs (/research/docs) draw a sidebar of their own, so there the app sidebar starts hidden and theirs is the only one on screen. It still peeks from the left edge, and pinning it keeps it open until you leave the page; it doesn't change whether the sidebar is hidden anywhere else.

Icons that move. This is on by default; turn off Animate sidebar icons in Settings → Preferences to stop it. Hovering a row in the sidebar, or tabbing to it (the icon or its label), makes its icon wiggle, bounce, pulse, spin, shake, flip, jelly or tada, a different one from the last time, for either half a second or a full second, and tints it a random color while it plays. Each icon plays at most once every three seconds. The research docs' own sidebar does the same. If your system asks for reduced motion, the icon only changes color.

While the sidebar is hidden the dock it carried floats at the top-left instead (CategoryDock lifts its suppression while useSidebarCollapsed() is true), so the five destinations stay one click away.

While a text editor has the keyboard (CardMirror, the REASON editor, any text field), Ctrl/⌘+B stays bold and does not toggle the sidebar.

Each tree section (Videos, Research, Practice, Coaching, Insights) opens and closes on its own; see The nav tree's headings. The Docs, Github, Support, Privacy and Reddit links sit on one compact line after the last section and scroll with the list rather than staying pinned. Docs and Settings are pinned at the bottom above the account menu, which links to Settings, Notifications and Contacts and signs you out. Signed out, that row is a Sign in button that opens the sign-in dialog without leaving the page.

On a phone nothing changes: the sidebar is not drawn below the md breakpoint, and the dock's Sidebar button still opens the drawer described above.

Staying inside the sidebar

A dock sized to its own contents (w-max, the default fluid: false form) is wider than the sidebar at its default 300px. Hosted there it either forced the sidebar to scroll sideways or reached over its border onto the page beside it — which on /reason-editor and /research/docs is a CardMirror editor.

The sidebar-hosted form passes fluid to Dock, which:

  • takes its width from the column (w-full max-w-full min-w-0) instead of from the item count, and
  • wraps an overflowing row onto a second line (flex-wrap) instead of growing past the column, so a future sixth or seventh destination still cannot escape it.

CategoryDock also shrinks the icons for that form: EMBEDDED_ICON_SIZE (34px) at rest and EMBEDDED_MAGNIFICATION (46px) hovered. Six items at 34px with gap-1.5 and p-2 come to 250px against 276px of usable column width, and a magnified icon adds 12px more — so the row fits without wrapping at every breakpoint, and the wrapping above is the backstop rather than the normal case.

The dock stays overflow-visible so a magnified icon isn't clipped at the dock's edge; the sidebar column is the clipping boundary.

The nav tree's headings

Below the dock, the same column carries the nav tree (VideoSidebarTree on /videos, its ToolNavTree tail everywhere else). It is three levels deep:

LevelElementWhat it is
1h1A top-level section: Videos, Coaching, Research, Practice
2h2A subgroup inside one — College Policy, Favorites, Lectures
3spanA leaf link: a tool, a debate format

Two rules hold for every h1:

  • It is not a link. The row renders without an href, so clicking it does nothing but toggle the section. Each section's flagship tool is the first link inside it (/coaching under Coaching), so nothing became unreachable — a click on the heading no longer navigates away from the page you are on just because you wanted to see what else is in the group.

  • One section is open at a time, and it follows the route. The tree is an accordion: opening a section closes the one that was open, and a closed section renders none of its links. Which one is open comes from the current path (sidebar-active-section.ts), so clicking an app dock button loads that destination's section into the sidebar and nothing else. The state is per-mount, and opening another section by hand still works.

    It used to render every section's links up front. That put around fifty next/links in the sidebar on /videos, and the router prefetched an RSC payload for each one the moment the page mounted — a burst of requests racing the video feed and its thumbnails on the page that already felt slowest. The tree links now also pass prefetch={false}, so the ones that are rendered are fetched on click rather than on sight.

    Resolution is longest-match over the links the tree actually renders: /research/cards/library opens Research, which lists it, and /practice/versus-ai opens Practice ("Debate Versus AI"). A dock destination in no tool section — /research/cards, /debate, /reason-editor — matches nothing and opens nothing. The dock's Research button (/research/docs) opens Research, by prefix on the Research Workspace link. /research/docs and /reason-editor used to sit in Research as "Debate Docs" and "Reason Editor"; they are the dock's own Research button and a top-level editor, so the rows only restated what the icons above them already said. Both routes keep their sidebars — /research/docs through the dock link list, /reason-editor through EXTRA_SIDEBAR_HREFS, which is what gives the editor its file-navigation panels.

SidebarToolSection.href outlives the heading link: sidebar-routes.ts still folds it into the set of paths that get the tool sidebar.

Indentation follows nesting, not level — each expanded node pads its own child list — so a leaf under College Policy sits a step deeper than one hanging straight off Coaching, wherever in the tree it is.

Every tool has an icon

Each tool in Coaching, Research and Practice shows a small icon of its own next to its name — a magnifying glass on Research Workspace, a gavel on Judge Profiles, swords on Debate Versus AI — so a long section can be scanned by shape rather than read line by line.

They are all drawn in the same muted grey as the section headings above them, at the same 16px, on purpose: the icons are there to tell the rows apart, not to compete with them or with the page you are reading beside the column. The Glossary and Rankings links at the end of Practice used to be the exception — full-color artwork sitting among the grey glyphs — and now match the rest.

Tests

  • packages/debate-videos/test/video-sidebar-render.test.tsx — the heading structure above: College Policy under a Videos h1, no h1 inside an anchor, every section a toggle button, and only the section holding the current route open (with the closed ones rendering none of their links).
  • packages/debate-videos/test/sidebar-active-section.test.ts — the route-to-section mapping itself, including the longest-match and dock-wins-a-tie rules above.
  • apps/debate-ai.com/lib/ui/__tests__/dock.test.tsx — the fluid variant's classes, host-set icon sizing, and that magnification never shrinks an icon below its resting size.
  • packages/debate-videos/test/sidebar-routes.test.ts — that /tools is no longer a dock destination but is still a sidebar one, and the prefix matching (including /cardsy not matching /cards).
  • packages/debate-videos/test/sidebar-video-links.test.tsx — that the tree renders every SIDEBAR_VIDEO_LINKS entry and the mobile quick-link tiles render all but the glossary/statistics pair, which has no tile and is reached from the Practice section.
  • packages/debate-videos/test/lectures-sidebar-docs-slot.test.tsx — that /videos' md:hidden block carries the tool sections, collapsed.
  • packages/debate-videos/test/lectures-sidebar-shell.test.tsx — that the rankings and glossary branches render the dock, the nav tree and the footer rather than a bare page, on a phone as well as a desktop.
  • apps/debate-ai.com/lib/nav/__tests__/dock-menu-sections.test.ts — that every sidebar destination (videos, tool sections, footer links) is reachable from the Settings menu, which is the whole nav below md, that there is no Apps section, and that /practice/features and /docs are reachable.
  • packages/debate-videos/test/unified-sidebar.test.tsx — that the tree mounted off the video pages carries the video sections and every tool section, that the column has a resize handle, a hide button and the footer it is handed, renders shown on the server, and that the hide/show choice is stored and broadcast.
  • packages/debate-webview/test/lib/layout/frame-navigation.test.ts — which clicks are left to the browser, and which links out of /docs become a full page load.
  • packages/debate-webview/test/lib/nav/dock-hidden.test.ts — that the dock starts shown, the Hide Dock choice is stored, broadcast and cleared, and still applies to the page when storage is blocked.
  • packages/debate-webview/test/lib/nav/dock-idle-prefetch.test.ts — which destinations are warmed in idle time, and that data saver turns it off.

All Videos is the home page

All Videos (/videos) is the first row under Videos and lists every round and lecture in the library. It is where / lands. The lecture library on its own is Lectures (/lectures), a single row at the end of the same section. The lecture categories are not in the sidebar: the lectures page shows them as a bar of cards at its top (see Lecture categories).

One collection highlighted at a time

The sidebar's collections (All Videos, Lectures, College Policy, HS Policy, HS Policy 1v1 (LD), Public Forum, Greatest of All-Time, My Favorites, Watch History) are one list, and only the open one is highlighted. Lectures lights up on every lecture page, category pages included (browsingLectures), and never alongside a round collection. packages/debate-videos/test/sidebar-single-highlight.test.tsx pins it.

Team Rankings stays highlighted on a team or school page. /teams/<team> and /schools/<school> are opened from the Team Rankings row (/coaching/rankings) rather than nested under it, so a plain path match never lit that row while reading a profile — ToolNavTree's isToolActive treats both prefixes as still-on-Team-Rankings, the same relationship EXTRA_SIDEBAR_HREFS already uses to keep the sidebar itself mounted on those pages (see Where it renders and sidebar-routes.ts).

The highlighted row scrolls into view

TreeItem scrolls its own row into view (scrollIntoView({ block: "nearest" })) whenever it becomes the highlighted one — on mount, and on navigating to a route that lights up a different row. "nearest" moves the sidebar's own scroll only as far as needed to bring the row on screen, and not at all if it is already visible, so following a link inside the currently-visible part of a long section (Practice runs to fifteen-plus rows) never jumps the column.

The feature catalog opens inside the app

/practice/features — the catalog of every surface in the app — is reached from the footer under the sidebar and from the dock's Site Links menu. Following either used to reload the whole tab into a bare page: the sidebar and the dock were gone, the persistent player stopped mid-lecture, and the page's only way back was a "Back" pill of its own.

It is now an ordinary page of the app. It renders in the same sidebar as every surface it catalogues, the footer and the menu reach it through the router rather than by loading a new document, and the "Back" pill is gone — the sidebar is how you leave it.

One link is deliberately still a full page load: /docs is a separately built help site served as static files, not a route this app knows, so it is followed the old way. Outside sites still open in a new tab.

Switching pages is a React render, not a frame load

Every dock destination is an ordinary route rendered as React in the one app document. Nothing loads in an <iframe>: the dock, the sidebar and the player stay mounted, and a sidebar link on /videos routes the same document like any other link.

To make a switch a render from cache, the dock fetches each destination's code ahead of the click. Hovering or focusing an icon prefetches that route, and once the current page has loaded the dock prefetches the others one at a time in idle time (lib/nav/dock-idle-prefetch.ts), so touch screens and quick clicks get the same head start. The idle pass skips the two heavy routes, /research/docs and /practice/versus-ai (the whole practice stack: the AI opponent, the round and matchup simulators, coach mode, the drill generator and the judge); hovering their icons still warms them. Each route is warmed at most once per page load, even when the sidebar's embedded dock remounts and restarts the pass. It also does nothing on a data-saver or 2G connection.

Only the app shell's dock runs the app-wide notifications and contacts polls; the sidebar's embedded copy doesn't, and every other mounted copy of those hooks (the account menu's badge, the contacts page) reuses the request one copy already made in the same 30-second tick.

A bar across the top shows a page switch in progress

Every page transition, from a dock icon, any in-app link, or back and forward, shows a slim bar across the top of the window in the theme's primary colour, like YouTube's. It creeps forward while the next page loads, fills when the new page has painted, and fades out. Switches that land within 150 ms never show it, and with reduced motion turned on it moves without animating.

  • Bar: packages/debate-webview/src/components/ui/RouteProgressBar.tsx
  • Pacing and state: packages/debate-webview/src/lib/ui/route-progress.ts
  • Start and finish signals: packages/debate-webview/src/lib/ui/use-route-loading.ts

The full-screen loading orb no longer shows for page transitions; it is left for code that asks for it with beginLoading.

Known gaps

  • /debate (the flow workspace) and /research/docs (the research agent) still draw their own full-height workspace sidebars instead of the shared one, so they have no resize handle or hide button of their own design and their contents are not yet sections of the shared column.
  • A hidden dock's tab does not reveal it on a pen or a touch screen that reports hover; it opens on a tap there too, and a tap elsewhere does not fold it again until the next navigation or a second tap on the tab.
  • On /docs the docs' search box sits in Fumadocs' header, not in the shared column, and with the sidebar hidden the docs have no dock (the docs don't mount the floating one).