Skip to content

fix(share): simplify + make the Share dialog honest (SHR-1/2/3/4/6)#125

Merged
eliotlim merged 6 commits into
mainfrom
feat/sharing-dialog-simplify
Jul 12, 2026
Merged

fix(share): simplify + make the Share dialog honest (SHR-1/2/3/4/6)#125
eliotlim merged 6 commits into
mainfrom
feat/sharing-dialog-simplify

Conversation

@eliotlim

Copy link
Copy Markdown
Owner

Problem

The per-page Share dialog was convoluted and, worse, dishonest:

  • Bare Copy link buttons on an unpublished desktop silently copied a dead tauri://localhost link and reported success — a link that resolves to nothing for anyone off that device.
  • "Forward" / "Forwarding" jargon leaked the internal verb instead of the user-facing Publish.
  • The scope picker showed 5 flat options — including dormant ones (members, authenticated) — as if they were equal everyday choices.
  • When a link was dead, the dialog dead-ended into Settings to publish instead of letting you publish in place.
  • "Workspace default" misstated the true effective default, so inherit was a mystery box.

Epic: Epic: Sharing & publishing — simplify + make honest (IA 2026-07)
Closes SHR-1 / SHR-2 / SHR-3 / SHR-4 / SHR-6.

Solution

In-repo, user-facing only:

  • Dead-link guard (useCopyPageLink): on a publish-capable desktop that isn't published, copy-link raises a toast pointing at publishing rather than silently copying a dead URL.
  • "Publish" wording replaces the last "Forwarding" strings across all four locales.
  • Progressive-disclosure scope picker: the everyday scopes (Workspace default / Anyone with the link / Only people invited) are up front; the obscure authenticated sits behind a More access options reveal; dormant members is hidden — but whatever scope a page is currently set to is always offered, so no stored value is ever stranded.
  • Inline Publish in the dialog (desktop, unpublished) reusing the existing useForwarding().enable() — no new exposure, just no detour into Settings.
  • Honest effective-default summary via an additive read-only InstanceInfo.defaultVisibility, so "Workspace default" states what it actually resolves to.

In-repo only — no edge / account / default changes. The cross-repo site-visibility bridge is SHR-8 (owner-gated) and is not in this PR.

Key files: ShareDialog.tsx, useCopyPageLink.ts, the 3 copy-link call sites (NavContextMenu / PageContextMenu / PageActionsCluster), server/app.ts (+ read-only field), sdk/provenance.ts (type), i18n ×4. No new deps.

This PR also folds in the pre-endorsed review nits (all gates approved with nits only): gate the inline claim-warning on !enabled so it doesn't re-show mid-reconnect; keep "Workspace default" among the primary scopes so reset-to-default stays reachable; finish the Publish rename on the last four edge-state strings; advanced-reveal a11y (move focus to the scope Select + relabel to "More access options"); tighten two copy lines that overstated access; and add an e2e for the new scope path.

Before / After

Behaviour Before After
Scope picker options
5 flat scopes, incl. dormant members / authenticated, as equal choices

3 everyday scopes up front; authenticated behind the reveal, members hidden
Whole Share dialog
no progressive disclosure; no honest default read

More access options reveal + honest effective-default line
Unpublished-desktop copy link Silently copies a dead tauri://localhost; dialog dead-ends into Settings to publish Dead-link guard toast; inline Publish button in the dialog
Edge-state + copy wording "Forwarding is on…"; "a link you can send to anyone"; "inherited pages" "Publishing is on…"; "a link you can share"; "pages set to Workspace default"

The captures come from the standalone web harness (no desktop forwarding), so the inline-Publish affordance isn't shown in the images — it's covered in the text row above.

Test procedure

  • pnpm verifygreen: sdk 171, ui 950, server 645 unit tests; server e2e 251 checks; MCP e2e 40 checks.
  • New scope-picker e2e (packages/web/e2e/share.spec.ts): asserts the primary options show, the More access options reveal exposes authenticated, and a selected advanced scope round-trips (persists via setPageVisibility and rehydrates on reopen). It type-checks under the web tsc pass; it runs in CI's sharded Playwright suite (it couldn't be run locally — a dev server was squatting on :3000).
  • The share-dialog @visual Chromatic baseline shifts intentionally (new "More access options" link + streamlined options).

Operational notes

  • No migrations, no env changes.
  • Gates cleared: security ✓ Sasha · code ✓ Quinn · design ✓ Devon.
  • Deferred (non-blocking, follow-up): copy-link toast non-manager gating; defaultVisibility viewer-gating; inline-publish + effective-default e2e (needs a forwarding mock).

