Skip to content

Make Share the leading filled action and explain rejected shares - #39

Merged
yixin0829 merged 1 commit into
mainfrom
fix/share-button-prominence
Oct 31, 2026
Merged

yixin0829 merged 1 commit into
mainfrom
fix/share-button-prominence

Conversation

@yixin0829

Copy link
Copy Markdown
Owner

Why

Share creation dropped in one step at the Oct 12 release (602e077). Before the release, about 20% of new generations led to a share link. Since then it has been about 3.7%. Share requests themselves still work. After the release:

  • 78 of 81 share attempts succeeded, with no 413s or 5xx errors.
  • The largest snapshot was about 36 KB, well under the limit.
  • Traffic, device mix and the cached share of requests did not change much.

What changed is how many people try to share. The release turned the only filled button on mobile ("Share snapshot", which was also full-width on desktop) into a small borderless "Share" button. It now sits after an equally weighted "Copy" button. Sharing fell 80% on mobile and 86% on desktop.

Metric: distinct new share links per uncached GET /v1/lp 200 (latency ≥ 3 s). The Oct 8–10 outage is excluded, and repeated clicks on the same snapshot count once.

What changes

  • Share leads as the filled primary button. It now comes before Copy and stays compact: 110 px on desktop and 65 px on phones. The toggle and both actions still fit on one row at 320–390 px. Copy stays secondary. The "Anyone with the link can view a copy of this path." notice and its aria-describedby link are unchanged.

  • Readable share errors. The new shareErrorMessage in client/src/util/shareSnapshot.js maps errors to messages:

    Response Message shown
    400 (moderation), 413, 422 "This path can't be shared. Use Copy to save it instead."
    422 with FastAPI's detail list Same message. Before this change it showed "[object Object]".
    429 (slowapi sends {error}, not detail) A rate-limit message
    Other string details Shown as is
    Network failure "Couldn't reach the server…", instead of the raw TypeError text

    The message says "Copy" because that is the button's label on phones.

  • No sideways scroll on small phones while a link is created. "Creating link..." is still shown on wider screens. Phones keep the short "Share" label during the request; the button is disabled with aria-busy, and its accessible name is "Creating link...". Before this, the label pushed a 320 px page to 352 px wide during the request. That bug predates this PR, but this PR sends more people through that state.

Unchanged:

  • The share request and the click guard.
  • The snapshot format: createShareSnapshot output is byte-identical.
  • The Copy behavior, server code, the proxy, SEO and analytics.

Verification

Check Result
npm run test 28 passed, including new shareErrorMessage cases
npm run build ok
npx playwright test 33 passed

Changes to the e2e tests:

  • Share/copy test (share action stays compact…, now share leads as a compact filled action…). It now also checks that Share is filled, that Copy is secondary, that Share sits left of Copy, and that Share's accessible description is the notice. It still requires Share to be under 200 px.
  • Phone-row tests (320/375/390 px). They now also hold the share request open and assert the row still fits with no horizontal scroll. Without the CSS change, the 320 px test fails: Expected: 320, Received: 393.
  • New test. A 422 with a list detail shows the readable message, no "[object Object]", and Share is enabled again.

Checked in a real browser at 1440, 768, 390, 375 and 320 px, in light and dark themes:

Check Result
Share text contrast 5.57:1 light, 4.59:1 dark (the old light secondary was 4.05:1)
Tab order Toggle → Share → Copy
Focus ring on the filled button Visible in both themes
Requests sent on a rapid double click 1

Reading the result

Use the existing backend logs and Firestore, so no new telemetry is needed:

  • Metric: distinct new docs in learning_path_shares (or deduped POST /v1/shares 201s) ÷ uncached GET /v1/lp 200 (latency ≥ 3 s).
  • Window: 7 to 14 days after the deploy. Before the release, daily rates varied a lot (about 12–38%). With about 100 uncached generations a day, the day-clustered 95% CI is about ±6 pp at 7 days and ±4 pp at 14 days.
  • How to read it:
    • ≥ 12%: the button change caused most of the drop.
    • ≤ 5%: look at the backend content change that shipped with the release (Cloud Run revision 00017).
    • In between: a partial recovery. This version is compact (about 1/11 of the old desktop area), and the notice and the Copy button stay as deliberate differences.
  • Merge timing: to keep the denominator clean, avoid merging changes to generation or cache keys during the window, e.g. Keep punctuation in learning path topics and give them distinct cache keys #36.

Share creation fell from about 20% to 3.7% of new generations when the
Oct 12 release made Share a small secondary button after Copy. Share is
now the compact filled button placed first; Copy stays secondary and the
privacy notice is unchanged.

Rejected shares now show readable messages instead of raw details or
"[object Object]", and phones keep the short label while a link is being
created so the toolbar no longer scrolls sideways at 320px.
@vercel

vercel Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
lp-generator-agro Ready Ready Preview Oct 31, 2026 2:27am UTC

Request Review

@yixin0829
yixin0829 merged commit cc5f812 into main Oct 31, 2026
5 checks passed

This branch was successfully deployed

1 active deployment
Preview — 24db6d58 Deployed Oct 31, 2026 by vercel[bot]
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