mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 04:18:05 +00:00
fix(ui): make trace chevron actually collapse auto-expanded traces
The first click on a trace's chevron did nothing visible when the trace's child was the currently-selected entry. Root cause: `toggle` only checked the `expanded` set; auto-expand kept re-injecting the requestId so the row stayed open even after the user added it to `expanded` (and oscillating subsequent clicks). Replace the single `expanded` set with a tristate driven by two sets — `userExpanded` (explicitly opened) and `userCollapsed` (explicitly closed). Auto-expand only fires when the id is in neither, so a click on an auto-expanded chevron now writes the collapse intent to `userCollapsed` and the row collapses on the first click. Refs #1138, #1151
This commit is contained in:
@@ -40,30 +40,72 @@ export function LogsEntryList({
|
||||
density = 'cozy',
|
||||
}: LogsEntryListProps) {
|
||||
const items = useMemo(() => deriveTraceGroups(entries), [entries]);
|
||||
const [expanded, setExpanded] = useState<Set<string>>(new Set());
|
||||
// Two-set tristate: `userExpanded` = explicitly opened, `userCollapsed`
|
||||
// = explicitly closed. Auto-expand (when selection lives inside a trace)
|
||||
// only fires when the id is in neither set, so a user click on an
|
||||
// auto-expanded chevron actually collapses — previously it added to
|
||||
// `expanded` while auto-expand kept showing it, so no visible change.
|
||||
const [userExpanded, setUserExpanded] = useState<Set<string>>(new Set());
|
||||
const [userCollapsed, setUserCollapsed] = useState<Set<string>>(new Set());
|
||||
|
||||
const toggle = useCallback((requestId: string) => {
|
||||
setExpanded((prev) => {
|
||||
const next = new Set(prev);
|
||||
if (next.has(requestId)) next.delete(requestId);
|
||||
else next.add(requestId);
|
||||
return next;
|
||||
});
|
||||
}, []);
|
||||
|
||||
// Auto-expand the trace whose child is currently selected.
|
||||
const effectiveExpanded = useMemo(() => {
|
||||
if (!selectedEntryId) return expanded;
|
||||
// Compute the auto-expand id (if any) — derived inside toggle and the
|
||||
// effective set so a single source of truth drives both render and
|
||||
// click logic.
|
||||
const autoExpandedId = useMemo(() => {
|
||||
if (!selectedEntryId) return null;
|
||||
const owning = items.find(
|
||||
(it) => it.kind === 'trace' && it.children.some((c) => c.id === selectedEntryId)
|
||||
);
|
||||
if (owning && owning.kind === 'trace' && !expanded.has(owning.requestId)) {
|
||||
const next = new Set(expanded);
|
||||
next.add(owning.requestId);
|
||||
return next;
|
||||
return owning && owning.kind === 'trace' ? owning.requestId : null;
|
||||
}, [items, selectedEntryId]);
|
||||
|
||||
const toggle = useCallback(
|
||||
(requestId: string) => {
|
||||
const isAutoExpanded = autoExpandedId === requestId;
|
||||
const isExplicitlyOpen = userExpanded.has(requestId);
|
||||
const isExplicitlyClosed = userCollapsed.has(requestId);
|
||||
const isCurrentlyOpen = isExplicitlyOpen || (isAutoExpanded && !isExplicitlyClosed);
|
||||
|
||||
if (isCurrentlyOpen) {
|
||||
// Close: clear user-open, mark user-closed (beats auto-expand).
|
||||
setUserExpanded((prev) => {
|
||||
if (!prev.has(requestId)) return prev;
|
||||
const next = new Set(prev);
|
||||
next.delete(requestId);
|
||||
return next;
|
||||
});
|
||||
setUserCollapsed((prev) => {
|
||||
if (prev.has(requestId)) return prev;
|
||||
const next = new Set(prev);
|
||||
next.add(requestId);
|
||||
return next;
|
||||
});
|
||||
} else {
|
||||
// Open: clear user-closed, mark user-open.
|
||||
setUserExpanded((prev) => {
|
||||
if (prev.has(requestId)) return prev;
|
||||
const next = new Set(prev);
|
||||
next.add(requestId);
|
||||
return next;
|
||||
});
|
||||
setUserCollapsed((prev) => {
|
||||
if (!prev.has(requestId)) return prev;
|
||||
const next = new Set(prev);
|
||||
next.delete(requestId);
|
||||
return next;
|
||||
});
|
||||
}
|
||||
},
|
||||
[autoExpandedId, userExpanded, userCollapsed]
|
||||
);
|
||||
|
||||
const effectiveExpanded = useMemo(() => {
|
||||
const result = new Set(userExpanded);
|
||||
if (autoExpandedId && !userCollapsed.has(autoExpandedId)) {
|
||||
result.add(autoExpandedId);
|
||||
}
|
||||
return expanded;
|
||||
}, [expanded, items, selectedEntryId]);
|
||||
return result;
|
||||
}, [userExpanded, userCollapsed, autoExpandedId]);
|
||||
|
||||
const renderItem = useCallback(
|
||||
(_index: number, item: DerivedItem) => {
|
||||
|
||||
Reference in New Issue
Block a user