Skip to content

fix(chat): polish the quick reaction strip and add double-tap tapback - #1605

Merged
bmc08gt merged 3 commits into
code/cashfrom
fix/reaction-strip-polish
Sep 28, 2026
Merged

bmc08gt merged 3 commits into
code/cashfrom
fix/reaction-strip-polish

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

PR 1 of the chat polish brief (reaction strip), matched to iOS, plus two backdrop gaps and a half-sheet bug found while testing it.

Reaction strip

  • Fades follow the scroll position instead of a fixed gradient. The leading fade runs 20dp in from the edge. The emoji scroll on under the "+", which frosts them with a Haze blur; the trailing fade runs from the middle of the "+" to 14dp past it, where the 40dp circle is last as tall as a 28dp emoji, and everything from there to the strip's end is hidden. Ending it later let emoji poke out around the circle's curve. Both fades mirror in RTL.
  • Centering: emoji line height equals the font size, with LineHeightStyle(Center, Trim.Both) and no font padding, so glyphs sit centered in their circles. The "+" is 40dp.
  • End padding is Inset + AddSize + ItemSpacing, 52dp (was 74dp).
  • Placement: the strip always opens above the bubble. It only goes below for a bubble taller than the viewport. Focusing a message that can take reactions scrolls an extra 55 + 16 + 8dp so the strip has room under the top bar.

Final constants, identical to iOS:

Constant Value
Strip height 55dp
Max width 313dp
Item size 40dp
Item spacing 4dp
Inset 8dp
"+" size 40dp
Leading fade 20dp
Trailing fade 14dp, from the middle of the "+"
Gap to bubble 16dp

The old FadeLead (28dp) is gone.

The six default emoji don't fit in 313dp: they need 8 + 6×40 + 5×4 + 4 + 40 + 8 = 320dp. At rest the strip scrolls 7dp and the last emoji sits under a partial trailing fade. The width is unchanged here; iOS has the same shortfall with the same constants, so this needs a design call.

Double-tap tapback

Double-tapping a bubble that can take reactions presents the strip alone: no selection bar, no actions. It's a new PresentReactionStrip action with a strip-only flag in ChatViewModel, separate from ToggleSelection.

This goes further than spec A5: cash bubbles, link cards and reply quotes take double-tap too. The cost is that their single tap now waits out the double-tap timeout (about 300ms) before opening the cash detail, following the link or jumping to the quote. Buttons inside cards, like "View" and "Invite People", stay instant. The iOS session has been told about the change so both platforms match.

Backdrop

While a message is raised, the composer, the $ button and the items above the oldest message (info and invite cards, the date, the hidden-messages placeholder) drew over the backdrop. They now blur and dim with the transcript. Tapping the dimmed composer clears the selection. These gaps are on code/cash too.

Half sheets

The reactors sheet couldn't stay expanded. A half sheet only offers the expanded detent while its content overflows. Five reactors overflowed at half height but fit when expanded, so expanding withdrew the detent and the sheet snapped back to half. ModalBottomSheetSceneStrategy now keeps the expanded detent once the content has overflowed. This applies to every sheet using AllowSheetExpansionWhenScrollable.

Long-press haptic

A long-press on a message buzzed twice: combinedClickable plays its own long-press haptic, and select also calls vibrator.tick(). Every combinedClickable that reports select now passes hapticFeedbackEnabled = false, so only the tick plays.

Long-presses that do nothing (the strip's emoji and "+", and the pill row's "N more" and "+") no longer play the platform haptic either. A pill's own long-press opens the reactors sheet and keeps its haptic.

The strip's fades were fixed gradients, its emoji sat off-center, and it
opened below bubbles near the top of the list. This matches the iOS spec:

- Fades follow the scroll position: 20dp on the leading edge, and a
  trailing fade that ends at the "+", mirrored in RTL.
- Emoji line height equals the font size, trimmed and without font
  padding, so glyphs center in their circles. "+" is 40dp.
- End padding is Inset + AddSize + ItemSpacing (52dp).
- The strip always opens above the bubble, except for a bubble taller
  than the viewport. Focusing a reactable message scrolls an extra
  55 + 16 + 8dp to make room.
- Double-tap presents the strip alone, with no selection bar or
  actions, on any bubble that can take reactions. Cash bubbles, link
  cards and reply quotes take double-tap too, so their single tap now
  waits out the double-tap timeout. Buttons inside cards stay instant.

While a message is raised, the composer, the $ button and the items
above the oldest message (info/invite card, date) now dim and blur with
the transcript; before, they drew over the backdrop.

Half sheets now keep the expanded detent once their content has
overflowed. The reactors sheet overflowed at half height but fit when
expanded, so it lost the detent on expanding and snapped back to half.
@bmc08gt bmc08gt self-assigned this Sep 28, 2026
@github-actions github-actions Bot added type: fix Bug fix area: ui Compose UI, theme, components, resources and removed type: fix Bug fix labels Sep 28, 2026
combinedClickable plays its own long-press haptic by default, and the
row's select also calls vibrator.tick(), so each long-press buzzed
twice. Turn off the platform haptic on every combinedClickable that
reports select: the row, cash bubbles, reply quotes and link cards.
@github-actions github-actions Bot added the type: fix Bug fix label Sep 28, 2026
The emoji now scroll on under the "+", which blurs them with Haze
instead of cutting them off at its edge. The trailing fade runs from the
middle of the "+" to 14dp past it, where the 40dp circle is last as
tall as a 28dp emoji, and hides everything from there to the strip's
end; ending it later let the emoji poke out around the circle's curve.

Long-presses that do nothing (the strip's emoji and "+", and the pill
row's "N more" and "+") no longer play the platform haptic. A pill's
own long-press opens the reactors sheet and keeps it.
@bmc08gt
bmc08gt merged commit 656a66e into code/cash Sep 28, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: ui Compose UI, theme, components, resources type: fix Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant