Compare commits

...

1 Commits

Author SHA1 Message Date
Naiyuan Qing
102ce725da fix(editor): cap issue mention chip at container width, no clickable gap
#4288 swapped the chip cap from a fixed `max-w-72` to `max-w-[min(18rem,100%)]`.
A percentage max-width on a flex item is dropped while its flex-container wrapper
(`<a class="inline-flex">`) computes its own max-content size, so the wrapper
ballooned to the untruncated title width while the chip truncated to the cap —
leaving an empty, clickable strip after the visible chip.

Fix it as standard atomic-inline behavior instead of a fixed magic cap:
- IssueChip caps at `max-w-full` with the title truncating to an ellipsis, so it
  wraps to the next line as a unit and only truncates once a whole line can't
  hold it.
- Drop `inline-flex` from the editor NodeView `<a>` (issue + project) and the
  markdown AppLink so the chip's only wrapper is a plain inline box with a
  definite (line-based) percentage basis — no second flex container to balloon.

ProjectChip uses a definite `max-w-72`, so it never hit the gap; left as-is.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 14:00:29 +08:00
4 changed files with 12 additions and 6 deletions

View File

@@ -69,7 +69,7 @@ function ProjectMention({
};
return (
<a href={projectPath} onClick={handleClick} className="project-mention inline-flex">
<a href={projectPath} onClick={handleClick} className="project-mention">
<ProjectChip
projectId={projectId}
fallbackLabel={fallbackLabel}
@@ -101,7 +101,7 @@ function IssueMention({
};
return (
<a href={issuePath} onClick={handleClick} className="issue-mention inline-flex">
<a href={issuePath} onClick={handleClick} className="issue-mention">
<IssueChip
issueId={issueId}
fallbackLabel={fallbackLabel}

View File

@@ -49,7 +49,7 @@ describe("IssueChip", () => {
render(<IssueChip issueId="issue-1" />);
const chip = screen.getByText("MUL-3405").closest(".issue-mention");
expect(chip).toHaveClass("min-w-0", "max-w-[min(18rem,100%)]");
expect(chip).toHaveClass("min-w-0", "max-w-full");
expect(screen.getByText("A very long issue title that should stay inside a narrow chat bubble"))
.toHaveClass("min-w-0", "truncate");
});

View File

@@ -7,7 +7,13 @@ import { StatusIcon } from "./status-icon";
/**
* Compact, presentation-only representation of an issue —
* `<StatusIcon> <identifier> <title>`, bordered, capped at 18rem or parent width.
* `<StatusIcon> <identifier> <title>`, bordered, capped at the container width
* (`max-w-full`) with the title truncating to an ellipsis. As an atomic inline
* box it wraps to the next line as a unit when it doesn't fit at the current
* position; the ellipsis only kicks in once a whole line can't hold it. The cap
* lives here (single source of truth) — wrappers must NOT add their own flex
* container around it, or a percentage cap gets dropped during the wrapper's
* intrinsic sizing and the clickable box diverges from the truncated chip.
*
* This is the single source of truth for the "issue-mention card" look.
* It is intentionally **not** a link or button: callers wrap it in whatever
@@ -28,7 +34,7 @@ export interface IssueChipProps {
}
const BASE_CLASS =
"issue-mention inline-flex min-w-0 max-w-[min(18rem,100%)] items-center gap-1.5 rounded-md border mx-0.5 px-2 py-0.5 text-xs";
"issue-mention inline-flex min-w-0 max-w-full items-center gap-1.5 rounded-md border mx-0.5 px-2 py-0.5 text-xs";
export function IssueChip({ issueId, fallbackLabel, className }: IssueChipProps) {
const wsId = useWorkspaceId();

View File

@@ -18,7 +18,7 @@ interface IssueMentionCardProps {
export function IssueMentionCard({ issueId, fallbackLabel }: IssueMentionCardProps) {
const p = useWorkspacePaths();
return (
<AppLink href={p.issueDetail(issueId)} className="issue-mention not-prose inline-flex max-w-full align-middle">
<AppLink href={p.issueDetail(issueId)} className="issue-mention not-prose align-middle">
<IssueChip
issueId={issueId}
fallbackLabel={fallbackLabel}