From e58cd2292ee3f28de40c60e110f8a1022ef6c942 Mon Sep 17 00:00:00 2001 From: Pixel Perfect Date: Thu, 29 Oct 2026 14:41:45 -0700 Subject: [PATCH 1/2] feat(web): add colored PR text preference --- .../src/components/ThreadStatusIndicators.tsx | 6 ++++- .../settings/AppearanceSettingsPanel.tsx | 26 +++++++++++++++++++ .../components/settings/SettingsPanels.tsx | 4 +++ .../src/components/settings/settingsSearch.ts | 6 +++++ packages/contracts/src/settings.ts | 2 ++ 5 files changed, 43 insertions(+), 1 deletion(-) diff --git a/apps/web/src/components/ThreadStatusIndicators.tsx b/apps/web/src/components/ThreadStatusIndicators.tsx index 0af0e063bdea3..96541e7d85f02 100644 --- a/apps/web/src/components/ThreadStatusIndicators.tsx +++ b/apps/web/src/components/ThreadStatusIndicators.tsx @@ -31,6 +31,7 @@ import { import { useRender } from "@base-ui/react/use-render"; import { type ReactNode, type AnimationEvent, type MouseEvent, type ReactElement } from "react"; import { cn } from "../lib/utils"; +import { useClientSettings } from "../hooks/useSettings"; import { revealThreadTerminal } from "../lib/revealThreadTerminal"; import { useEnvironmentQuery } from "../state/query"; @@ -259,6 +260,7 @@ function PullRequestBadge({ onOpenList: () => void; onOpenPullRequest: (event: MouseEvent, url?: string) => void; }) { + const colorizePullRequestText = useClientSettings((settings) => settings.colorizePullRequestText); const onClick = opensList ? (event: MouseEvent) => { event.preventDefault(); @@ -287,7 +289,9 @@ function PullRequestBadge({ className={cn("contents font-normal text-xs tabular-nums", presentation.toneClassName)} > - {presentation.text} + + {presentation.text} + + + updateSettings({ + colorizePullRequestText: DEFAULT_UNIFIED_SETTINGS.colorizePullRequestText, + }) + } + /> + ) : null + } + control={ + + updateSettings({ colorizePullRequestText: Boolean(checked) }) + } + aria-label="Color PR text" + /> + } + /> void) { ? ["Diff colors"] : []), ...(settings.chatWidth !== DEFAULT_UNIFIED_SETTINGS.chatWidth ? ["Chat width"] : []), + ...(settings.colorizePullRequestText !== DEFAULT_UNIFIED_SETTINGS.colorizePullRequestText + ? ["Color PR text"] + : []), ...(settings.effortDisplay !== DEFAULT_UNIFIED_SETTINGS.effortDisplay ? ["Effort display"] : []), @@ -609,6 +612,7 @@ export function useSettingsRestore(onRestored?: () => void) { appearanceContrast: DEFAULT_UNIFIED_SETTINGS.appearanceContrast, diffColorScheme: DEFAULT_UNIFIED_SETTINGS.diffColorScheme, chatWidth: DEFAULT_UNIFIED_SETTINGS.chatWidth, + colorizePullRequestText: DEFAULT_UNIFIED_SETTINGS.colorizePullRequestText, effortDisplay: DEFAULT_UNIFIED_SETTINGS.effortDisplay, mathRenderingEnabled: DEFAULT_UNIFIED_SETTINGS.mathRenderingEnabled, timestampFormat: DEFAULT_UNIFIED_SETTINGS.timestampFormat, diff --git a/apps/web/src/components/settings/settingsSearch.ts b/apps/web/src/components/settings/settingsSearch.ts index dc494caf5344d..af71de73458fc 100644 --- a/apps/web/src/components/settings/settingsSearch.ts +++ b/apps/web/src/components/settings/settingsSearch.ts @@ -333,6 +333,12 @@ export const SETTINGS_SEARCH_ITEMS = [ "customize show hide panel card environment editor scripts branch pull request git changes servers automations lineage usage limits 5 hour weekly quota tokens context window", ], }, + { + id: "colorize-pull-request-text", + title: "Color PR text", + to: "/settings/appearance", + searchTerms: ["pull request merge request sidebar indicator badge number stack status color"], + }, { id: "effort-display", title: "Effort display", diff --git a/packages/contracts/src/settings.ts b/packages/contracts/src/settings.ts index 179e58b7a0b56..b11f90af90ee2 100644 --- a/packages/contracts/src/settings.ts +++ b/packages/contracts/src/settings.ts @@ -357,6 +357,7 @@ export const ClientSettingsSchema = Schema.Struct({ ), chatWidth: ChatWidth.pipe(Schema.withDecodingDefault(Effect.succeed("comfortable" as const))), effortDisplay: EffortDisplay.pipe(Schema.withDecodingDefault(Effect.succeed("label" as const))), + colorizePullRequestText: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(true))), loadBalancingEnabled: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))), loadBalancingWeights: LoadBalancingWeights.pipe(Schema.withDecodingDefault(Effect.succeed({}))), appearanceContrast: AppearanceContrast.pipe( @@ -1770,6 +1771,7 @@ export const ClientSettingsPatch = Schema.Struct({ diffColorScheme: Schema.optionalKey(DiffColorScheme), chatWidth: Schema.optionalKey(ChatWidth), effortDisplay: Schema.optionalKey(EffortDisplay), + colorizePullRequestText: Schema.optionalKey(Schema.Boolean), loadBalancingEnabled: Schema.optionalKey(Schema.Boolean), loadBalancingWeights: Schema.optionalKey(LoadBalancingWeights), appearanceContrast: Schema.optionalKey(AppearanceContrast), From 82d23ea0696efa70967026217dd6aec273c5fbec Mon Sep 17 00:00:00 2001 From: Pixel Perfect Date: Thu, 29 Oct 2026 14:54:03 -0700 Subject: [PATCH 2/2] fix(web): honor PR text colors in search results --- apps/web/src/components/ThreadStatusIndicators.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/web/src/components/ThreadStatusIndicators.tsx b/apps/web/src/components/ThreadStatusIndicators.tsx index 96541e7d85f02..e56a93c6f4b0f 100644 --- a/apps/web/src/components/ThreadStatusIndicators.tsx +++ b/apps/web/src/components/ThreadStatusIndicators.tsx @@ -835,6 +835,7 @@ export function ThreadSearchPullRequestNumber({ enabled?: boolean; settled?: boolean; }) { + const colorizePullRequestText = useClientSettings((settings) => settings.colorizePullRequestText); const matched = pullRequestMatchesSearchQuery(thread, query); const supportsMultiplePullRequests = useSupportsMultiplePullRequests(thread.environmentId); const linked = useLinkedThreadPullRequest( @@ -886,7 +887,9 @@ export function ThreadSearchPullRequestNumber({ > {/* text-current opts out of the command palette's muted icon color. */} - {presentation.text} + + {presentation.text} + ); }