Skip to content

feat(share): flat end-of-conversation band + split copy-link button#6369

Draft
tsahimatsliah wants to merge 7 commits into
claude/share-end-of-conversationfrom
claude/share-split-copy-button
Draft

feat(share): flat end-of-conversation band + split copy-link button#6369
tsahimatsliah wants to merge 7 commits into
claude/share-end-of-conversationfrom
claude/share-split-copy-button

Conversation

@tsahimatsliah

@tsahimatsliah tsahimatsliah commented Jul 23, 2026

Copy link
Copy Markdown
Member

Stacked on #6349 (claude/share-end-of-conversation), which is itself stacked on #6343. Review #6343#6349 → this one, or read this diff alone — it only touches the band and its share control.

#6349 introduced the end-of-conversation share band as a bordered card with an icon-only share trigger, behind two feature flags. This PR is the design pass on top of it: the band goes flat by default, the trigger becomes a labelled split button, and the band ships to everyone.

Shipping to everyone

The band is no longer gated. share_end_of_conversation is deleted (nothing else read it) and the sharing_visibility kill-switch check is dropped from this component, so the comment threshold is the only condition. The flag and useSharingVisibility stay in the codebase — they gate the other surfaces in the initiative.

That means no runtime off-switch for this band: turning it off after merge takes a revert. Flagged deliberately, per the product call to show it to everyone.

The band

flat is now the default variant: no fill, no card border, just a top hairline separating the strip from the comments above it. card is still available via variant="card" for surfaces that want the heavier self-contained block.

The split copy control

ShareActions gains a split variant — two real buttons that read as one control:

  • Left half copies the link straight away. The copy glyph cross-fades into a green check on success (opacity + scale + blur, all compositor-only, collapsing to an instant swap under prefers-reduced-motion).
  • Right half is a chevron that opens the design-system DropdownMenu with the standard social tiles. It rotates to point back at the menu it opened.

Geometry follows the button guidelines exactly rather than approximating them: at every ButtonSize the control matches a standard button's height, corner radius, type scale and outer padding. The only deviations are at the shared edge — both inner paddings tighten one step so the seam isn't sitting in a canyon, and the chevron drops the icon-only square so it hugs the seam symmetrically.

The divider

The two halves are separated by a single rule, not two borders meeting:

Variant Divider
Secondary / Float / Subtle the chevron half's own DS border (the main half drops border-r) — full height, matching the outer edge in width, colour and hover transition by construction
Primary no border to inherit, so a full-height rule in the label colour at 20%
Tertiary a ghost button, so a full-height rule would float — a shorter rule (6px inset) in exactly the colour tailwind/buttons.ts gives Subtle's border

Two build-level gotchas worth knowing, both commented in the code:

  • bg-current compiles to nothing here — this theme replaces Tailwind's colors wholesale and has no current key. A hairline drawn with it renders as no hairline, which is what let the two real borders read as a double rule in the first place.
  • before:opacity-* does not survive this project's Tailwind build on pseudo-elements: the class lands in the DOM and the element renders at full strength. Both dividers mix their alpha into the colour instead.

Structure

  • SplitShareButton.tsx — the control (padding maps, divider, chevron, dropdown).
  • CopyStateIcon.tsx — the cross-fading copy/check glyph, shared with the mobile and popover paths.
  • ShareActions.tsx — back to a variant router.

The icon variant still uses the existing Popover rather than DropdownMenu; migrating it would change the DOM of every icon-only share surface in the app, so it is deliberately left for a follow-up.

Storybook

  • Components/Share/EndOfConversationShare — every state (below/at/above threshold, no comments, flat vs card, dark/light), plus a real 390px iframe for the mobile path.
  • Components/Share/SplitShareButton — the split control across all five variants and all five sizes, and an AgainstStandardButtons page that prints live computed geometry (height, radius, type, padding) beside the standard buttons so the guideline match is checkable rather than asserted.

