From 5c918af3d5a30b4ab594d630027c5d7f777f0a1a Mon Sep 17 00:00:00 2001
From: Matthew Feroz <136640686+MatthewFeroz@users.noreply.github.com>
Date: Mon, 5 Oct 2026 17:18:27 -0700
Subject: [PATCH] feat(clients): pinned threads stand out in the thread list
---
...rated-uniwind-default-theme-variables.json | 8 ++++
apps/mobile/generated-uniwind-themes.css | 48 +++++++++++++++++++
.../features/threads/thread-list-v2-items.tsx | 9 +++-
.../thread-list-v2-row-appearance.android.ts | 7 +++
.../threads/thread-list-v2-row-appearance.ts | 9 ++++
.../src/lib/materialYouTheme.android.ts | 5 ++
apps/mobile/src/lib/materialYouTheme.test.ts | 13 +++++
apps/mobile/src/lib/mobileTheme.ts | 12 +++++
apps/web/src/components/Sidebar.tsx | 17 ++++---
apps/web/src/index.css | 5 ++
10 files changed, 125 insertions(+), 8 deletions(-)
diff --git a/apps/mobile/generated-uniwind-default-theme-variables.json b/apps/mobile/generated-uniwind-default-theme-variables.json
index 961a0df24cd4..3c34aa7e0dd6 100644
--- a/apps/mobile/generated-uniwind-default-theme-variables.json
+++ b/apps/mobile/generated-uniwind-default-theme-variables.json
@@ -12,6 +12,8 @@
"--color-thread-selected-foreground": "#27272a",
"--color-thread-selected-foreground-muted": "#71717b",
"--color-thread-hover": "#fcfcfc",
+ "--color-thread-pin": "#1b4ed8",
+ "--color-thread-pin-outline": "rgba(27, 78, 216, 0.2)",
"--color-row-hover": "#f4f4f5",
"--color-composer-panel": "rgba(252, 252, 252, 0.88)",
"--color-composer-surface": "rgba(244, 244, 245, 0.94)",
@@ -82,6 +84,8 @@
"--color-drawer": "#fafafa",
"--color-drawer-foreground": "#27272a",
"--color-drawer-foreground-muted": "#71717b",
+ "--color-drawer-pin": "#1b4ed8",
+ "--color-drawer-pin-outline": "rgba(27, 78, 216, 0.2)",
"--color-drawer-border": "#e4e4e7",
"--color-drawer-shadow": "rgba(0, 0, 0, 0.12)",
"--color-dot-separator": "rgba(113, 113, 123, 0.35)",
@@ -101,6 +105,8 @@
"--color-thread-selected-foreground": "#f1f3f7",
"--color-thread-selected-foreground-muted": "#a3a3a3",
"--color-thread-hover": "#131313",
+ "--color-thread-pin": "#4b7cf3",
+ "--color-thread-pin-outline": "rgba(75, 124, 243, 0.2)",
"--color-row-hover": "#141414",
"--color-composer-panel": "rgba(10, 10, 10, 0.92)",
"--color-composer-surface": "rgba(26, 27, 27, 0.9)",
@@ -171,6 +177,8 @@
"--color-drawer": "#000000",
"--color-drawer-foreground": "#f1f3f7",
"--color-drawer-foreground-muted": "#a3a3a3",
+ "--color-drawer-pin": "#4b7cf3",
+ "--color-drawer-pin-outline": "rgba(75, 124, 243, 0.2)",
"--color-drawer-border": "#141414",
"--color-drawer-shadow": "rgba(0, 0, 0, 0.32)",
"--color-dot-separator": "rgba(129, 129, 129, 0.35)",
diff --git a/apps/mobile/generated-uniwind-themes.css b/apps/mobile/generated-uniwind-themes.css
index 82e7ad85d6cf..3187e9b2e52f 100644
--- a/apps/mobile/generated-uniwind-themes.css
+++ b/apps/mobile/generated-uniwind-themes.css
@@ -14,6 +14,8 @@
--color-thread-selected-foreground: #27272a;
--color-thread-selected-foreground-muted: #71717b;
--color-thread-hover: #fcfcfc;
+ --color-thread-pin: #1b4ed8;
+ --color-thread-pin-outline: rgba(27, 78, 216, 0.2);
--color-row-hover: #f4f4f5;
--color-composer-panel: rgba(252, 252, 252, 0.88);
--color-composer-surface: rgba(244, 244, 245, 0.94);
@@ -84,6 +86,8 @@
--color-drawer: #fafafa;
--color-drawer-foreground: #27272a;
--color-drawer-foreground-muted: #71717b;
+ --color-drawer-pin: #1b4ed8;
+ --color-drawer-pin-outline: rgba(27, 78, 216, 0.2);
--color-drawer-border: #e4e4e7;
--color-drawer-shadow: rgba(0, 0, 0, 0.12);
--color-dot-separator: rgba(113, 113, 123, 0.35);
@@ -173,6 +177,8 @@
--color-thread-selected-foreground: #f1f3f7;
--color-thread-selected-foreground-muted: #a3a3a3;
--color-thread-hover: #131313;
+ --color-thread-pin: #4b7cf3;
+ --color-thread-pin-outline: rgba(75, 124, 243, 0.2);
--color-row-hover: #141414;
--color-composer-panel: rgba(10, 10, 10, 0.92);
--color-composer-surface: rgba(26, 27, 27, 0.9);
@@ -243,6 +249,8 @@
--color-drawer: #000000;
--color-drawer-foreground: #f1f3f7;
--color-drawer-foreground-muted: #a3a3a3;
+ --color-drawer-pin: #4b7cf3;
+ --color-drawer-pin-outline: rgba(75, 124, 243, 0.2);
--color-drawer-border: #141414;
--color-drawer-shadow: rgba(0, 0, 0, 0.32);
--color-dot-separator: rgba(129, 129, 129, 0.35);
@@ -332,6 +340,8 @@
--color-thread-selected-foreground: #454554;
--color-thread-selected-foreground-muted: #ac1668;
--color-thread-hover: #f8f8f7;
+ --color-thread-pin: #b11f60;
+ --color-thread-pin-outline: rgba(177, 31, 96, 0.2);
--color-row-hover: #eccfe3;
--color-composer-panel: rgba(253, 247, 253, 0.88);
--color-composer-surface: rgba(250, 243, 251, 0.94);
@@ -402,6 +412,8 @@
--color-drawer: #f2e1f4;
--color-drawer-foreground: #454554;
--color-drawer-foreground-muted: #ac1668;
+ --color-drawer-pin: #c2236a;
+ --color-drawer-pin-outline: rgba(194, 35, 106, 0.2);
--color-drawer-border: #eceae9;
--color-drawer-shadow: rgba(0, 0, 0, 0.12);
--color-dot-separator: rgba(172, 22, 104, 0.35);
@@ -491,6 +503,8 @@
--color-thread-selected-foreground: #f4f4f5;
--color-thread-selected-foreground-muted: #e7d0dd;
--color-thread-hover: #261922;
+ --color-thread-pin: #eb88b4;
+ --color-thread-pin-outline: rgba(235, 136, 180, 0.2);
--color-row-hover: #463753;
--color-composer-panel: rgba(31, 26, 36, 0.92);
--color-composer-surface: rgba(41, 35, 45, 0.9);
@@ -561,6 +575,8 @@
--color-drawer: #171018;
--color-drawer-foreground: #f4f4f5;
--color-drawer-foreground-muted: #e7d0dd;
+ --color-drawer-pin: #e14c8e;
+ --color-drawer-pin-outline: rgba(225, 76, 142, 0.2);
--color-drawer-border: #322028;
--color-drawer-shadow: rgba(0, 0, 0, 0.32);
--color-dot-separator: rgba(231, 208, 221, 0.35);
@@ -650,6 +666,8 @@
--color-thread-selected-foreground: #241523;
--color-thread-selected-foreground-muted: #5d585e;
--color-thread-hover: #cae0d5;
+ --color-thread-pin: #166642;
+ --color-thread-pin-outline: rgba(22, 102, 66, 0.2);
--color-row-hover: #d5e6dd;
--color-composer-panel: rgba(243, 247, 244, 0.88);
--color-composer-surface: rgba(243, 247, 244, 0.94);
@@ -720,6 +738,8 @@
--color-drawer: #e2ede7;
--color-drawer-foreground: #241523;
--color-drawer-foreground-muted: #645f64;
+ --color-drawer-pin: #166642;
+ --color-drawer-pin-outline: rgba(22, 102, 66, 0.2);
--color-drawer-border: #cbd3d0;
--color-drawer-shadow: rgba(0, 0, 0, 0.12);
--color-dot-separator: rgba(116, 108, 115, 0.35);
@@ -809,6 +829,8 @@
--color-thread-selected-foreground: #fffaff;
--color-thread-selected-foreground-muted: #bbc0bf;
--color-thread-hover: #2a4938;
+ --color-thread-pin: #79dba5;
+ --color-thread-pin-outline: rgba(121, 219, 165, 0.2);
--color-row-hover: #325c46;
--color-composer-panel: rgba(27, 40, 33, 0.92);
--color-composer-surface: rgba(27, 40, 33, 0.9);
@@ -879,6 +901,8 @@
--color-drawer: #21362b;
--color-drawer-foreground: #fffaff;
--color-drawer-foreground-muted: #aab0af;
+ --color-drawer-pin: #69d69a;
+ --color-drawer-pin-outline: rgba(105, 214, 154, 0.2);
--color-drawer-border: #6f7a75;
--color-drawer-shadow: rgba(0, 0, 0, 0.32);
--color-dot-separator: rgba(145, 149, 149, 0.35);
@@ -968,6 +992,8 @@
--color-thread-selected-foreground: #241523;
--color-thread-selected-foreground-muted: #5e5862;
--color-thread-hover: #cdddea;
+ --color-thread-pin: #1f5d90;
+ --color-thread-pin-outline: rgba(31, 93, 144, 0.2);
--color-row-hover: #d8e4ee;
--color-composer-panel: rgba(245, 247, 248, 0.88);
--color-composer-surface: rgba(245, 247, 248, 0.94);
@@ -1038,6 +1064,8 @@
--color-drawer: #e4ecf2;
--color-drawer-foreground: #241523;
--color-drawer-foreground-muted: #655e69;
+ --color-drawer-pin: #1f5d90;
+ --color-drawer-pin-outline: rgba(31, 93, 144, 0.2);
--color-drawer-border: #cdd2d9;
--color-drawer-shadow: rgba(0, 0, 0, 0.12);
--color-dot-separator: rgba(116, 108, 117, 0.35);
@@ -1127,6 +1155,8 @@
--color-thread-selected-foreground: #fffaff;
--color-thread-selected-foreground-muted: #b0b4ba;
--color-thread-hover: #283e50;
+ --color-thread-pin: #81c2f0;
+ --color-thread-pin-outline: rgba(129, 194, 240, 0.2);
--color-row-hover: #324e66;
--color-composer-panel: rgba(23, 33, 43, 0.92);
--color-composer-surface: rgba(23, 33, 43, 0.9);
@@ -1197,6 +1227,8 @@
--color-drawer: #1e2d3b;
--color-drawer-foreground: #fffaff;
--color-drawer-foreground-muted: #a2a5ae;
+ --color-drawer-pin: #74bbee;
+ --color-drawer-pin-outline: rgba(116, 187, 238, 0.2);
--color-drawer-border: #6d757f;
--color-drawer-shadow: rgba(0, 0, 0, 0.32);
--color-dot-separator: rgba(141, 143, 151, 0.35);
@@ -1286,6 +1318,8 @@
--color-thread-selected-foreground: #241523;
--color-thread-selected-foreground-muted: #62575d;
--color-thread-hover: #ead8cf;
+ --color-thread-pin: #8e4622;
+ --color-thread-pin-outline: rgba(142, 70, 34, 0.2);
--color-row-hover: #eee0d9;
--color-composer-panel: rgba(249, 247, 245, 0.88);
--color-composer-surface: rgba(249, 247, 245, 0.94);
@@ -1356,6 +1390,8 @@
--color-drawer: #f3eae5;
--color-drawer-foreground: #241523;
--color-drawer-foreground-muted: #6a5d64;
+ --color-drawer-pin: #8e4622;
+ --color-drawer-pin-outline: rgba(142, 70, 34, 0.2);
--color-drawer-border: #dad0ce;
--color-drawer-shadow: rgba(0, 0, 0, 0.12);
--color-dot-separator: rgba(118, 108, 116, 0.35);
@@ -1445,6 +1481,8 @@
--color-thread-selected-foreground: #fffaff;
--color-thread-selected-foreground-muted: #b9b1b0;
--color-thread-hover: #4f3528;
+ --color-thread-pin: #f2aa7c;
+ --color-thread-pin-outline: rgba(242, 170, 124, 0.2);
--color-row-hover: #644330;
--color-composer-panel: rgba(41, 30, 26, 0.92);
--color-composer-surface: rgba(41, 30, 26, 0.9);
@@ -1515,6 +1553,8 @@
--color-drawer: #39281f;
--color-drawer-foreground: #fffaff;
--color-drawer-foreground-muted: #aca2a1;
+ --color-drawer-pin: #f1a06c;
+ --color-drawer-pin-outline: rgba(241, 160, 108, 0.2);
--color-drawer-border: #7e716e;
--color-drawer-shadow: rgba(0, 0, 0, 0.32);
--color-dot-separator: rgba(150, 142, 143, 0.35);
@@ -1604,6 +1644,8 @@
--color-thread-selected-foreground: #241523;
--color-thread-selected-foreground-muted: #605662;
--color-thread-hover: #ded8ed;
+ --color-thread-pin: #6449a2;
+ --color-thread-pin-outline: rgba(100, 73, 162, 0.2);
--color-row-hover: #e5e0f0;
--color-composer-panel: rgba(248, 247, 249, 0.88);
--color-composer-surface: rgba(248, 247, 249, 0.94);
@@ -1674,6 +1716,8 @@
--color-drawer: #edeaf4;
--color-drawer-foreground: #241523;
--color-drawer-foreground-muted: #685d6a;
+ --color-drawer-pin: #6449a2;
+ --color-drawer-pin-outline: rgba(100, 73, 162, 0.2);
--color-drawer-border: #d5d0db;
--color-drawer-shadow: rgba(0, 0, 0, 0.12);
--color-dot-separator: rgba(118, 108, 118, 0.35);
@@ -1763,6 +1807,8 @@
--color-thread-selected-foreground: #fffaff;
--color-thread-selected-foreground-muted: #a6a2ae;
--color-thread-hover: #352c4f;
+ --color-thread-pin: #b39bf5;
+ --color-thread-pin-outline: rgba(179, 155, 245, 0.2);
--color-row-hover: #433765;
--color-composer-panel: rgba(29, 25, 41, 0.92);
--color-composer-surface: rgba(29, 25, 41, 0.9);
@@ -1833,6 +1879,8 @@
--color-drawer: #272139;
--color-drawer-foreground: #fffaff;
--color-drawer-foreground-muted: #9b97a4;
+ --color-drawer-pin: #af95f4;
+ --color-drawer-pin-outline: rgba(175, 149, 244, 0.2);
--color-drawer-border: #736d7e;
--color-drawer-shadow: rgba(0, 0, 0, 0.32);
--color-dot-separator: rgba(142, 138, 149, 0.35);
diff --git a/apps/mobile/src/features/threads/thread-list-v2-items.tsx b/apps/mobile/src/features/threads/thread-list-v2-items.tsx
index 92ffbcd23f56..1345e9d74d82 100644
--- a/apps/mobile/src/features/threads/thread-list-v2-items.tsx
+++ b/apps/mobile/src/features/threads/thread-list-v2-items.tsx
@@ -952,7 +952,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: {
) : null}
@@ -1131,6 +1131,13 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: {
}}
style={rowAppearance.cardStyle}
>
+ {pinnedRow && rowAppearance.pinnedOutlineStyle ? (
+
+ ) : null}
{sidebarPane ? (
cardContent
) : (
diff --git a/apps/mobile/src/features/threads/thread-list-v2-row-appearance.android.ts b/apps/mobile/src/features/threads/thread-list-v2-row-appearance.android.ts
index 8be6b240755d..524a41b5f9fc 100644
--- a/apps/mobile/src/features/threads/thread-list-v2-row-appearance.android.ts
+++ b/apps/mobile/src/features/threads/thread-list-v2-row-appearance.android.ts
@@ -51,6 +51,13 @@ export function getThreadListV2RowAppearance(
tertiaryIconTintClassName: sidebarPane
? "accent-drawer-foreground-muted"
: "accent-foreground-tertiary",
+ pinIconTintClassName: sidebarPane ? "accent-drawer-pin" : "accent-thread-pin",
+ // Every Android row is a rounded card, so pinned rows always get the hairline.
+ pinnedOutlineStyle: {
+ borderRadius: 20,
+ borderWidth: 1,
+ borderColor: theme[sidebarPane ? "--color-drawer-pin-outline" : "--color-thread-pin-outline"],
+ } satisfies ViewStyle,
style,
cardStyle: sidebarPane ? { ...style, paddingHorizontal: 12, paddingVertical: 10 } : style,
swipeContainerStyle,
diff --git a/apps/mobile/src/features/threads/thread-list-v2-row-appearance.ts b/apps/mobile/src/features/threads/thread-list-v2-row-appearance.ts
index b73f87b86a2a..4901007eee7a 100644
--- a/apps/mobile/src/features/threads/thread-list-v2-row-appearance.ts
+++ b/apps/mobile/src/features/threads/thread-list-v2-row-appearance.ts
@@ -49,6 +49,15 @@ export function getThreadListV2RowAppearance(
tertiaryIconTintClassName: sidebarPane
? "accent-drawer-foreground-muted"
: "accent-foreground-tertiary",
+ pinIconTintClassName: sidebarPane ? "accent-drawer-pin" : "accent-thread-pin",
+ // Pinned cards get a hairline; flat native rows carry the pin by color alone.
+ pinnedOutlineStyle: sidebarPane
+ ? ({
+ borderRadius: 12,
+ borderWidth: 1,
+ borderColor: theme["--color-drawer-pin-outline"],
+ } satisfies ViewStyle)
+ : undefined,
style,
cardStyle: sidebarPane ? { ...style, paddingHorizontal: 12, paddingVertical: 10 } : undefined,
swipeContainerStyle,
diff --git a/apps/mobile/src/lib/materialYouTheme.android.ts b/apps/mobile/src/lib/materialYouTheme.android.ts
index 311518428efb..5d2a6d05573d 100644
--- a/apps/mobile/src/lib/materialYouTheme.android.ts
+++ b/apps/mobile/src/lib/materialYouTheme.android.ts
@@ -54,6 +54,11 @@ export function materialYouPaletteToMobileThemeVariables(
"--color-foreground-tertiary": withAlpha(palette.onSurfaceVariant, 0.58),
"--color-border": withAlpha(palette.outlineVariant, dark ? 0.5 : 0.65),
"--color-focus": palette.primary,
+ // Material tonal palettes keep primary legible on their own surfaces.
+ "--color-thread-pin": palette.primary,
+ "--color-thread-pin-outline": withAlpha(palette.primary, 0.2),
+ "--color-drawer-pin": palette.primary,
+ "--color-drawer-pin-outline": withAlpha(palette.primary, 0.2),
"--color-border-subtle": withAlpha(palette.outlineVariant, dark ? 0.34 : 0.46),
"--color-separator": withAlpha(palette.outlineVariant, dark ? 0.24 : 0.34),
"--color-subtle": withAlpha(palette.onSurface, 0.05),
diff --git a/apps/mobile/src/lib/materialYouTheme.test.ts b/apps/mobile/src/lib/materialYouTheme.test.ts
index d803a161ad87..8b701c3d8d81 100644
--- a/apps/mobile/src/lib/materialYouTheme.test.ts
+++ b/apps/mobile/src/lib/materialYouTheme.test.ts
@@ -59,6 +59,19 @@ describe("Material You system colors", () => {
expect(variables["--color-placeholder"]).toBe("#1C1B1F9E");
});
+ it("tints pinned thread rows with the system primary", () => {
+ const variables = materialYouPaletteToMobileThemeVariables(
+ palette,
+ "light",
+ getMobileThemeRuntimeVariables("t3-code", "light", "android"),
+ );
+
+ expect(variables["--color-thread-pin"]).toBe(palette.primary);
+ expect(variables["--color-drawer-pin"]).toBe(palette.primary);
+ expect(variables["--color-thread-pin-outline"]).toBe("#6750A433");
+ expect(variables["--color-drawer-pin-outline"]).toBe("#6750A433");
+ });
+
it("uses the Messages-style RCS tones for sent messages", () => {
const base = getMobileThemeRuntimeVariables("t3-code", "dark", "android");
const dark = materialYouPaletteToMobileThemeVariables(
diff --git a/apps/mobile/src/lib/mobileTheme.ts b/apps/mobile/src/lib/mobileTheme.ts
index 4159232fe7ab..a1c1960b3f21 100644
--- a/apps/mobile/src/lib/mobileTheme.ts
+++ b/apps/mobile/src/lib/mobileTheme.ts
@@ -243,6 +243,14 @@ export function createMobileThemeVariables(
const c = nativeColors(colors);
const groupedCard = themeColorToNativeColor(groupedCardColor);
const textSurfaces = [c.canvas, c.surface, c.surfaceRaised, c.chrome, groupedCard];
+ // Pinned thread rows: the theme's focus accent, solved for contrast on every
+ // background the row can sit on (rest, pressed, selected).
+ const threadPin = readableTextColor(c.focus, [
+ ...textSurfaces,
+ c.toolbarControlHover,
+ c.sidebarRowActive,
+ ]);
+ const drawerPin = readableTextColor(c.focus, [c.sidebar, c.sidebarRowHover, c.sidebarRowActive]);
return {
"--color-screen": c.canvas,
"--color-sheet": withAlpha(c.chrome, 0.98),
@@ -259,6 +267,8 @@ export function createMobileThemeVariables(
c.sidebarRowActive,
),
"--color-thread-hover": c.sidebarRowHover,
+ "--color-thread-pin": threadPin,
+ "--color-thread-pin-outline": themeColorWithAlpha(threadPin, 0.2),
"--color-row-hover": c.toolbarControlHover,
"--color-composer-panel": themeColorWithAlpha(c.canvas, appearance === "dark" ? 0.92 : 0.88),
"--color-composer-surface": themeColorWithAlpha(
@@ -338,6 +348,8 @@ export function createMobileThemeVariables(
c.sidebar,
c.sidebarRowHover,
]),
+ "--color-drawer-pin": drawerPin,
+ "--color-drawer-pin-outline": themeColorWithAlpha(drawerPin, 0.2),
"--color-drawer-border": c.sidebarBorder,
"--color-drawer-shadow": withAlpha("#000000", appearance === "dark" ? 0.32 : 0.12),
"--color-dot-separator": withAlpha(c.textMuted, 0.35),
diff --git a/apps/web/src/components/Sidebar.tsx b/apps/web/src/components/Sidebar.tsx
index 667f87b8df96..80251c63c225 100644
--- a/apps/web/src/components/Sidebar.tsx
+++ b/apps/web/src/components/Sidebar.tsx
@@ -1531,7 +1531,8 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: {
// All sidebar rows share one surface model. Live threads used to look
// like elevated cards while settled threads were plain rows, leaving neither
// a useful hierarchy nor a reliable hover cue. Status now lives in the row
- // content; surface is reserved for interaction (hover, multi-select, route).
+ // content; background fills mark interaction (hover, multi-select, route) and
+ // unsent drafts. Pinned rows add a hairline outline instead of a fill.
const rowSurfaceClassName = cn(
"group/sidebar-row relative w-full cursor-pointer overflow-hidden rounded-md text-left outline-none select-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
variantAction === "unsettle" && "[&:not(:hover):not(:focus-within)_*]:text-secondary-label/70",
@@ -1549,6 +1550,12 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: {
shouldRecede &&
status === "working" &&
"opacity-70 transition-opacity hover:opacity-100 focus-within:opacity-100 motion-reduce:transition-none",
+ // Pin-colored hairline; in the built-in palettes it stays fainter than the
+ // focus and file-drop rings.
+ props.isPinned &&
+ !isFileDragOver &&
+ !props.sortable?.isDragging &&
+ "ring-1 ring-inset ring-sidebar-pin/20",
isFileDragOver && "ring-1 ring-inset ring-primary/70",
isFileDragOver && !props.isActive && !isSelected && "bg-sidebar-row-hover",
// The lifted row is an opaque card so the rows beneath it never show
@@ -1714,7 +1721,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: {
type="button"
aria-label="Unpin thread"
onClick={handleUnpinClick}
- className="group/unpin inline-flex cursor-pointer items-center rounded-sm text-muted-foreground/65 outline-none transition-colors hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring"
+ className="group/unpin inline-flex cursor-pointer items-center rounded-sm text-sidebar-pin outline-none transition-colors hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring"
/>
}
>
@@ -1732,11 +1739,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: {
Unpin thread
) : (
-
+
)
) : null;
diff --git a/apps/web/src/index.css b/apps/web/src/index.css
index a4b80193dce2..d553840b8ffb 100644
--- a/apps/web/src/index.css
+++ b/apps/web/src/index.css
@@ -274,6 +274,7 @@ html[data-mobile-composer-route-transition="true"]::view-transition-old(t3-mobil
--color-sidebar-row-active: var(--sidebar-row-active);
--color-sidebar-row-selected: var(--sidebar-row-selected);
--color-sidebar-border: var(--contrast-sidebar-border);
+ --color-sidebar-pin: var(--sidebar-pin);
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
@@ -1582,6 +1583,10 @@ html[data-theme-id="t3-chat"] [data-app-sidebar] {
color-mix(in srgb, var(--sidebar-border) var(--appearance-contrast-base), transparent),
var(--sidebar-foreground) var(--appearance-contrast-border-boost)
);
+ /* Pinned threads take the theme's focus accent, pulled mostly toward the
+ sidebar text so the pin stays legible in the built-in palettes and follows
+ the contrast setting. Theme action colors are fills and can vanish here. */
+ --sidebar-pin: color-mix(in oklab, var(--ring) 40%, var(--contrast-sidebar-foreground));
}
body {