vuetifyjs / vuetifyjs/0

[Documentation] Bookmark API entries from the API popover (movable companion panel)

Open
#537 0 comments 0 reactions 1 assignee View on GitHub

@johnleider is already working on this.

Since Jul 7, 2026.

enhancement T: feature
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:

  1. useApiBookmarks — singleton composable, persisted via useStorage under api:bookmarks. Record shape { name, apiType, apiLink } (Vue APIs excluded — they have no v0 page). Modeled on the existing useSearch favorites block.
  2. 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.
  3. useMovable + CompanionPanel — a headless position/mode state machine (docked | floating | minimized) plus the panel shell that consumes it, useStack (z-layer), and useApiBookmarks. 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)

  • useApiBookmarks store (toggle/has/remove/clear/count, persisted).
  • Star toggle in DocsApiHover header; builds the bookmark record from the current hover entry.
  • CompanionPanel as a docked right-side sheet (mirrors AppSettingsSheet: fixed sheet + useStack ticket + Escape-to-close), listing bookmarks with per-row navigate + remove.
  • Trigger button in AppBar with a count badge.

Phase 2 — detach + drag

  • useMovable headless composable: position math, viewport clamping, mode machine; persistence flows in via initial/initialMode and out via onChange (no app coupling).
  • Wire floating mode into CompanionPanel: 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 Tabs switch — the checkpoint that justifies extracting useMovable into packages/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, descriptive aria-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 in DocsApiHover).
  • Persistence starts local (localStorage via useStorage); a synced path is possible later if accounts land.
  • Verification is manual (pnpm typecheck + browser checks) per repo testing policy.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.