feat(messages): collapse reactions to one row with a +N chip (#138)
CI / Build & Quality Checks (push) Successful in 1m36s
CI / Docker image build & smoke test (push) Skipped
CI / Secret scan (gitleaks) (push) Successful in 10s
CI / Trigger Desktop Build (push) Canceled after 0s
CI / Playwright smoke (e2e) (push) Canceled after 0s
CI / Build & Quality Checks (push) Successful in 1m36s
CI / Docker image build & smoke test (push) Skipped
CI / Secret scan (gitleaks) (push) Successful in 10s
CI / Trigger Desktop Build (push) Canceled after 0s
CI / Playwright smoke (e2e) (push) Canceled after 0s
Many distinct reactions used to wrap into a tall stack (16 reactions = 4 rows at phone width). Now only the first row is shown, ending in a "+N" chip; tapping it expands inline and a "less" chip collapses again. Expanded state is remembered per message for the session. Nothing changes when the reactions already fit on one row. Overflowing chips stay in the DOM (invisible, aria-hidden, untabbable, clipped by max-height) so the container keeps its natural width — which keeps shrink-to-fit bubble layout stable — and each chip stays measurable. utils/reactionOverflow.ts holds the unit-tested fit calculation; a ResizeObserver re-fits on width changes. "+N" is forced LTR for RTL UIs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* [Gitea #138] How many reaction chips fit on one row next to a "+N" chip.
|
||||
*
|
||||
* Returns `undefined` when every chip fits on the first row (nothing to
|
||||
* collapse). Otherwise returns the number of leading chips to show; the
|
||||
* caller renders a "+N" chip after them. Always at least 1 chip.
|
||||
*/
|
||||
export function fitReactionRow(
|
||||
chipWidths: number[],
|
||||
moreChipWidth: number,
|
||||
gap: number,
|
||||
rowWidth: number,
|
||||
): number | undefined {
|
||||
const rowLength = (count: number, extra: number) => {
|
||||
let total = extra;
|
||||
for (let i = 0; i < count; i += 1) total += chipWidths[i] + (i > 0 || extra > 0 ? gap : 0);
|
||||
return total;
|
||||
};
|
||||
if (rowLength(chipWidths.length, 0) <= rowWidth) return undefined;
|
||||
let count = chipWidths.length - 1;
|
||||
while (count > 1 && rowLength(count, 0) + gap + moreChipWidth > rowWidth) count -= 1;
|
||||
return count;
|
||||
}
|
||||
|
||||
/** Session-only memory of which messages have their reactions expanded. */
|
||||
export const expandedReactionMessages = new Set<string>();
|
||||
Reference in New Issue
Block a user