From ad496c0fb53706f221241dd48440c68d3333937d Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Sun, 6 Sep 2026 19:48:19 -0700 Subject: Chat reactions render inside the bubble (Telegram-style), not floating below it. Reactions were a sibling of the bubble (a separate row under it), so they hung outside the message. Moved the reaction pills inside .chat-bubble, tucked under the text, across all three renderers: community channel messages, DMs, and the read-only public /chat page. The pill background and the "your reaction" highlight border now derive from the bubble's own text colour (color-mix on currentColor), so they read correctly on both the plain bubble and the accent "me" bubble. Tapping a pill stops propagation so it toggles the reaction without also opening the message action sheet. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MGzU12QrAA4G6BYGzGVdXz --- src/features/messages.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'src/features') diff --git a/src/features/messages.js b/src/features/messages.js index 66a1270..4455711 100644 --- a/src/features/messages.js +++ b/src/features/messages.js @@ -2984,16 +2984,17 @@ export function messagesFeature(ctx) { edit ? h('span', { class: 'chat-edited' }, ' ', t('msgEdited')) : null, mine ? h('button', { class: 'chat-del', title: t('msgDelete'), onClick: () => deleteMessage(room, chId, m) }, '×') - : null), - counts.size - ? h('div', { class: 'chat-reacts' }, - [...counts.entries()].map(([emoji, n]) => - h('span', { - class: 'chat-react clickable' + (emoji === myReact ? ' on' : ''), - title: t('msgReact'), - onClick: () => sendReaction(room, chId, m, emoji), - }, emoji, n > 1 ? ' ' + n : ''))) - : null) + : null, + // reactions tuck inside the bubble, under the text (Telegram-style) + counts.size + ? h('div', { class: 'chat-reacts' }, + [...counts.entries()].map(([emoji, n]) => + h('span', { + class: 'chat-react clickable' + (emoji === myReact ? ' on' : ''), + title: t('msgReact'), + onClick: (e) => { e.stopPropagation(); sendReaction(room, chId, m, emoji); }, + }, emoji, n > 1 ? ' ' + n : ''))) + : null)) ); }); } @@ -3206,7 +3207,7 @@ export function messagesFeature(ctx) { return h('div', { class: 'chat-reacts' }, [...counts.entries()].map(([emoji, n]) => h('span', { class: 'chat-react clickable' + (emoji === myReact ? ' on' : ''), - onClick: () => sendDmReaction(peer, m, emoji), + onClick: (e) => { e.stopPropagation(); sendDmReaction(peer, m, emoji); }, }, emoji, n > 1 ? ' ' + n : ''))); }; const dmReplyBar = () => { @@ -3246,8 +3247,7 @@ export function messagesFeature(ctx) { ui.msgSheet = ui.msgSheet === m.rumor.id ? null : m.rumor.id; render(); }, - }, dmQuote(m), ...noteBody(m.rumor.content)), - dmChips(m), + }, dmQuote(m), ...noteBody(m.rumor.content), dmChips(m)), h('div', { class: 'chat-time' }, timeLabel(m.rumor.created_at * 1000))))) : [h('div', { class: 'muted small', style: 'text-align:center;padding:24px 0' }, t('msgNoDmsYet'))])), dmReplyBar(), -- cgit v1.2.3