Skip to content

feat(share): share/copy on hot-take surfaces#6365

Draft
tsahimatsliah wants to merge 2 commits into
claude/website-sharing-visibility-be6b32from
claude/share-hot-takes
Draft

feat(share): share/copy on hot-take surfaces#6365
tsahimatsliah wants to merge 2 commits into
claude/website-sharing-visibility-be6b32from
claude/share-hot-takes

Conversation

@tsahimatsliah

@tsahimatsliah tsahimatsliah commented Jul 22, 2026

Copy link
Copy Markdown
Member

Part of the sharing-visibility initiative (PR 19 — hot takes, #23). Builds on the PR 1 foundation branch.

Changes

Share/copy affordances on every hot-take surface, all composing the shared ShareActions primitive through one new HotTakeShareControl / HotTakeShareButton (flag-gated wrapper):

  • HotTakeItem / HotTakeItem.v2 — share icon in the action area (between the owner edit/delete hover group and the upvote), driven by a new optional ownerUsername prop so existing consumers keep their exact DOM when it is absent.
  • ProfileUserHotTakes header — section-level share next to the owner "Add" button, shown to owners and visitors, only when the section has at least one take (flag not even evaluated for empty sections).
  • HotAndColdModal card — share pinned top-right of the top card of the swipe stack only (rendered last + explicit z-20 above the swipe-effect overlays); hidden for takes without an author.
  • PopularHotTakesList header — board-level share implemented INSIDE the component via the existing header slot of LeaderboardList; the custom header mirrors the container's stock heading markup so flag-on only adds the control. pages/users.tsx is untouched (owned by claude/share-leaderboard, PR feat(share): leaderboard share affordances + share-my-rank card #6359 — post-merge my header prop still wins over its titleAction default, so no double affordance).

Deep links: new getHotTakesProfileUrl(username) (reuses HOT_TAKES_ANCHOR, deliberately without the addHotTake query that getAddHotTakeProfileUrl carries, which would pop the add-modal for owners) — a shared link lands on the hot-takes section of the owner's profile. Popular-list rows were refactored to the same helper (byte-identical URL). Pre-filled text quotes the take: Hot take: "…" — @user on daily.dev.

Logging

One entity-level event for all surfaces — no per-surface event names:

  • LogEvent.ShareLog (existing) + new Origin.HotTake = 'hot take' (appended at the end of the Origin enum; the existing HotTakeList/HotAndCold origins are per-surface vote origins, not a generic hot-take origin)
  • target_id = hot take id (single-take shares) / owner id (section share)
  • extra = { provider, origin, surface } with surfaceprofile item | profile header | hot and cold modal | popular hot takes

Flag

share_hot_takes, default false, appended at the END of featureManagement.ts. Gated via useHotTakeShareEnabled = useSharingVisibility() master switch AND the per-topic flag through useConditionalFeature + shouldEvaluate (per-topic flag only evaluated once the master switch is on, so control users are never bucketed). Flag-off is byte-identical to the PR 1 branch — asserted in Jest (innerHTML equality on items, structural identity on headers).

V1/V2 variant findings

HotTakeItem.tsx is a wrapper that picks the variant at runtime via useEngagementBarV2() (auth user + engagement_bar_v2 flag): V2 (.v2 file, ButtonV2/CardAction) for flagged authenticated users, V1 (QuaternaryButton) otherwise. Both are reachable, so both variants got the identical share control; a describe.each spec covers both.

Composition audit

  • HotTakeItem is rendered only by ProfileUserHotTakes → per-item control + section-header control coexist (item + list-header, no same-element duplicates).
  • HotAndColdModal's onboarding mode renders OnboardingPostCard (posts, not hot takes) — untouched; only HotTakeCard gets the control, and only the top card of the stack (asserted: exactly one control with nextTake present).
  • PopularHotTakesList rows are plain profile links → header control only.
  • Tests assert exactly one control per element on every surface.

Verification

  • node ./scripts/typecheck-strict-changed.js — pass
  • pnpm --filter shared lint — exit 0
  • NODE_ENV=test pnpm --filter shared test — 297 suites / 2005 tests passed
  • NODE_ENV=test pnpm --filter webapp test — 44 suites / 297 tests passed (incl. MyFeedPage, no re-run needed)
  • git diff --name-only origin/claude/website-sharing-visibility-be6b32...HEAD — 16 files, all in scope; pages/users.tsx absent
  • Storybook: HotTakeShare.stories.tsx covers item (V1 + V2), modal-card and popular-list states plus controls; flag-off stories hold FeaturesReadyContext not-ready since the repo-wide mock/gb.ts coerces false defaults truthy — Jest is the real flag-off guarantee. storybook lint not runnable (pre-existing).

Follow-up (not in this PR)

Image-share for a single hot take (rendering the take as a shareable card image) is likely the right long-term shape for this surface — deliberately not built here; this PR is link+text only.

🤖 Generated with Claude Code

Preview domain

https://claude-share-hot-takes.preview.app.daily.dev

Share affordances on every hot-take surface, built on the PR 1
ShareActions primitive: HotTakeItem (V1 + V2) action area, the
ProfileUserHotTakes section header, the HotAndColdModal top card, and a
header share inside PopularHotTakesList (pages/users.tsx untouched).

- deep links land on the owner profile's #hot-takes anchor
  (getHotTakesProfileUrl), pre-filled text quotes the take
- one generic ShareLog event with the new Origin.HotTake for all
  surfaces; extra.surface distinguishes, target_id = take id / owner id
- behind share_hot_takes (default false) AND the sharing_visibility
  master flag via useHotTakeShareEnabled; flag-off is byte-identical
  (asserted in Jest on every surface)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 22, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
daily-webapp Ready Ready Preview Jul 22, 2026 8:00pm
storybook Building Building Preview Jul 22, 2026 8:00pm

Request Review

Replaces the free-string extra.surface vocabulary that shadowed existing
enum values: the modal reuses Origin.HotAndCold, the profile surfaces reuse
Origin.HotTakeList (target_id already separates item from header), and the
leaderboard card gets a proper PopularHotTakes member in place of HotTake.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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