Skip to content

Share mode: contextual formatting toolbar#16

Open
cathrynlavery wants to merge 1 commit intoEveryInc:mainfrom
cathrynlavery:os/feature/share-formatting-bar
Open

Share mode: contextual formatting toolbar#16
cathrynlavery wants to merge 1 commit intoEveryInc:mainfrom
cathrynlavery:os/feature/share-formatting-bar

Conversation

@cathrynlavery
Copy link

@cathrynlavery cathrynlavery commented Mar 12, 2026

Summary

Adds a formatting toolbar for share-mode documents, giving shared-doc viewers intuitive editing controls without the full app chrome. The bar renders as a vertical right-rail on desktop and a bottom dock on mobile, with a secondary contextual popup (bold/italic/link) that floats near the text selection on desktop.

Why

Share mode is designed for non-technical collaborators — people who may never have used a markdown editor. Previously, shared documents had no visible formatting controls, which meant users had to know markdown syntax or keyboard shortcuts to format text. This PR adds a formatting toolbar that feels like a subtle editorial aid rather than app chrome, keeping the warm, paper-like aesthetic of share mode intact.

Design approach

The formatting bar was designed through a brainstorm process that evaluated three layout directions:

  1. Right-side vertical rail (chosen for desktop) — takes advantage of the ~130px right margin between the 860px editor card and 1120px container. Always visible, doesn't obscure content.
  2. Bottom horizontal dock (chosen for mobile) — frosted-glass strip within thumb reach, avoids collision with the fixed share banner at top.
  3. Inline ruler (rejected) — too intrusive, breaks the reading flow.

The contextual floating toolbar (bold/italic/link) appears on text selection, inspired by Notion/Medium. This keeps inline formatting controls close to the cursor without cluttering the persistent rail with too many buttons.

Key decisions

  • No ProseMirror plugin — avoids editor.reconfigure() which breaks collab/Yjs state after initialization. Instead uses selectionchange/keyup DOM listeners for active-state tracking.
  • Hybrid labels — monospace text for headings (H1/H2/H3) and inline (B/I), inlined Lucide SVGs for structural controls (link, lists, quote, code block). No new dependencies.
  • Banner-aware positioning — contextual bar uses getTopViewportInset() to avoid overlapping fixed banners (share, readonly, review-lock, error).
  • Mobile simplification — contextual popup disabled on mobile (≤999px) since the bottom dock already has all controls within thumb reach.

Files changed

File What changed
src/editor/share-formatting-bar.ts New ~490-line self-contained module. Creates both the rail bar and contextual bar using vanilla DOM + ProseMirror commands.
src/editor/index.ts Integration — bar appended to #editor-container after share-mode init, visibility toggled with editable state. Adds data-share-mode attribute on <body>.

What to review

  • share-formatting-bar.ts is the bulk of this PR. Start there.
  • The __fmtSetEditable / __fmtCleanup escape hatches on the bar element (lines 460–490) — using any casts to avoid a class refactor. Fine for now, flag if you disagree.
  • The data-share-mode attribute change in updateBannerLayout touches non-share behavior (removes the old white background override) — verify no regression in non-share mode.

Test plan

  • Open a shared doc on desktop — formatting rail appears on right side when editable
  • Select text — contextual bar (B/I/link) appears near selection, repositions on scroll
  • Click outside editor — contextual bar dismisses
  • Toggle read-only (e.g. review lock) — both bars hide
  • Open on mobile (≤999px) — bottom dock appears, no contextual popup
  • Open a non-share doc — no formatting bar visible, no style regressions

Screenshots

Desktop: vertical rail in the right margin, contextual popup on text selection
Mobile: horizontal frosted-glass dock at bottom

@cathrynlavery cathrynlavery changed the title feat: share-mode contextual formatting toolbar Share mode: contextual formatting toolbar Mar 12, 2026
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