fix(channels): collapse overflowing tag suggestions into a "+N" pill

With 2+ suggestions the narrow tags cell clipped the second ghost chip
mid-word right next to the edit "+", reading as the icon covering it. Route
the ghost chips through the same fit machinery the attached chips use: a
dedicated SuggestedChipsLane fits what the cell holds and collapses the rest
into a "+N" pill whose hover popover still one-tap accepts / dismisses each.

The lane is attached-XOR-ghost (suggestions are untagged-only, and accepting
one now drops the whole channel from the suggestion cache), so each lane owns
the full cell width instead of clipping the other.
This commit is contained in:
2026-08-26 02:39:00 +02:00
parent 549aae67cc
commit 17f8885fb1
3 changed files with 183 additions and 68 deletions
+6 -5
View File
@@ -205,14 +205,15 @@ export default function Channels() {
const dismissSuggestion = (cid: string, tagId: number) =>
setDismissed((prev) => new Set(prev).add(sKey(cid, tagId)));
const acceptSuggestion = (cid: string, tagId: number) => {
// Optimistically drop it from the suggestions cache so the ghost chip vanishes at once; toggleTag
// attaches the real tag (its onSuccess re-invalidates suggestions + the channel detail).
// Optimistically drop the WHOLE channel from the suggestions cache: attaching any tag makes it
// "tagged", which the server excludes from suggestions entirely — so its other ghost chips would
// vanish on the next refetch anyway. Removing them now keeps the ghost lane and the attached lane
// mutually exclusive (no transient of both showing). toggleTag attaches the real tag; its onSuccess
// re-invalidates suggestions + the channel detail.
qc.setQueryData<TagSuggestions>(qk.tagSuggestions(), (old) => {
if (!old?.[cid]) return old;
const rest = old[cid].filter((s) => s.tag_id !== tagId);
const next = { ...old };
if (rest.length) next[cid] = rest;
else delete next[cid];
delete next[cid];
return next;
});
toggleTag(cid, tagId, false);