feat(share): briefing copy actions + personalized digest share parity - #6353
feat(share): briefing copy actions + personalized digest share parity#6353tsahimatsliah wants to merge 5 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
The preview deploy resolves The flag default in git revert 6cf22f33b |
A presidential briefing is one of the most shareable things daily.dev
produces, and there was almost nowhere to share it from: the briefing list
had no copy affordance, the header had a single desktop-only copy-link
button, the briefing body had none at all, and the personalized digest —
which renders the same header component — had nothing.
- `/briefing` rows gain copy-link and a share arrow.
- The briefing body gains a copy control on every heading, bullet and
paragraph. `BriefContent` wraps `Markdown`, appends a mount node per item
and portals a control in, since the body is one sanitized-HTML blob. A
heading copies its whole section; every copy appends the briefing link so
a paste stays attributed.
- The post header gains the same copy + share pair, outside the laptop-only
wrapper so it works on mobile.
- `DigestPostContent` passes `showShareButton`, reaching parity with the
brief.
One glyph per meaning across all of it: arrow opens a share surface, link
copies the bare URL, stacked squares copy text with the link appended, page
copies the summary. Every control confirms with the design system's success
checkmark and a `ToastType.Success` toast.
Also fixes a pre-existing layout bug: `base.css` sets a global
`* { flex-shrink: 0 }`, so the row's `w-full` text column refused to shrink
and painted trailing controls ~100px outside the card on every row.
Gated by `share_briefing_digest`, which also requires the master
`sharing_visibility` kill-switch. Flag-off is identical to PR 1.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bc27c9d to
06d9043
Compare
|
Rebuilt as a single clean commit on top of PR 1. The temporary Consequence for preview testing: |
…ORE MERGE The preview deploy resolves `share_briefing_digest` to its `false` default, so none of this PR's surfaces render there. `isDevelopment` is false in a Vercel preview build (NODE_ENV is `production`), so the documented local escape hatch does not reach it. Isolated in its own commit on purpose: `git revert` restores the real gate and leaves the feature commit untouched. The flag default in `featureManagement.ts` stays `false`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
It sits in its own commit on top of the feature commit, so Revert before merge. |
A briefing should read as prose, not as a grid of affordances. The controls inside the body now sit at `opacity-0` and are revealed by hovering their own item. Touch has no hover, so coarse pointers still get them outright, and keyboard focus reveals them too — otherwise the feature would be unreachable in both. The control stays pinned while confirming so the checkmark survives the pointer leaving as the click lands. Scoped to `BriefContent`: the `/briefing` row and the post header keep their always-visible controls, since those are single controls on a card rather than one per line of prose. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The link riding along with every in-briefing copy was `post.commentsPermalink` raw, while every other share surface copies a tracked, shortened URL built with `ReferralCampaignKey.SharePost`. These were the only shares in the app going out uncredited — traffic from a pasted bullet was attributed to nobody. Resolved through `useGetShortUrl` up front rather than awaited in the click handler: awaiting there would put the clipboard write outside the user gesture, which browsers can block. `getTrackedUrl` covers the logged-out and still-loading cases. Also spreads `logOpts` from `ActiveFeedContext` on the briefing share events, matching `usePostContent`, `SocialShare` and `ShareBar`, so a brief or digest opened as a feed modal carries grid position like every other post share. It is a no-op on `/briefing`, which provides no `logOpts`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
capJavert
left a comment
There was a problem hiding this comment.
Code review complete. Blocking before merge: useShareBriefingDigest still contains FORCE_ON_FOR_PREVIEW = true, which bypasses both sharing_visibility and share_briefing_digest for every environment. Revert commit 7441c0f68 as documented before this can be approved. I found no merge conflict; the PR is currently clean against its stacked base.
…VERT BEFORE MERGE" This reverts commit 7441c0f.
|
@capJavert Fixed in You were right, and more right than my own commit message was. I labelled it "for preview", but
return isSharingVisible && value;
Why it existed, for context: Verified after the revert: shared 296 suites / 2004 tests, webapp 44 / 297, strict typecheck and Two things in this PR that are additive to analytics and worth a heads-up rather than a change:
Existing dashboards will not break, but they will not include these copies until the filters are widened. Happy to rename either if you would prefer they fold into an existing value. |
PR 7 of the sharing-visibility initiative. Stacks on PR 1 (#6343) — base is
claude/website-sharing-visibility-be6b32, notmain.A presidential briefing is one of the most shareable things daily.dev produces, and there was almost nowhere to share it from: the briefing list had no copy affordance, the header had a single desktop-only copy-link button, the briefing body had none at all, and the personalized digest — which renders the same header component — had nothing whatsoever.
What changed
1.
/briefingrows (BriefListItem.tsx) — copy-link and a share arrow at the end of each row.2. Inside the briefing body (new
BriefContent.tsx) — the body is a single sanitized-HTML blob fromMarkdown, so there was no per-item affordance: the only way to share one finding was to select text by hand.BriefContentwrapsMarkdown, appends a mount node to every heading, bullet and paragraph, and portals a copy control into it.A bullet or paragraph copies its own text; a heading copies its whole section — heading, prose, then one bullet per line — stopping at the next heading. The selector is deliberately wide (
h1–h4,li, standalonep): the body is model-generated, so heading level and bullets-vs-prose vary between briefings, and matching onlyh2/h3/lileft some briefs with no controls at all. Controls are dimmed at rest and come to full strength on hover or focus — never hover-only, which is undiscoverable on a mouse and unreachable on touch.3. Post header (
BriefPostHeaderActions.tsx) — the same copy + share pair, outside thehidden laptop:blockwrapper, since sharing a briefing matters at least as much on mobile. Copy link is its own control rather than living only inside the popover: it is the most common action and should not cost two taps.4. Digest parity (
DigestPostContent.tsx) — it rendered the identical header component withshowShareButtonomitted, so it had no share affordance. Now passes it, gated. While making it a changed file the strict-typecheck guard surfaced its pre-existing strict-null backlog, fixed by mirroringBriefPostContent. No behaviour change.Icon language
The share trigger, the copy-link control and the copy-text actions all rendered a copy or link glyph, so "share" and "copy" were indistinguishable. Settled to one glyph per meaning:
ShareIcon)CopyIcon)DocsIcon)Every text copy appends the briefing link, so a paste into Slack is quotable and still carries attribution.
Copy confirmation
Every control confirms with the design system's success checkmark (
VIcon/text-status-success) for 1s, and toasts useToastType.Successso the chip carries the same check.New
useCopyFeedbackhook:useCopyalready exposes acopyingflag, but there is one per hook instance — the controls inside a briefing share one, so using it directly would light them all at once. The hook tracks which control fired.Structure
BriefShareControls.tsxholds the copy + share pair and the standalone copy-link button, used by both the row and the header so the two surfaces cannot drift.Layout fix
base.csssets a global* { flex-shrink: 0 }, so the row's text column kept itsw-fullwidth and refused to shrink: the trailing control painted ~100px outside the card border on every row, not just long titles.min-w-0 flex-1restores a shrinkable basis and the title truncates. Measured 0px overflow at 640/480/360px.Flag
share_briefing_digest, defaultfalse, resolved byuseShareBriefingDigest, which also requires the masteruseSharingVisibility()gate.Flag-off is identical to PR 1, asserted in Jest: the row renders no interactive controls, the header keeps its legacy copy-link button, the body renders exactly as today, and the digest exposes nothing.
Storybook
stories/components/BriefSharing.stories.tsx— every state of all four surfaces, each in flag-on and flag-off form, plus anOverviewmapping them on one page and anIconLanguagestory documenting the vocabulary.Two notes for reviewers:
useConditionalFeaturereads GrowthBook throughFeaturesReadyContext+GrowthBookContext. With neither mounted — Storybook's default — every flag resolves to itsdefaultValue, i.e. off. (The'control'-returning mock in.storybook/main.tsapplies touseFeature, not this path.) A smallFeatureGateprovider pins flags per story, which the header needs since it reads the gate directly and has no override prop.Toastrenderer is mounted in the decorator. Copy actions already toasted throughuseCopy, but Storybook never rendered it, so the confirmation was invisible there.OG image — deferred, deliberately
Not shipped.
packages/webapp/pages/image-generator/pages are plain Next.js pages that a backend screenshot service renders and captures. A briefing OG image needs that service taught a new route plus an ISR data path for brief posts — a backend dependency that cannot land from this repo alone.Verification
node ./scripts/typecheck-strict-changed.js— passedpnpm --filter shared lint— cleanNODE_ENV=test pnpm --filter shared test— 296 suites / 2004 testsNODE_ENV=test pnpm --filter webapp test— 44 suites / 297 testsNODE_ENV=test pnpm --filter extension test— 6 suites / 43 testsTests cover both copy payloads and the section boundary, the wide selector against an
h1/h4prose-only brief, the nested-paragraph case, the checkmark appearing only on the clicked control and clearing after its window, logging discriminators per item kind, and flag-off rendering nothing.🤖 Generated with Claude Code
Preview domain
https://claude-share-briefing-digest.preview.app.daily.dev