authorgravatar for gr261212@gmail.comG-R3 <gr261212@gmail.com> 2026-09-02 05:15:02-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-02 09:15:02+00:00
log70cd258d8aac43ea57494527b00bf36de3efa6c0
treed8430759077384a429c6a53fafa5e82ed7d4b055
parentf14f41b894448298a86865c9114e6700245356e7
signature Signed by PGP key B5690EEEBB952194

fix(web): prevent two-digit list markers from being clipped (#9101)

Co-authored-by: shivam <91240327+shivamhwp@users.noreply.github.com>

3 files changed, 13 insertions(+), 16 deletions(-)

apps/web/src/components/ChatMarkdown.test.tsx+5-5
......@@ -360,13 +360,13 @@ describe("orderedListGutterStyle", () => {
360360 expect(orderedListGutterStyle(9, undefined)).toBeUndefined();
361361 });
362362
363 it("leaves the default gutter alone for two-digit lists", () => {
364 expect(orderedListGutterStyle(99, undefined)).toBeUndefined();
363 it("widens the gutter for two-digit lists", () => {
364 expect(orderedListGutterStyle(99, undefined)).toEqual({ "--list-gutter": "3ch" });
365365 });
366366
367 it("leaves the default gutter alone for a two-digit list that starts above 1", () => {
367 it("widens the gutter for a two-digit list that starts above 1", () => {
368368 // start=50 + 49 items => last marker is "98", still two digits.
369 expect(orderedListGutterStyle(49, 50)).toBeUndefined();
369 expect(orderedListGutterStyle(49, 50)).toEqual({ "--list-gutter": "3ch" });
370370 });
371371
372372 it("widens the gutter once the last marker reaches three digits", () => {
......@@ -387,7 +387,7 @@ describe("orderedListGutterStyle", () => {
387387 it("uses the widest marker and includes a negative start's minus sign", () => {
388388 expect(orderedListGutterStyle(1001, -1000)).toEqual({ "--list-gutter": "6ch" });
389389 expect(orderedListGutterStyle(3, -15)).toEqual({ "--list-gutter": "4ch" });
390 expect(orderedListGutterStyle(3, -5)).toBeUndefined();
390 expect(orderedListGutterStyle(3, -5)).toEqual({ "--list-gutter": "3ch" });
391391 });
392392
393393 it("treats a missing/zero item count as a single item", () => {
apps/web/src/components/ChatMarkdown.tsx+5-8
......@@ -328,13 +328,10 @@ function findTaskListMarkerOffset(markdown: string, listItemStart: number): numb
328328}
329329
330330/**
331 * The default `1.25rem` marker gutter (`.chat-markdown ol`) fits markers up to
332 * two characters wide. Once a marker reaches three characters (item 100+),
333 * `list-style-position: outside` paints it wider than that gutter and clips
334 * the leading character against the item's own overflow. Rather than widening
335 * the gutter for every list, only lists whose widest marker is 3+ characters
336 * get a wider `--list-gutter`. The width includes a negative marker's minus
337 * sign.
331 * The default `1.25rem` marker gutter (`.chat-markdown ol`) fits one-character
332 * markers. Wider markers can extend past it and get clipped by a collapsed
333 * message's overflow. Widen the gutter to fit the widest marker, including a
334 * negative marker's minus sign.
338335 */
339336export function orderedListGutterStyle(
340337 itemCount: number,
......@@ -344,7 +341,7 @@ export function orderedListGutterStyle(
344341 const firstNumber = Number.isNaN(parsedStart) ? 1 : parsedStart;
345342 const lastNumber = firstNumber + Math.max(itemCount - 1, 0);
346343 const markerWidth = Math.max(String(firstNumber).length, String(lastNumber).length);
347 if (markerWidth <= 2) return undefined;
344 if (markerWidth <= 1) return undefined;
348345 return { "--list-gutter": `${markerWidth + 1}ch` };
349346}
350347
apps/web/src/index.css+3-3
......@@ -1643,8 +1643,8 @@ code {
16431643}
16441644
16451645.chat-markdown ul {
1646 /* Reset for nested uls under a widened ol — --list-gutter is an inherited
1647 custom property, so without this a task-list under a 3+ digit ordered
1646 /* Reset for nested uls under a widened ol. --list-gutter is an inherited
1647 custom property, so without this a task-list under a multi-digit ordered
16481648 list would inherit the outer gutter instead of its own default. */
16491649 --list-gutter: 1.25rem;
16501650 padding-left: 1.25rem;
......@@ -1653,7 +1653,7 @@ code {
16531653
16541654/* --list-gutter defaults to the same 1.25rem as .chat-markdown ul, but
16551655 ChatMarkdown's `ol` renderer widens it (via inline style) for lists whose
1656 widest marker is 3+ characters, so item 100+ isn't clipped by list-style-position:
1656 widest marker has multiple characters so it isn't clipped by list-style-position:
16571657 outside painting the marker past the padding box. Reset it here too so a
16581658 nested ol without its own widened marker doesn't inherit the outer one. */
16591659.chat-markdown ol {