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
27 lines
985 B
TypeScript
27 lines
985 B
TypeScript
/**
|
|
* [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>();
|