pnpm verify green (sdk 171 / ui 950 / server 645 unit · server e2e 251 · MCP e2e 40) · gates cleared: security ✓ Sasha, code ✓ Quinn, design ✓ Devon.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KFk2T9k3p7ghCjdzMfkA5w

eliotlim and others added 6 commits July 11, 2026 22:01
On a publish-capable desktop that isn't currently published, the bare
"Copy link" buttons copied a `tauri://localhost` deep link that is dead
for anyone else — and reported success silently. Route all three (the
page-actions cluster, the page context menu, the nav "…" menu) through a
shared `useCopyPageLink` hook that, in that local-only case, toasts and
offers a "Publish" action into Settings → Sharing instead of copying.
Published desktops, the web app, and LAN/remote servers copy as before.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KFk2T9k3p7ghCjdzMfkA5w
…SHR-2)

The web relay publish path was labelled "Forward to the web" / "Forward
this device" — unfamiliar wording that also blurred it against the LAN
listener. Rename the forwarding surface (title, toggle, sign-in-pending
and resumed announcements) to "Publish to the web" / "Publish this
device", and retitle the LAN listener "Share on local network
(advanced)" so the two publish paths read as clearly distinct. Copy only,
no behavior change; en/de/ja/zh.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KFk2T9k3p7ghCjdzMfkA5w
The scope select listed all five visibility scopes flat — including
dormant `members` and the power-user `inherit`/`authenticated` — as if
equal everyday choices. Show only the two that carry the real decision
(`restricted` vs `public`) by default, tuck `inherit`/`authenticated`
behind an "Advanced options" reveal, and drop `members` from the choices.
Whatever the page is currently set to is always included, so a stored
`members`/`authenticated`/`inherit` value still renders and stays
settable. en/de/ja/zh.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KFk2T9k3p7ghCjdzMfkA5w
…" (SHR-6)

The `inherit` ("Workspace default") summary read the guest gate, so on a
claimed instance it misstated what inheriting resolves to — inherit
actually resolves to the root `defaultVisibility` (e.g. members) once
claimed; the guest gate only governs an unclaimed instance's rule-0
short-circuit. Expose `defaultVisibility` in `InstanceInfo` and, when the
instance is claimed, summarise from it (falling back to the guest-gate
line for unclaimed / pre-SHR-6 servers). Display-truth only — the actual
default is unchanged. en/de/ja/zh.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KFk2T9k3p7ghCjdzMfkA5w
On an unpublished desktop the dialog pointed managers at "Settings →
Sharing & publishing" to get a sendable link — a detour that left the
copied link dead in the meantime. Replace that pointer with an inline
"Publish this device" button that drives the SAME `useForwarding().enable()`
the Settings toggle runs (claim + dial out — no new exposure), with the
claim warning, sign-in handoff, and refusal states shown inline. Once the
tunnel is online the normal copy-link footer takes over with the forwarded
URL, so a fresh desktop reaches a working link without leaving the dialog.
The local-only hint is trimmed for the non-manager case. en/de/ja/zh.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KFk2T9k3p7ghCjdzMfkA5w
Pre-endorsed review fixes on the SHR-1..6 Share-dialog simplification
(security ✓ Sasha, code ✓ Quinn, design ✓ Devon — all nits only):

- Gate the inline-publish irreversible-claim warning on `!enabled` too, so
  it doesn't redundantly re-show mid-reconnect (matches
  SharingPublishingSettings). (Quinn)
- Keep "Workspace default" (`inherit`) among the primary scopes so
  resetting to the workspace default is always reachable, not buried; only
  the obscure `authenticated` sits behind the reveal. (Devon)
- Finish the Publish rename: swap the last four "Forwarding" edge-state
  strings (partialUnscoped / ensureRescope / bindFailed / unbindHeld) to
  "Publishing" across en/de/ja/zh. (Devon)
- Advanced-reveal a11y: move focus to the scope Select on reveal and
  relabel the link to "More access options". (Devon)
- Tighten two copy lines that overstated access: the publish hint →
  "get a link you can share", and effective-default → "pages set to
  Workspace default" (not "inherited pages"), across all locales.
  (Sasha + Devon)
- Add an e2e covering the SHR-4 progressive-disclosure scope path:
  primary options show, the reveal exposes `authenticated`, and a stored
  advanced scope round-trips.

No access-default, edge, relay, account, or server changes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KFk2T9k3p7ghCjdzMfkA5w
@vercel

vercel Bot commented Jul 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
app.book.pub Ready Ready Preview, Comment Jul 11, 2026 3:16pm

Request Review

@eliotlim eliotlim merged commit 1d89d84 into main Jul 12, 2026
10 checks passed
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