Verification

  • 18 tests pass across ShareActions.spec.tsx, EndOfConversationShare.spec.tsx, PostComments.spec.tsx, including a new test that opens the dropdown and asserts the social tiles are present. Tests for the now-removed flag paths are deleted rather than inverted.
  • packages/webapp PostPage suite passes (48 tests) — cross-package check per AGENTS.md.
  • Shared lint clean, changed-file strict typecheck clean.
  • Divider colours verified in-browser against Subtle's computed borderLeftColor.

Seeing it on the preview

Open any post with more than 3 comments — no flags to toggle.

🤖 Generated with Claude Code

Preview domain

https://claude-share-split-copy-button.preview.app.daily.dev

@vercel

vercel Bot commented Jul 23, 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 23, 2026 2:03pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
storybook Ignored Ignored Jul 23, 2026 2:03pm

Request Review

tsahimatsliah and others added 3 commits July 23, 2026 15:19
Adds a `split` variant to ShareActions: two real buttons that read as one
control. The left half copies the link and cross-fades its glyph to a green
check; the right half is a chevron that opens the standard DropdownMenu with
the social tiles.

Geometry matches a standard Button at every size — height, radius, type scale
and outer padding — deviating only at the shared edge, where both inner
paddings tighten one step and the chevron drops its icon-only square.

The divider is a single rule: the chevron half keeps its own DS border while
the main half drops `border-r`, since two borders meeting is what reads as a
double line. Borderless variants have no border to inherit and draw their own.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drops the card's fill and border for a single hairline rule separating the
strip from the comments above it, and moves the trigger to the labelled split
button. `variant="card"` keeps the heavier self-contained surface for surfaces
that want it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Every band state (either side of the threshold, flat vs card, in context below
a comment list, a real 390px mobile frame) and the split control across all
variants and sizes, with computed geometry printed beside the standard buttons
so the guideline match is checkable rather than asserted.

The auth/log/query decorator the share stories share is extracted to
`share.mocks.tsx` — it had been copied verbatim into three story files.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Removes both gates: the `share_end_of_conversation` experiment flag (deleted,
nothing else read it) and the `sharing_visibility` kill-switch check. The
comment threshold is now the only condition, so the two-component split
(gated wrapper + ungated band) collapses into one.

`useSharingVisibility` and `sharing_visibility` stay — they gate the other
surfaces in the initiative, this one just no longer consumes them.

Tests for the discarded path are removed rather than inverted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Review pass over the PR:

- The copy confirmation was swapped in for every ShareActions variant, which
  silently restyled the icon-only triggers on the feed card, brief header and
  mobile share widget. Those keep the existing `secondary` fill; the green
  check is now the split control's alone.
- The flat band set `py-4 pt-6`, which resolved correctly only because
  Tailwind emits `pt-*` after `py-*` in the stylesheet — class order in the
  attribute has no bearing on it. Now `pb-4 pt-6`.
- `hasActiveDiscussion` lost its last external caller with the flag wrapper,
  so it is no longer exported.
- Comment still cited the old "Share this discussion" label.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- The chevron carried `pressed`, which renders `aria-pressed` and is painted
  as a held-down fill. Removed: the rotation is the only open-state signal the
  control wants, and Radix already sets `aria-expanded`, which is the correct
  semantic for a menu trigger.
- The split dropdown repeated a "Share" heading under a trigger that already
  says so, and centred its tiles. Heading dropped and tiles aligned left. The
  popover used by the icon-only surfaces keeps both.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The `p-4` on DropdownMenuContent never applied — the dropdown's CSS module
applies `p-1.5` at the same specificity and wins on stylesheet order, leaving
6px. And `flex-wrap` with `justify-start` collected all the leftover row width
on one side, so the insets measured top 7 / right 41 / bottom 29 / left 15.

Now `!p-4` so the override lands, and a 4-column grid whose columns divide the
content box exactly. Measured insets: top 17 / right 17.8 / bottom 17 /
left 17.8 — the 1.8px is cell-centring slack, identical on both sides.

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