Skip to content

Commit fbe98b9

Browse files
committed
style: add left emerald accent bar to active chat entry in sidebar
1 parent 2da7ccf commit fbe98b9

File tree

3 files changed

+51
-5
lines changed

3 files changed

+51
-5
lines changed

apps/desktop/src/app/shell/AppSidebar.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,8 @@ function SessionItem({
703703
onSelect?.(session.id);
704704
}}
705705
className={cn(
706-
isActive && "border-l-2 border-primary bg-primary/[0.08] font-medium",
706+
"border-l-2",
707+
isActive ? "border-primary bg-primary/[0.08] font-medium" : "border-transparent",
707708
deEmphasized && !isActive && "opacity-50",
708709
unnamed && !isActive && "text-sidebar-foreground/50",
709710
)}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { describe, expect, it } from "vitest";
2+
import { readFileSync } from "node:fs";
3+
import { resolve } from "node:path";
4+
5+
const sidebarSrc = readFileSync(
6+
resolve(__dirname, "../../apps/desktop/src/app/shell/AppSidebar.tsx"),
7+
"utf-8",
8+
);
9+
10+
// Extract the SessionItem function body for scoped assertions
11+
const sessionItemStart = sidebarSrc.indexOf("function SessionItem");
12+
const sessionItemBody = sidebarSrc.slice(sessionItemStart);
13+
14+
describe("Chat sidebar – active accent bar", () => {
15+
// AC1: Active chat entry shows a left emerald accent bar
16+
it("applies border-l-2 with primary color to active chat entry", () => {
17+
expect(sessionItemBody).toContain("border-l-2");
18+
expect(sessionItemBody).toContain("border-primary");
19+
});
20+
21+
// AC2: Inactive entries maintain consistent left alignment (transparent border)
22+
it("applies transparent left border to inactive entries for consistent alignment", () => {
23+
expect(sessionItemBody).toContain("border-transparent");
24+
});
25+
26+
// AC3: All entries have a consistent 2px left border (no layout shift)
27+
it("all entries have border-l-2 regardless of active state", () => {
28+
// border-l-2 should be applied unconditionally (not inside isActive conditional)
29+
// Find the className area of the non-editing return path
30+
const normalReturn = sessionItemBody.indexOf("SidebarMenuButton");
31+
const classNameArea = sessionItemBody.slice(normalReturn, normalReturn + 500);
32+
// border-l-2 should appear as a base class, not gated by isActive
33+
expect(classNameArea).toMatch(/["'`]border-l-2/);
34+
});
35+
36+
// AC4: Active entry uses primary border color and background tint
37+
it("active entry has background tint with emerald accent", () => {
38+
expect(sessionItemBody).toContain("bg-primary/[0.08]");
39+
});
40+
41+
// AC5: Active entry has font-medium for text emphasis
42+
it("active entry has font-medium weight", () => {
43+
expect(sessionItemBody).toContain("font-medium");
44+
});
45+
});

test/ui/sidebar-chat-hierarchy.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ describe("Chat sidebar visual hierarchy", () => {
2323
expect(sidebarSrc).toMatch(/tracking-\[0\.1em\]/);
2424
});
2525

26-
// AC2: Active conversation has a clear visual indicator (teal accent)
27-
it("active conversation has a teal left border indicator", () => {
26+
// AC2: Active conversation has a clear visual indicator (emerald accent)
27+
it("active conversation has a left border indicator with primary color", () => {
2828
expect(sidebarSrc).toMatch(/border-l.*primary|border-primary/);
29-
// The active state should reference isActive for the teal border
30-
expect(sidebarSrc).toMatch(/isActive.*border-l|border-l.*isActive/);
29+
// The active state controls the border color (primary vs transparent)
30+
expect(sidebarSrc).toMatch(/isActive.*border-primary/);
3131
});
3232

3333
// AC3: Message counts as badges (not inline parenthetical)

0 commit comments

Comments
 (0)