feat(sidebar): show compact timestamp in recent activity rows
The sidebar's recent activity list (SidebarActivitySections) rendered its session rows without an inline timestamp on web/desktop — the compact relative label only appeared in the hover tooltip and on touch runtimes. Render the existing i18n-backed formatSessionCompactDateLabel inline in the recent rows' metadata slot, alongside the goal/branch glyphs, for web/desktop too. It keeps the same hover-fade as the other metadata, so the hover-revealed row actions never overlap it, and the full date stays available in the row tooltip. No new strings: the label reuses common.relative.* keys. Fixes #2560
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
import { describe, expect, test } from 'bun:test';
|
||||
import { readFileSync } from 'node:fs';
|
||||
|
||||
const source = readFileSync(new URL('./SessionNodeItem.tsx', import.meta.url), 'utf8');
|
||||
|
||||
describe('SessionNodeItem recent-activity timestamp', () => {
|
||||
test('the recent activity rows render the compact timestamp in the inline metadata slot', () => {
|
||||
// The right-slot guard must open for recent rows even when no activity,
|
||||
// goal glyph, or branch marker is present.
|
||||
const guard = source.indexOf("showActivityDuration || sessionGoalGlyph || showInlineBranchMarker || renderContext === 'recent'");
|
||||
expect(guard).toBeGreaterThan(-1);
|
||||
// The recent-only block sits inside that slot…
|
||||
const guardOpen = source.indexOf("{renderContext === 'recent' ? (", guard);
|
||||
expect(guardOpen).toBeGreaterThan(guard);
|
||||
// …and the compact label rendered there is the first one after it.
|
||||
const label = source.indexOf('{sessionCompactUpdatedLabel}', guardOpen);
|
||||
expect(label).toBeGreaterThan(guardOpen);
|
||||
// The only later occurrence is the pre-existing row tooltip (which shows
|
||||
// the full date), not a second inline render.
|
||||
const tooltipLabel = source.indexOf('{sessionCompactUpdatedLabel}', label + 1);
|
||||
expect(tooltipLabel).toBeGreaterThan(label);
|
||||
expect(source.indexOf('title={sessionUpdatedLabel}', tooltipLabel - 80)).toBeGreaterThan(-1);
|
||||
});
|
||||
|
||||
test('the timestamp shares the hover-fade of the other metadata so revealed actions never overlap it', () => {
|
||||
const guard = source.indexOf("showActivityDuration || sessionGoalGlyph || showInlineBranchMarker || renderContext === 'recent'");
|
||||
// The slot content fades out while the row is hovered (hideOnHoverClass)
|
||||
// and while the row menu is open — the same span that now carries the
|
||||
// recent timestamp.
|
||||
const hideOnHover = source.indexOf('hideOnHoverClass', guard);
|
||||
expect(hideOnHover).toBeGreaterThan(guard);
|
||||
expect(hideOnHover).toBeLessThan(source.indexOf("{renderContext === 'recent' ? (", guard));
|
||||
});
|
||||
|
||||
test('the compact label uses the existing i18n-backed relative time helper', () => {
|
||||
// formatSessionCompactDateLabel (already used by touch runtimes and the
|
||||
// row tooltip) is the source of the label — no new formatting code.
|
||||
expect(source.indexOf('const sessionCompactUpdatedLabel = formatSessionCompactDateLabel(sessionTimestamp);')).toBeGreaterThan(-1);
|
||||
expect(source.indexOf('{sessionCompactUpdatedLabel}')).toBeGreaterThan(-1);
|
||||
});
|
||||
});
|
||||
@@ -1257,7 +1257,7 @@ function SessionNodeItemComponent(props: Props): React.ReactNode {
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
) : (showActivityDuration || sessionGoalGlyph || showInlineBranchMarker) ? (
|
||||
) : (showActivityDuration || sessionGoalGlyph || showInlineBranchMarker || renderContext === 'recent') ? (
|
||||
<div className="relative ml-1 flex h-4 flex-shrink-0 items-center justify-end">
|
||||
<span className={cn(
|
||||
'inline-flex items-center gap-1 whitespace-nowrap text-right transition-opacity duration-150',
|
||||
@@ -1281,6 +1281,18 @@ function SessionNodeItemComponent(props: Props): React.ReactNode {
|
||||
style={prIconColor ? { color: prIconColor } : undefined}
|
||||
/>
|
||||
) : null}
|
||||
{/* The recent activity list shows its compact
|
||||
timestamp inline (touch runtimes already get
|
||||
it through the alwaysShowActions branch);
|
||||
it shares the slot with the goal/branch
|
||||
metadata and hides on hover exactly like
|
||||
them, so the revealed row actions never
|
||||
overlap it. */}
|
||||
{renderContext === 'recent' ? (
|
||||
<span className="flex-shrink-0 text-[0.72rem] leading-none text-muted-foreground/75 tabular-nums">
|
||||
{sessionCompactUpdatedLabel}
|
||||
</span>
|
||||
) : null}
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user