mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-23 10:08:38 +02:00
#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>
73 lines
2.9 KiB
TypeScript
73 lines
2.9 KiB
TypeScript
"use client";
|
|
|
|
import { useQuery } from "@tanstack/react-query";
|
|
import { issueListOptions, issueDetailOptions } from "@multica/core/issues/queries";
|
|
import { useWorkspaceId } from "@multica/core/hooks";
|
|
import { StatusIcon } from "./status-icon";
|
|
|
|
/**
|
|
* Compact, presentation-only representation of an issue —
|
|
* `<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
|
|
* interactive shell they need (AppLink for markdown mentions, an <a> with
|
|
* cmd-click support inside the editor's NodeView, a plain span next to a
|
|
* dismiss button in chat's context anchor card, …).
|
|
*
|
|
* Size budget: must fit within a 14px line-box when used inline — hence
|
|
* `py-0.5` + text-xs (see MentionView docstring for the math).
|
|
*/
|
|
export interface IssueChipProps {
|
|
issueId: string;
|
|
/** Shown when the issue can't be resolved (deleted, other workspace, …). */
|
|
fallbackLabel?: string;
|
|
/** Extra classes — callers layer interaction hints here
|
|
* (e.g. `hover:bg-accent cursor-pointer` for navigable variants). */
|
|
className?: string;
|
|
}
|
|
|
|
const BASE_CLASS =
|
|
"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();
|
|
const { data: issues = [] } = useQuery(issueListOptions(wsId));
|
|
const listIssue = issues.find((i) => i.id === issueId);
|
|
|
|
// Fallback fetch for issues outside the first page of the list (e.g. Done).
|
|
const { data: detailIssue } = useQuery({
|
|
...issueDetailOptions(wsId, issueId),
|
|
enabled: !listIssue,
|
|
});
|
|
|
|
const issue = listIssue ?? detailIssue;
|
|
const cls = className ? `${BASE_CLASS} ${className}` : BASE_CLASS;
|
|
|
|
if (!issue) {
|
|
return (
|
|
<span className={cls}>
|
|
<span className="min-w-0 truncate font-medium text-muted-foreground">
|
|
{fallbackLabel ?? issueId.slice(0, 8)}
|
|
</span>
|
|
</span>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<span className={cls}>
|
|
<StatusIcon status={issue.status} className="h-3.5 w-3.5 shrink-0" />
|
|
<span className="font-medium text-muted-foreground shrink-0">
|
|
{issue.identifier}
|
|
</span>
|
|
<span className="min-w-0 truncate text-foreground">{issue.title}</span>
|
|
</span>
|
|
);
|
|
}
|