feat(composer): tap once to preview, again to send stickers/GIFs on touch (#147)
CI / Build & Quality Checks (push) Successful in 1m59s
CI / Docker image build & smoke test (push) Skipped
CI / Secret scan (gitleaks) (push) Successful in 6s
CI / Trigger Desktop Build (push) Successful in 5s
CI / Playwright smoke (e2e) (push) Canceled after 4m38s

Fat-finger guard for phones. On coarse-pointer devices the first tap on a
sticker (emoji board Sticker tab) or a GIF parks it in a small bar with a
thumbnail, name, Send and Cancel; a second tap on the same item or Send
sends it; tapping a different item switches the preview; tapping empty
picker space or Cancel clears it. Mouse clicks, keyboard activation and
screen-reader activation (bare click without touch events) still send in
one step, and the emoji tab is untouched.

useRecentTouch records touches inside the picker at the document level so
it survives the Sticker tab remount, and reports false without a coarse
pointer.

Also fixes the compact composer's GIF picker opening mostly off-screen:
end-aligning the 312px popout to a button near the left edge of the
overflow row pushed it to x≈-95; it now anchors to the row itself.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
2026-09-20 00:15:09 -04:00
co-authored by Claude Opus 5
parent bf05751eca
commit 8d11a62e14
5 changed files with 196 additions and 18 deletions
+10 -2
View File
@@ -1339,12 +1339,20 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
{(gifOpen: boolean, setGifOpen) => (
<PopOut
offset={16}
alignOffset={-44}
// [Gitea #147] In the compact overflow row the GIF button sits
// near the left edge; end-aligning a 312px picker to it pushed
// most of it off-screen. Anchor to the row instead.
alignOffset={compact ? 0 : -44}
position="Top"
align="End"
anchor={
gifOpen
? (gifBtnRef.current?.getBoundingClientRect() ?? undefined)
? ((compact
? gifBtnRef.current?.closest('#composer-more-actions')
: gifBtnRef.current
)?.getBoundingClientRect() ??
gifBtnRef.current?.getBoundingClientRect() ??
undefined)
: undefined
}
content={