[Documentation] Bookmark API entries from the API popover (movable companion panel)
@johnleider is already working on this.
Since Jul 7, 2026.
- Dominant language
- TypeScript
- Stars
- 735
- Forks
- 10
- Avg merge
- 10h 47m
- Merged PRs (30d)
- 72
Description
Summary
Let readers bookmark any v0 API entry (component or composable) directly from the API hover popover, and revisit their saved entries from a movable, dockable companion panel that persists across visits.
The docs surface is large (63 composables, ~83 planned components). A lightweight, personal "pin the things I'm shortlisting" affordance improves return-trip discoverability without sending the reader off-site.
Scope
Docs-app-local (apps/docs). Nothing lands in packages/0 for now — but the movable-panel logic is written extraction-clean so it can graduate into @vuetify/v0 later if it proves out (same approach being taken with Tour).
Architecture
Three layers:
useApiBookmarks— singleton composable, persisted viauseStorageunderapi:bookmarks. Record shape{ name, apiType, apiLink }(Vue APIs excluded — they have no v0 page). Modeled on the existinguseSearchfavorites block.- Star toggle in the API hover popover (
DocsApiHover) — the hover popover is already interactive (keeps itself open when the pointer is over it; footer links already stop propagation), so the star is just another action button in the header. useMovable+CompanionPanel— a headless position/mode state machine (docked | floating | minimized) plus the panel shell that consumes it,useStack(z-layer), anduseApiBookmarks. The panel is built as a generic companion surface, not bookmarks-specific, so future engagement surfaces (recents, "what's new") can reuse it.
No existing v0 primitive covers free-move positioning (useDragDrop is drop-target semantics; usePopover is anchor-only). useMovable composes the Splitter/SplitterHandle pointer pattern (pointer capture + useRaf throttle + useDocumentEventListener + user-select/touch-action suppression) with clamp for viewport constraint and useStack for stacking.
v0 primitives used
useStorage, useStack, useRaf, useDocumentEventListener, useToggleScope, useBreakpoints, clamp, IN_BROWSER — plus router-link for navigation.
Phased plan
Phase 1 — docked bookmarks (ships the feature)
useApiBookmarksstore (toggle/has/remove/clear/count, persisted).- Star toggle in
DocsApiHoverheader; builds the bookmark record from the current hover entry. CompanionPanelas a docked right-side sheet (mirrorsAppSettingsSheet: fixed sheet +useStackticket + Escape-to-close), listing bookmarks with per-row navigate + remove.- Trigger button in
AppBarwith a count badge.
Phase 2 — detach + drag
useMovableheadless composable: position math, viewport clamping, mode machine; persistence flows in viainitial/initialModeand out viaonChange(no app coupling).- Wire
floatingmode intoCompanionPanel: drag handle on the header, detach/dock button, persisted layout (panel:layout), clamp-on-resize, force-docked below a tablet breakpoint (free-drag is a desktop affordance).
Phase 3 — polish + reuse
- Minimize (pill) mode; snap-to-edge docking zones; optional resize (borrow
Splitter). - Prove reuse by dropping a second surface (recents / "what's new") into the panel behind a
Tabsswitch — the checkpoint that justifies extractinguseMovableintopackages/0.
Files
| File | Action |
|---|---|
apps/docs/src/composables/useApiBookmarks.ts |
Create — persisted bookmark store + panel open-state + layout |
apps/docs/src/components/docs/DocsApiHover.vue |
Modify — star toggle in the popover header |
apps/docs/src/composables/useMovable.ts |
Create (Phase 2) — extraction-clean headless position/mode logic |
apps/docs/src/components/app/CompanionPanel.vue |
Create — dock↔float↔minimize shell rendering the bookmarks list |
apps/docs/src/components/app/AppBar.vue |
Modify — bookmarks trigger button + count badge |
apps/docs/src/App.vue |
Modify — mount CompanionPanel once |
Accessibility
- Star button:
aria-pressed, descriptivearia-label. - Panel:
role="dialog",aria-labelledby, non-modal (scrim: false), Escape-to-close. - Floating mode: keyboard nudge + a "reset position" escape hatch so a lost panel is always recoverable; respect reduced-motion on the detach transition.
Notes / open calls
- Bookmark identity is the entry's full name + type + canonical
apiLink(already computed inDocsApiHover). - Persistence starts local (
localStorageviauseStorage); a synced path is possible later if accounts land. - Verification is manual (
pnpm typecheck+ browser checks) per repo testing policy.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.