authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-09-24 10:49:04-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-24 10:49:04-07:00
log315fcca10a826d8aa1cbdffc3ef5b5eb5a1e2f9d
tree76aa7388fe5aa248af8f42146799f7ac0225f30c
parent80fc23ac32cd8fe5011a94420cff1f469367f1fc
signature Signed by PGP key B5690EEEBB952194

fix(web): web colors come from theme tokens (#13371)

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

28 files changed, 173 insertions(+), 172 deletions(-)

apps/web/src/components/ChatMarkdown.tsx+1-1
...@@ -308,7 +308,7 @@ function CodexArtifactTemplateCard(props: {...@@ -308,7 +308,7 @@ function CodexArtifactTemplateCard(props: {
308 <div className="flex min-w-0 flex-1 items-center gap-3">308 <div className="flex min-w-0 flex-1 items-center gap-3">
309 <span className="relative flex size-9 shrink-0 items-center justify-center rounded-lg border border-border/70 bg-background text-muted-foreground shadow-xs">309 <span className="relative flex size-9 shrink-0 items-center justify-center rounded-lg border border-border/70 bg-background text-muted-foreground shadow-xs">
310 <Icon aria-hidden className="size-5" />310 <Icon aria-hidden className="size-5" />
311 <span className="absolute -right-1 -bottom-1 flex size-4 items-center justify-center rounded-full border border-background bg-fuchsia-500 text-white shadow-xs">311 <span className="absolute -right-1 -bottom-1 flex size-4 items-center justify-center rounded-full border border-background bg-primary text-primary-foreground shadow-xs">
312 <SparklesIcon aria-hidden className="size-2.5" />312 <SparklesIcon aria-hidden className="size-2.5" />
313 </span>313 </span>
314 </span>314 </span>
apps/web/src/components/Icons.tsx+85
...@@ -781,3 +781,88 @@ export const ForgejoIcon: Icon = (props) => (...@@ -781,3 +781,88 @@ export const ForgejoIcon: Icon = (props) => (
781 </g>781 </g>
782 </svg>782 </svg>
783);783);
784
785// macOS System Settings > Privacy & Security pane marks, so the SnapShot setup
786// step points at the same icon the user is about to look for.
787export const MacScreenRecordingIcon: Icon = (props) => {
788 const gradientId = useId();
789 return (
790 <svg viewBox="0 0 32 32" aria-hidden="true" {...props}>
791 <defs>
792 <linearGradient id={gradientId} x2="0" y2="1">
793 <stop stopColor="#ff6972" />
794 <stop offset="1" stopColor="#ff2938" />
795 </linearGradient>
796 </defs>
797 <rect
798 x="0.5"
799 y="0.5"
800 width="31"
801 height="31"
802 rx="7"
803 fill={`url(#${gradientId})`}
804 stroke="#ffffff40"
805 />
806 <circle cx="16" cy="16" r="10" fill="none" stroke="#fff" strokeWidth="2" />
807 <circle cx="16" cy="16" r="4.5" fill="#fff" />
808 </svg>
809 );
810};
811
812export const MacAccessibilityIcon: Icon = (props) => {
813 const gradientId = useId();
814 return (
815 <svg viewBox="0 0 32 32" aria-hidden="true" {...props}>
816 <defs>
817 <linearGradient id={gradientId} x2="0" y2="1">
818 <stop stopColor="#48b6ff" />
819 <stop offset="1" stopColor="#0085ff" />
820 </linearGradient>
821 </defs>
822 <rect
823 x="0.5"
824 y="0.5"
825 width="31"
826 height="31"
827 rx="7"
828 fill={`url(#${gradientId})`}
829 stroke="#ffffff40"
830 />
831 <circle cx="16" cy="16" r="10" fill="none" stroke="#fff" strokeWidth="1.75" />
832 <circle cx="16" cy="10" r="1.6" fill="#fff" />
833 <path
834 d="m10 13 6 1 6-1M16 14v4m0 0-2.5 6m2.5-6 2.5 6"
835 fill="none"
836 stroke="#fff"
837 strokeWidth="1.6"
838 strokeLinecap="round"
839 strokeLinejoin="round"
840 />
841 </svg>
842 );
843};
844
845// Codex's Computer Use app mark, shown on computer-use rows in the work log.
846export const ComputerUseAppIcon: Icon = (props) => {
847 const gradientId = `${useId().replaceAll(":", "")}-computer-use-app-gradient`;
848 return (
849 <svg viewBox="0 0 24 24" aria-hidden="true" {...props}>
850 <defs>
851 <linearGradient id={gradientId} x1="2" y1="2" x2="22" y2="22">
852 <stop offset="0" stopColor="#00dff0" />
853 <stop offset="0.42" stopColor="#3b9cff" />
854 <stop offset="0.72" stopColor="#b044f5" />
855 <stop offset="1" stopColor="#ff78b6" />
856 </linearGradient>
857 </defs>
858 <rect x="1" y="1" width="22" height="22" rx="5" fill={`url(#${gradientId})`} />
859 <path
860 d="m7.2 6.2 10.5 4.1-4.2 2.1-2 4.7z"
861 fill="white"
862 stroke="#315cff"
863 strokeWidth="1.1"
864 strokeLinejoin="round"
865 />
866 </svg>
867 );
868};
apps/web/src/components/LegacySidebar.tsx+1-1
...@@ -806,7 +806,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: SidebarThreadRowP...@@ -806,7 +806,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: SidebarThreadRowP
806 <button806 <button
807 type="button"807 type="button"
808 aria-label={`Open localhost:${discoveredPorts[0]?.port ?? ""}`}808 aria-label={`Open localhost:${discoveredPorts[0]?.port ?? ""}`}
809 className="inline-flex cursor-pointer items-center justify-center text-emerald-600 outline-hidden focus-visible:ring-1 focus-visible:ring-ring dark:text-emerald-400"809 className="inline-flex cursor-pointer items-center justify-center text-success-foreground outline-hidden focus-visible:ring-1 focus-visible:ring-ring"
810 onClick={handleOpenDiscoveredPort}810 onClick={handleOpenDiscoveredPort}
811 />811 />
812 }812 }
apps/web/src/components/QuitHoldOverlay.tsx+1-1
...@@ -48,7 +48,7 @@ export function QuitHoldOverlay() {...@@ -48,7 +48,7 @@ export function QuitHoldOverlay() {
48 role="status"48 role="status"
49 className="pointer-events-none fixed inset-x-0 top-[22%] z-100 flex justify-center"49 className="pointer-events-none fixed inset-x-0 top-[22%] z-100 flex justify-center"
50 >50 >
51 <div className="rounded-full bg-neutral-700/95 px-8 py-4 text-2xl font-bold text-white shadow-xl">51 <div className="rounded-full bg-foreground/95 px-8 py-4 text-2xl font-bold text-background shadow-xl">
52 {message}52 {message}
53 </div>53 </div>
54 </div>54 </div>
apps/web/src/components/Sidebar.tsx+9-9
...@@ -414,7 +414,7 @@ function SidebarThreadTooltip({...@@ -414,7 +414,7 @@ function SidebarThreadTooltip({
414 </div>414 </div>
415 ) : null}415 ) : null}
416 {thread.session?.lastError ? (416 {thread.session?.lastError ? (
417 <div className="flex min-w-0 items-center gap-2 text-red-600 dark:text-red-400">417 <div className="flex min-w-0 items-center gap-2 text-destructive-foreground">
418 <CircleAlertIcon className="size-3 shrink-0 stroke-current" />418 <CircleAlertIcon className="size-3 shrink-0 stroke-current" />
419 <div className="min-w-0 truncate">Error occurred</div>419 <div className="min-w-0 truncate">Error occurred</div>
420 </div>420 </div>
...@@ -529,8 +529,8 @@ function SortableThreadRow(props: {...@@ -529,8 +529,8 @@ function SortableThreadRow(props: {
529529
530// Unsent work shares one look: the new-thread draft rows and thread rows530// Unsent work shares one look: the new-thread draft rows and thread rows
531// with unsent composer text both use this tint and pen so they read alike.531// with unsent composer text both use this tint and pen so they read alike.
532const draftSurfaceClassName = "bg-amber-400/[0.04] hover:bg-amber-400/[0.08]";532const draftSurfaceClassName = "bg-warning/4 hover:bg-warning/8";
533const draftPenClassName = "size-3 shrink-0 text-amber-600 dark:text-amber-300/80";533const draftPenClassName = "size-3 shrink-0 text-warning-foreground";
534534
535// Structural list items — the section headers and the535// Structural list items — the section headers and the
536// empty-section placeholders — take part in the sortable list so they shift536// empty-section placeholders — take part in the sortable list so they shift
...@@ -647,7 +647,7 @@ function SidebarSectionHeader(props: {...@@ -647,7 +647,7 @@ function SidebarSectionHeader(props: {
647 const snoozed = props.marker === "snoozed-header";647 const snoozed = props.marker === "snoozed-header";
648 const className = cn(648 const className = cn(
649 "flex h-full w-full items-center gap-2 px-2 text-left text-xs font-medium",649 "flex h-full w-full items-center gap-2 px-2 text-left text-xs font-medium",
650 snoozed ? "text-blue-600 dark:text-blue-400" : "text-sidebar-muted-foreground/60",650 snoozed ? "text-info-foreground" : "text-sidebar-muted-foreground/60",
651 props.dragging && "text-sidebar-foreground/80",651 props.dragging && "text-sidebar-foreground/80",
652 props.isDropTarget && "text-primary",652 props.isDropTarget && "text-primary",
653 );653 );
...@@ -658,7 +658,7 @@ function SidebarSectionHeader(props: {...@@ -658,7 +658,7 @@ function SidebarSectionHeader(props: {
658 aria-hidden658 aria-hidden
659 className={cn(659 className={cn(
660 "h-px min-w-2 flex-1",660 "h-px min-w-2 flex-1",
661 snoozed ? "bg-blue-500/20 dark:bg-blue-400/15" : "bg-sidebar-border/60",661 snoozed ? "bg-info/20" : "bg-sidebar-border/60",
662 props.dragging && "bg-sidebar-foreground/25",662 props.dragging && "bg-sidebar-foreground/25",
663 props.isDropTarget && "bg-primary/50",663 props.isDropTarget && "bg-primary/50",
664 )}664 )}
...@@ -1143,7 +1143,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: {...@@ -1143,7 +1143,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: {
1143 ? {1143 ? {
1144 label: "Approval",1144 label: "Approval",
1145 icon: "approval" as const,1145 icon: "approval" as const,
1146 className: "text-amber-700 dark:text-amber-300",1146 className: "text-warning-foreground",
1147 }1147 }
1148 : status === "input"1148 : status === "input"
1149 ? {1149 ? {
...@@ -1161,7 +1161,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: {...@@ -1161,7 +1161,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: {
1161 ? {1161 ? {
1162 label: "Woke",1162 label: "Woke",
1163 icon: "woke" as const,1163 icon: "woke" as const,
1164 className: "text-amber-700 dark:text-amber-300",1164 className: "text-warning-foreground",
1165 }1165 }
1166 : isUnread1166 : isUnread
1167 ? {1167 ? {
...@@ -1629,7 +1629,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: {...@@ -1629,7 +1629,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: {
1629 {variantAction === "unsnooze" && props.snoozeWakeLabelText !== null ? (1629 {variantAction === "unsnooze" && props.snoozeWakeLabelText !== null ? (
1630 // Snoozed rows show when they come BACK, not when they were1630 // Snoozed rows show when they come BACK, not when they were
1631 // last touched — the return ticket is the row's whole story.1631 // last touched — the return ticket is the row's whole story.
1632 <span className="text-xs text-blue-600 tabular-nums dark:text-blue-400">1632 <span className="text-xs text-info-foreground tabular-nums">
1633 {props.snoozeWakeLabelText}1633 {props.snoozeWakeLabelText}
1634 </span>1634 </span>
1635 ) : isWoke ? (1635 ) : isWoke ? (
...@@ -1642,7 +1642,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: {...@@ -1642,7 +1642,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: {
1642 type="button"1642 type="button"
1643 aria-label="Dismiss Woke notification"1643 aria-label="Dismiss Woke notification"
1644 onClick={handleAcknowledgeWokeClick}1644 onClick={handleAcknowledgeWokeClick}
1645 className="inline-flex cursor-pointer items-center gap-1 rounded-sm text-xs font-medium text-amber-700 outline-none hover:underline focus-visible:ring-2 focus-visible:ring-ring dark:text-amber-300"1645 className="inline-flex cursor-pointer items-center gap-1 rounded-sm text-xs font-medium text-warning-foreground outline-none hover:underline focus-visible:ring-2 focus-visible:ring-ring"
1646 >1646 >
1647 <AlarmClockIcon aria-hidden className="size-3" />1647 <AlarmClockIcon aria-hidden className="size-3" />
1648 <span role="status">Woke</span>1648 <span role="status">Woke</span>
apps/web/src/components/ThreadNotificationCoordinator.tsx+4-13
...@@ -164,22 +164,13 @@ function EnvironmentNotifications({...@@ -164,22 +164,13 @@ function EnvironmentNotifications({
164 hideCopyButton: true,164 hideCopyButton: true,
165 leadingIcon:165 leadingIcon:
166 kind === "completion" ? (166 kind === "completion" ? (
167 <CircleCheckIcon167 <CircleCheckIcon aria-hidden className="size-4 text-success-foreground" />
168 aria-hidden
169 className="size-4 text-emerald-700 dark:text-emerald-300"
170 />
171 ) : status === "approval" ? (168 ) : status === "approval" ? (
172 <ShieldQuestionIcon169 <ShieldQuestionIcon aria-hidden className="size-4 text-warning-foreground" />
173 aria-hidden
174 className="size-4 text-amber-700 dark:text-amber-300"
175 />
176 ) : status === "failed" ? (170 ) : status === "failed" ? (
177 <CircleAlertIcon aria-hidden className="size-4 text-red-700 dark:text-red-300" />171 <CircleAlertIcon aria-hidden className="size-4 text-destructive-foreground" />
178 ) : (172 ) : (
179 <MessageCircleQuestionIcon173 <MessageCircleQuestionIcon aria-hidden className="size-4 text-info-foreground" />
180 aria-hidden
181 className="size-4 text-indigo-600 dark:text-indigo-300"
182 />
183 ),174 ),
184 },175 },
185 actionProps: {176 actionProps: {
apps/web/src/components/ThreadSearchMatch.tsx+1-1
...@@ -57,7 +57,7 @@ export function ThreadSearchMatchExcerpt(props: {...@@ -57,7 +57,7 @@ export function ThreadSearchMatchExcerpt(props: {
57 const isUser = props.match.source === "user";57 const isUser = props.match.source === "user";
58 return (58 return (
59 <span className="truncate text-xs text-muted-foreground/85">59 <span className="truncate text-xs text-muted-foreground/85">
60 <span className={isUser ? "text-blue-400" : "text-emerald-400"}>60 <span className={isUser ? "text-info-foreground" : "text-success-foreground"}>
61 {isUser ? "You:" : "Agent:"}61 {isUser ? "You:" : "Agent:"}
62 </span>{" "}62 </span>{" "}
63 <HighlightedSearchText text={props.match.snippet} query={props.match.query} />63 <HighlightedSearchText text={props.match.snippet} query={props.match.query} />
apps/web/src/components/chat/ChatComposer.tsx+1-1
...@@ -6559,7 +6559,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps)...@@ -6559,7 +6559,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps)
6559 <span6559 <span
6560 role="img"6560 role="img"
6561 aria-label="Draft attachment may not persist"6561 aria-label="Draft attachment may not persist"
6562 className="absolute left-1 top-1 inline-flex items-center justify-center rounded bg-background/85 p-0.5 text-amber-600"6562 className="absolute left-1 top-1 inline-flex items-center justify-center rounded bg-background/85 p-0.5 text-warning-foreground"
6563 >6563 >
6564 <CircleAlertIcon className="size-3" />6564 <CircleAlertIcon className="size-3" />
6565 </span>6565 </span>
apps/web/src/components/chat/ContextWindowMeter.tsx+1-1
...@@ -63,7 +63,7 @@ export function ContextWindowMeter(props: {...@@ -63,7 +63,7 @@ export function ContextWindowMeter(props: {
63 cy="12"63 cy="12"
64 r={radius}64 r={radius}
65 fill="none"65 fill="none"
66 stroke="color-mix(in oklab, var(--color-muted-foreground) 24%, transparent)"66 className="stroke-muted-foreground/24"
67 strokeWidth="3"67 strokeWidth="3"
68 />68 />
69 <circle69 <circle
apps/web/src/components/chat/MessagesTimeline.tsx+1-25
...@@ -63,7 +63,6 @@ import {...@@ -63,7 +63,6 @@ import {
63 use,63 use,
64 useCallback,64 useCallback,
65 useEffect,65 useEffect,
66 useId,
67 useLayoutEffect,66 useLayoutEffect,
68 useMemo,67 useMemo,
69 useRef,68 useRef,
...@@ -256,6 +255,7 @@ import {...@@ -256,6 +255,7 @@ import {
256 type ReviewCommentContext,255 type ReviewCommentContext,
257} from "../../reviewCommentContext";256} from "../../reviewCommentContext";
258import { PullRequestGlyph } from "~/components/pullRequest/pullRequestIcons";257import { PullRequestGlyph } from "~/components/pullRequest/pullRequestIcons";
258import { ComputerUseAppIcon } from "~/components/Icons";
259259
260// ---------------------------------------------------------------------------260// ---------------------------------------------------------------------------
261// Context — shared state consumed by every row component via Context.261// Context — shared state consumed by every row component via Context.
...@@ -4146,30 +4146,6 @@ function BrowserAppIcon({ className }: { className: string }) {...@@ -4146,30 +4146,6 @@ function BrowserAppIcon({ className }: { className: string }) {
4146 );4146 );
4147}4147}
41484148
4149function ComputerUseAppIcon({ className }: { className: string }) {
4150 const gradientId = `${useId().replaceAll(":", "")}-computer-use-app-gradient`;
4151 return (
4152 <svg viewBox="0 0 24 24" className={className} aria-hidden>
4153 <defs>
4154 <linearGradient id={gradientId} x1="2" y1="2" x2="22" y2="22">
4155 <stop offset="0" stopColor="#00dff0" />
4156 <stop offset="0.42" stopColor="#3b9cff" />
4157 <stop offset="0.72" stopColor="#b044f5" />
4158 <stop offset="1" stopColor="#ff78b6" />
4159 </linearGradient>
4160 </defs>
4161 <rect x="1" y="1" width="22" height="22" rx="5" fill={`url(#${gradientId})`} />
4162 <path
4163 d="m7.2 6.2 10.5 4.1-4.2 2.1-2 4.7z"
4164 fill="white"
4165 stroke="#315cff"
4166 strokeWidth="1.1"
4167 strokeLinejoin="round"
4168 />
4169 </svg>
4170 );
4171}
4172
4173function ToolActivityIconView(props: {4149function ToolActivityIconView(props: {
4174 icon: ToolActivityIcon | undefined;4150 icon: ToolActivityIcon | undefined;
4175 fallbackName: WorkEntryIconName;4151 fallbackName: WorkEntryIconName;
apps/web/src/components/chat/ModelListRow.tsx+1-1
...@@ -117,7 +117,7 @@ export const ModelListRow = memo(function ModelListRow(props: {...@@ -117,7 +117,7 @@ export const ModelListRow = memo(function ModelListRow(props: {
117 <StarIcon117 <StarIcon
118 className={cn(118 className={cn(
119 "size-3.5 sm:size-3",119 "size-3.5 sm:size-3",
120 props.isFavorite && "fill-current text-yellow-500",120 props.isFavorite && "fill-current text-warning",
121 )}121 )}
122 />122 />
123 </Button>123 </Button>
apps/web/src/components/chat/TerminalContextInlineChip.tsx+1-1
...@@ -26,7 +26,7 @@ export function TerminalContextInlineChip(props: TerminalContextInlineChipProps)...@@ -26,7 +26,7 @@ export function TerminalContextInlineChip(props: TerminalContextInlineChipProps)
26 >26 >
27 <div className="overflow-hidden rounded-md border border-border/70 bg-background/80">27 <div className="overflow-hidden rounded-md border border-border/70 bg-background/80">
28 <div className="flex items-center gap-2 border-b border-border/70 px-3 py-2">28 <div className="flex items-center gap-2 border-b border-border/70 px-3 py-2">
29 <TerminalIcon className="size-4 shrink-0 text-emerald-500" aria-hidden />29 <TerminalIcon className="size-4 shrink-0 text-success" aria-hidden />
30 <span className="min-w-0 truncate text-sm font-medium text-foreground">30 <span className="min-w-0 truncate text-sm font-medium text-foreground">
31 {terminalLabel}31 {terminalLabel}
32 </span>32 </span>
apps/web/src/components/cloud/ConnectCliAuthSurface.tsx+1-1
...@@ -23,7 +23,7 @@ function ConnectCliAuthMessage({...@@ -23,7 +23,7 @@ function ConnectCliAuthMessage({
23 return (23 return (
24 <>24 <>
25 {eyebrow ? (25 {eyebrow ? (
26 <p className="text-[10px] font-semibold tracking-[0.18em] text-blue-600 uppercase dark:text-blue-400">26 <p className="text-[10px] font-semibold tracking-[0.18em] text-primary uppercase">
27 {eyebrow}27 {eyebrow}
28 </p>28 </p>
29 ) : null}29 ) : null}
apps/web/src/components/device/DeviceStreamView.tsx+2-2
...@@ -395,7 +395,7 @@ export function DeviceStreamView(props: {...@@ -395,7 +395,7 @@ export function DeviceStreamView(props: {
395 {axElements.map((element) => (395 {axElements.map((element) => (
396 <div396 <div
397 key={element.id}397 key={element.id}
398 className="absolute border border-sky-400/80 bg-sky-400/10"398 className="absolute border border-info/80 bg-info/10"
399 style={{399 style={{
400 left: `${element.x * 100}%`,400 left: `${element.x * 100}%`,
401 top: `${element.y * 100}%`,401 top: `${element.y * 100}%`,
...@@ -404,7 +404,7 @@ export function DeviceStreamView(props: {...@@ -404,7 +404,7 @@ export function DeviceStreamView(props: {
404 }}404 }}
405 >405 >
406 {element.label ? (406 {element.label ? (
407 <span className="absolute -top-3.5 left-0 max-w-full truncate rounded-sm bg-sky-500 px-1 text-[9px] leading-3.5 text-white">407 <span className="absolute -top-3.5 left-0 max-w-full truncate rounded-sm bg-info px-1 text-[9px] leading-3.5 text-white">
408 {element.label}408 {element.label}
409 </span>409 </span>
410 ) : null}410 ) : null}
apps/web/src/components/preview/ThreadPreviewMiniPlayer.tsx+4-2
...@@ -462,7 +462,9 @@ function MiniPlayerShell({...@@ -462,7 +462,9 @@ function MiniPlayerShell({
462 <span462 <span
463 className={cn(463 className={cn(
464 "block size-2 rounded-full shadow-sm ring-1 ring-background/70",464 "block size-2 rounded-full shadow-sm ring-1 ring-background/70",
465 recording ? "bg-red-500 motion-safe:animate-status-pulse" : "bg-foreground/25",465 recording
466 ? "bg-destructive motion-safe:animate-status-pulse"
467 : "bg-foreground/25",
466 )}468 )}
467 />469 />
468 </div>470 </div>
...@@ -475,7 +477,7 @@ function MiniPlayerShell({...@@ -475,7 +477,7 @@ function MiniPlayerShell({
475 >477 >
476 {recording ? (478 {recording ? (
477 <span aria-hidden className="flex size-6 shrink-0 items-center justify-center">479 <span aria-hidden className="flex size-6 shrink-0 items-center justify-center">
478 <span className="size-2 rounded-full bg-red-500 motion-safe:animate-status-pulse" />480 <span className="size-2 rounded-full bg-destructive motion-safe:animate-status-pulse" />
479 </span>481 </span>
480 ) : null}482 ) : null}
481 <Tooltip>483 <Tooltip>
apps/web/src/components/pullRequest/PullRequestCodeTab.tsx+4-4
...@@ -852,7 +852,7 @@ function PullRequestCodeTab({...@@ -852,7 +852,7 @@ function PullRequestCodeTab({
852 />852 />
853 {stale ? (853 {stale ? (
854 <Tooltip>854 <Tooltip>
855 <TooltipTrigger render={<span className="text-amber-600 dark:text-amber-500" />}>855 <TooltipTrigger render={<span className="text-warning-foreground" />}>
856 Changed856 Changed
857 </TooltipTrigger>857 </TooltipTrigger>
858 <TooltipPopup side="bottom">858 <TooltipPopup side="bottom">
...@@ -1157,7 +1157,7 @@ function PullRequestCodeTab({...@@ -1157,7 +1157,7 @@ function PullRequestCodeTab({
1157 <TooltipTrigger render={<span className="flex shrink-0 items-center" />}>1157 <TooltipTrigger render={<span className="flex shrink-0 items-center" />}>
1158 <TriangleAlertIcon1158 <TriangleAlertIcon
1159 aria-label="Your ticks could not be read"1159 aria-label="Your ticks could not be read"
1160 className="size-3.5 text-amber-600 dark:text-amber-500"1160 className="size-3.5 text-warning-foreground"
1161 />1161 />
1162 </TooltipTrigger>1162 </TooltipTrigger>
1163 <TooltipPopup side="bottom">1163 <TooltipPopup side="bottom">
...@@ -1171,7 +1171,7 @@ function PullRequestCodeTab({...@@ -1171,7 +1171,7 @@ function PullRequestCodeTab({
1171 <TooltipTrigger render={<span className="flex shrink-0 items-center" />}>1171 <TooltipTrigger render={<span className="flex shrink-0 items-center" />}>
1172 <TriangleAlertIcon1172 <TriangleAlertIcon
1173 aria-label="This count covers only part of the change"1173 aria-label="This count covers only part of the change"
1174 className="size-3.5 text-amber-600 dark:text-amber-500"1174 className="size-3.5 text-warning-foreground"
1175 />1175 />
1176 </TooltipTrigger>1176 </TooltipTrigger>
1177 <TooltipPopup side="bottom">1177 <TooltipPopup side="bottom">
...@@ -1187,7 +1187,7 @@ function PullRequestCodeTab({...@@ -1187,7 +1187,7 @@ function PullRequestCodeTab({
1187 <TooltipTrigger render={<span className="flex shrink-0 items-center" />}>1187 <TooltipTrigger render={<span className="flex shrink-0 items-center" />}>
1188 <TriangleAlertIcon1188 <TriangleAlertIcon
1189 aria-label="Some of this diff was not shown"1189 aria-label="Some of this diff was not shown"
1190 className="size-3.5 text-amber-600 dark:text-amber-500"1190 className="size-3.5 text-warning-foreground"
1191 />1191 />
1192 </TooltipTrigger>1192 </TooltipTrigger>
1193 <TooltipPopup side="bottom">1193 <TooltipPopup side="bottom">
apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx+1-1
...@@ -379,7 +379,7 @@ function PullRequestBaseFreshnessWarning({...@@ -379,7 +379,7 @@ function PullRequestBaseFreshnessWarning({
379 type="button"379 type="button"
380 aria-label={summary}380 aria-label={summary}
381 className={cn(381 className={cn(
382 "inline-flex min-w-0 shrink-0 cursor-help items-center gap-1 rounded-sm text-amber-600 outline-none focus-visible:ring-2 focus-visible:ring-ring dark:text-amber-400/90",382 "inline-flex min-w-0 shrink-0 cursor-help items-center gap-1 rounded-sm text-warning-foreground outline-none focus-visible:ring-2 focus-visible:ring-ring",
383 className,383 className,
384 )}384 )}
385 />385 />
apps/web/src/components/pullRequest/PullRequestReviewAnnotation.tsx+1-1
...@@ -220,7 +220,7 @@ export function ReviewThreadCard({...@@ -220,7 +220,7 @@ export function ReviewThreadCard({
220 >220 >
221 <div className="flex items-center gap-2 text-xs text-muted-foreground">221 <div className="flex items-center gap-2 text-xs text-muted-foreground">
222 {thread.isResolved ? (222 {thread.isResolved ? (
223 <CheckCircle2Icon className="size-3.5 text-emerald-600 dark:text-emerald-500" />223 <CheckCircle2Icon className="size-3.5 text-success-foreground" />
224 ) : (224 ) : (
225 <CircleIcon className="size-3.5" />225 <CircleIcon className="size-3.5" />
226 )}226 )}
apps/web/src/components/pullRequest/PullRequestSummaryTab.tsx+1-1
...@@ -943,7 +943,7 @@ export function PullRequestSummaryTab({...@@ -943,7 +943,7 @@ export function PullRequestSummaryTab({
943 ) : (943 ) : (
944 <>944 <>
945 {detail.commentsTruncated ? (945 {detail.commentsTruncated ? (
946 <p className="mb-2 rounded-md border border-amber-500/30 bg-amber-500/5 px-2 py-1.5 text-xs">946 <p className="mb-2 rounded-md border border-warning/30 bg-warning-surface px-2 py-1.5 text-xs">
947 This conversation is longer than this page reads in one go. The most recent{" "}947 This conversation is longer than this page reads in one go. The most recent{" "}
948 {detail.comments.length} are here; open it on the host to read the rest.948 {detail.comments.length} are here; open it on the host to read the rest.
949 </p>949 </p>
apps/web/src/components/settings/AddProviderInstanceDialog.tsx+1-1
...@@ -259,7 +259,7 @@ export function AddProviderInstanceDialog({...@@ -259,7 +259,7 @@ export function AddProviderInstanceDialog({
259 <RadioPrimitive.Root259 <RadioPrimitive.Root
260 key={option.value}260 key={option.value}
261 value={option.value}261 value={option.value}
262 className="relative flex cursor-pointer items-center gap-3 rounded-lg bg-card px-3 py-3 text-left text-muted-foreground outline-none ring-1 ring-black/5 hover:bg-zinc-50 focus-visible:ring-2 focus-visible:ring-ring data-checked:bg-primary/8 data-checked:text-foreground data-checked:ring-2 data-checked:ring-primary data-checked:hover:bg-primary/8 dark:bg-white/3 dark:ring-white/5 dark:hover:bg-white/5 dark:data-checked:bg-primary/15 dark:data-checked:ring-primary dark:data-checked:hover:bg-primary/15"262 className="relative flex cursor-pointer items-center gap-3 rounded-lg bg-card px-3 py-3 text-left text-muted-foreground outline-none ring-1 ring-black/5 hover:bg-accent focus-visible:ring-2 focus-visible:ring-ring data-checked:bg-primary/8 data-checked:text-foreground data-checked:ring-2 data-checked:ring-primary data-checked:hover:bg-primary/8 dark:bg-white/3 dark:ring-white/5 dark:hover:bg-white/5 dark:data-checked:bg-primary/15 dark:data-checked:ring-primary dark:data-checked:hover:bg-primary/15"
263 >263 >
264 <IconComponent className="size-4 shrink-0" aria-hidden />264 <IconComponent className="size-4 shrink-0" aria-hidden />
265 <span className="min-w-0 flex-1 truncate text-sm font-medium text-foreground">265 <span className="min-w-0 flex-1 truncate text-sm font-medium text-foreground">
apps/web/src/components/settings/ConnectionsSettings.tsx+1-1
...@@ -756,7 +756,7 @@ const PairingLinkListRow = memo(function PairingLinkListRow({...@@ -756,7 +756,7 @@ const PairingLinkListRow = memo(function PairingLinkListRow({
756 <div className="flex min-h-5 items-center gap-1.5">756 <div className="flex min-h-5 items-center gap-1.5">
757 <ConnectionStatusDot757 <ConnectionStatusDot
758 tooltipText={`Link created at ${formatAccessTimestamp(pairingLink.createdAt)}`}758 tooltipText={`Link created at ${formatAccessTimestamp(pairingLink.createdAt)}`}
759 dotClassName="bg-amber-400"759 dotClassName="bg-warning"
760 />760 />
761 <h3 className="text-sm font-medium text-foreground">{primaryLabel}</h3>761 <h3 className="text-sm font-medium text-foreground">{primaryLabel}</h3>
762 </div>762 </div>
apps/web/src/components/settings/DiagnosticsSettings.tsx+4-6
...@@ -116,7 +116,7 @@ function StatBlock({...@@ -116,7 +116,7 @@ function StatBlock({
116 <div116 <div
117 className={cn(117 className={cn(
118 "mt-1 truncate font-mono text-lg font-semibold tabular-nums text-foreground",118 "mt-1 truncate font-mono text-lg font-semibold tabular-nums text-foreground",
119 tone === "warning" && "text-amber-600 dark:text-amber-400",119 tone === "warning" && "text-warning-foreground",
120 tone === "danger" && "text-destructive",120 tone === "danger" && "text-destructive",
121 )}121 )}
122 >122 >
...@@ -287,7 +287,7 @@ function ProcessNameCell({...@@ -287,7 +287,7 @@ function ProcessNameCell({
287 ) : (287 ) : (
288 <span className="size-5 shrink-0" aria-hidden="true" />288 <span className="size-5 shrink-0" aria-hidden="true" />
289 )}289 )}
290 <span className="size-1.5 shrink-0 rounded-full bg-emerald-500/80" />290 <span className="size-1.5 shrink-0 rounded-full bg-success/80" />
291 <Tooltip>291 <Tooltip>
292 <TooltipTrigger292 <TooltipTrigger
293 render={<span className="min-w-0 truncate font-medium text-foreground">{name}</span>}293 render={<span className="min-w-0 truncate font-medium text-foreground">{name}</span>}
...@@ -465,7 +465,7 @@ function ResourceHistoryProcessNameCell({...@@ -465,7 +465,7 @@ function ResourceHistoryProcessNameCell({
465 <span465 <span
466 className={cn(466 className={cn(
467 "size-1.5 shrink-0 rounded-full",467 "size-1.5 shrink-0 rounded-full",
468 process.isServerRoot ? "bg-amber-500/90" : "bg-emerald-500/80",468 process.isServerRoot ? "bg-warning/90" : "bg-success/80",
469 )}469 )}
470 />470 />
471 <Tooltip>471 <Tooltip>
...@@ -1100,9 +1100,7 @@ export function DiagnosticsSettingsPanel() {...@@ -1100,9 +1100,7 @@ export function DiagnosticsSettingsPanel() {
1100 <div1100 <div
1101 className={cn(1101 className={cn(
1102 "flex items-start gap-2",1102 "flex items-start gap-2",
1103 traceDiagnosticsPartialFailure1103 traceDiagnosticsPartialFailure ? "text-warning-foreground" : "text-destructive",
1104 ? "text-amber-600 dark:text-amber-400"
1105 : "text-destructive",
1106 )}1104 )}
1107 >1105 >
1108 <AlertTriangleIcon className="mt-0.5 size-3.5 shrink-0" />1106 <AlertTriangleIcon className="mt-0.5 size-3.5 shrink-0" />
apps/web/src/components/settings/ResourceTelemetryDiagnostics.tsx+23-25
...@@ -142,10 +142,10 @@ function categoryLabel(category: ResourceTelemetryProcessCategory): string {...@@ -142,10 +142,10 @@ function categoryLabel(category: ResourceTelemetryProcessCategory): string {
142}142}
143143
144function categoryDotClass(category: ResourceTelemetryProcessCategory): string {144function categoryDotClass(category: ResourceTelemetryProcessCategory): string {
145 if (category === "resource-monitor") return "bg-amber-500";145 if (category === "resource-monitor") return "bg-warning";
146 if (category.startsWith("electron-")) return "bg-sky-500";146 if (category.startsWith("electron-")) return "bg-info";
147 if (category === "server") return "bg-violet-500";147 if (category === "server") return "bg-violet-500";
148 return "bg-emerald-500";148 return "bg-success";
149}149}
150150
151function ioSemanticsLabel(semantics: ResourceTelemetryIoSemantics): string {151function ioSemanticsLabel(semantics: ResourceTelemetryIoSemantics): string {
...@@ -196,10 +196,8 @@ function SourceStatusBadge({...@@ -196,10 +196,8 @@ function SourceStatusBadge({
196 className={cn(196 className={cn(
197 "inline-flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.08em]",197 "inline-flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.08em]",
198 tone === "neutral" && "border-border/70 bg-muted/45 text-muted-foreground",198 tone === "neutral" && "border-border/70 bg-muted/45 text-muted-foreground",
199 tone === "default" &&199 tone === "default" && "border-success/25 bg-success/10 text-success-foreground",
200 "border-emerald-500/25 bg-emerald-500/10 text-emerald-700 dark:text-emerald-300",200 tone === "warning" && "border-warning/30 bg-warning/10 text-warning-foreground",
201 tone === "warning" &&
202 "border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300",
203 tone === "danger" && "border-destructive/30 bg-destructive/10 text-destructive",201 tone === "danger" && "border-destructive/30 bg-destructive/10 text-destructive",
204 )}202 )}
205 >203 >
...@@ -207,8 +205,8 @@ function SourceStatusBadge({...@@ -207,8 +205,8 @@ function SourceStatusBadge({
207 className={cn(205 className={cn(
208 "size-1.5 rounded-full",206 "size-1.5 rounded-full",
209 tone === "neutral" && "bg-muted-foreground/55",207 tone === "neutral" && "bg-muted-foreground/55",
210 tone === "default" && "bg-emerald-500",208 tone === "default" && "bg-success",
211 tone === "warning" && "bg-amber-500",209 tone === "warning" && "bg-warning",
212 tone === "danger" && "bg-destructive",210 tone === "danger" && "bg-destructive",
213 )}211 )}
214 />212 />
...@@ -258,7 +256,7 @@ function IconStat({...@@ -258,7 +256,7 @@ function IconStat({
258 <div256 <div
259 className={cn(257 className={cn(
260 "mt-2.5 truncate font-mono text-2xl font-semibold tracking-[-0.05em] tabular-nums text-foreground",258 "mt-2.5 truncate font-mono text-2xl font-semibold tracking-[-0.05em] tabular-nums text-foreground",
261 tone === "warning" && "text-amber-600 dark:text-amber-300",259 tone === "warning" && "text-warning-foreground",
262 tone === "danger" && "text-destructive",260 tone === "danger" && "text-destructive",
263 )}261 )}
264 >262 >
...@@ -412,10 +410,10 @@ function ResourceHistoryChart({...@@ -412,10 +410,10 @@ function ResourceHistoryChart({
412 <span className="h-1.5 w-3 rounded-full bg-foreground/70" /> CPU average410 <span className="h-1.5 w-3 rounded-full bg-foreground/70" /> CPU average
413 </span>411 </span>
414 <span className="inline-flex items-center gap-1.5">412 <span className="inline-flex items-center gap-1.5">
415 <span className="h-1.5 w-3 rounded-full bg-sky-500/70" /> I/O reads413 <span className="h-1.5 w-3 rounded-full bg-info/70" /> I/O reads
416 </span>414 </span>
417 <span className="inline-flex items-center gap-1.5">415 <span className="inline-flex items-center gap-1.5">
418 <span className="h-1.5 w-3 rounded-full bg-amber-500/80" /> I/O writes416 <span className="h-1.5 w-3 rounded-full bg-warning/80" /> I/O writes
419 </span>417 </span>
420 </div>418 </div>
421 <div className="flex h-32 items-end gap-1 overflow-hidden rounded-lg border border-border/40 bg-muted/8 px-2 pt-3 pb-2">419 <div className="flex h-32 items-end gap-1 overflow-hidden rounded-lg border border-border/40 bg-muted/8 px-2 pt-3 pb-2">
...@@ -445,11 +443,11 @@ function ResourceHistoryChart({...@@ -445,11 +443,11 @@ function ResourceHistoryChart({
445 style={{ height: `${cpuHeight}%` }}443 style={{ height: `${cpuHeight}%` }}
446 />444 />
447 <span445 <span
448 className="block rounded-t-sm bg-sky-500/70"446 className="block rounded-t-sm bg-info/70"
449 style={{ height: `${readHeight}%` }}447 style={{ height: `${readHeight}%` }}
450 />448 />
451 <span449 <span
452 className="block rounded-t-sm bg-amber-500/80"450 className="block rounded-t-sm bg-warning/80"
453 style={{ height: `${writeHeight}%` }}451 style={{ height: `${writeHeight}%` }}
454 />452 />
455 </div>453 </div>
...@@ -632,10 +630,10 @@ function ProcessTable({...@@ -632,10 +630,10 @@ function ProcessTable({
632 <td className="px-3 py-2 text-right font-mono tabular-nums">630 <td className="px-3 py-2 text-right font-mono tabular-nums">
633 {formatBytes(process.residentBytes)}631 {formatBytes(process.residentBytes)}
634 </td>632 </td>
635 <td className="px-3 py-2 text-right font-mono tabular-nums text-sky-700 dark:text-sky-300">633 <td className="px-3 py-2 text-right font-mono tabular-nums text-info-foreground">
636 {formatRate(process.ioReadBytesPerSecond)}634 {formatRate(process.ioReadBytesPerSecond)}
637 </td>635 </td>
638 <td className="px-3 py-2 text-right font-mono tabular-nums text-amber-700 dark:text-amber-300">636 <td className="px-3 py-2 text-right font-mono tabular-nums text-warning-foreground">
639 {formatRate(process.ioWriteBytesPerSecond)}637 {formatRate(process.ioWriteBytesPerSecond)}
640 </td>638 </td>
641 <td className="px-3 py-2 text-right font-mono tabular-nums text-muted-foreground">639 <td className="px-3 py-2 text-right font-mono tabular-nums text-muted-foreground">
...@@ -740,10 +738,10 @@ function HistoryProcessTable({...@@ -740,10 +738,10 @@ function HistoryProcessTable({
740 <td className="px-3 py-2 text-right font-mono tabular-nums">738 <td className="px-3 py-2 text-right font-mono tabular-nums">
741 {formatBytes(process.peakRssBytes)}739 {formatBytes(process.peakRssBytes)}
742 </td>740 </td>
743 <td className="px-3 py-2 text-right font-mono tabular-nums text-sky-700 dark:text-sky-300">741 <td className="px-3 py-2 text-right font-mono tabular-nums text-info-foreground">
744 {formatBytes(process.ioReadBytes)}742 {formatBytes(process.ioReadBytes)}
745 </td>743 </td>
746 <td className="px-3 py-2 text-right font-mono tabular-nums text-amber-700 dark:text-amber-300">744 <td className="px-3 py-2 text-right font-mono tabular-nums text-warning-foreground">
747 {formatBytes(process.ioWriteBytes)}745 {formatBytes(process.ioWriteBytes)}
748 </td>746 </td>
749 <td className="px-3 py-2 text-right font-mono tabular-nums text-muted-foreground">747 <td className="px-3 py-2 text-right font-mono tabular-nums text-muted-foreground">
...@@ -797,10 +795,10 @@ function AttributionTable({ entries }: { entries: ReadonlyArray<ResourceAttribut...@@ -797,10 +795,10 @@ function AttributionTable({ entries }: { entries: ReadonlyArray<ResourceAttribut
797 {entry.component}795 {entry.component}
798 </td>796 </td>
799 <td className="truncate px-3 py-2 text-muted-foreground">{entry.operation}</td>797 <td className="truncate px-3 py-2 text-muted-foreground">{entry.operation}</td>
800 <td className="px-3 py-2 text-right font-mono tabular-nums text-sky-700 dark:text-sky-300">798 <td className="px-3 py-2 text-right font-mono tabular-nums text-info-foreground">
801 {formatBytes(entry.logicalReadBytes)}799 {formatBytes(entry.logicalReadBytes)}
802 </td>800 </td>
803 <td className="px-3 py-2 text-right font-mono tabular-nums text-amber-700 dark:text-amber-300">801 <td className="px-3 py-2 text-right font-mono tabular-nums text-warning-foreground">
804 {formatBytes(entry.logicalWriteBytes)}802 {formatBytes(entry.logicalWriteBytes)}
805 </td>803 </td>
806 <td className="px-3 py-2 text-right font-mono tabular-nums">{entry.count}</td>804 <td className="px-3 py-2 text-right font-mono tabular-nums">{entry.count}</td>
...@@ -997,7 +995,7 @@ export function ResourceTelemetryDiagnostics({...@@ -997,7 +995,7 @@ export function ResourceTelemetryDiagnostics({
997 </p>995 </p>
998 </div>996 </div>
999 <div className="flex items-center gap-2 text-[10px] text-muted-foreground/65">997 <div className="flex items-center gap-2 text-[10px] text-muted-foreground/65">
1000 <span className="size-1.5 rounded-full bg-emerald-500" />998 <span className="size-1.5 rounded-full bg-success" />
1001 Sampling every {snapshot ? formatSampleInterval(snapshot.sampleIntervalMs) : "..."}999 Sampling every {snapshot ? formatSampleInterval(snapshot.sampleIntervalMs) : "..."}
1002 </div>1000 </div>
1003 </div>1001 </div>
...@@ -1063,17 +1061,17 @@ export function ResourceTelemetryDiagnostics({...@@ -1063,17 +1061,17 @@ export function ResourceTelemetryDiagnostics({
1063 <div className="grid border-t border-border/60 bg-muted/10 md:grid-cols-3">1061 <div className="grid border-t border-border/60 bg-muted/10 md:grid-cols-3">
1064 <AggregateCard1062 <AggregateCard
1065 label="Backend + agents"1063 label="Backend + agents"
1066 accentClass="bg-emerald-500/80"1064 accentClass="bg-success/80"
1067 aggregate={snapshot.groups.backend}1065 aggregate={snapshot.groups.backend}
1068 />1066 />
1069 <AggregateCard1067 <AggregateCard
1070 label="Desktop"1068 label="Desktop"
1071 accentClass="bg-sky-500/80"1069 accentClass="bg-info/80"
1072 aggregate={snapshot.groups.electron}1070 aggregate={snapshot.groups.electron}
1073 />1071 />
1074 <AggregateCard1072 <AggregateCard
1075 label="Monitor overhead"1073 label="Monitor overhead"
1076 accentClass="bg-amber-500/80"1074 accentClass="bg-warning/80"
1077 aggregate={snapshot.groups.monitor}1075 aggregate={snapshot.groups.monitor}
1078 />1076 />
1079 </div>1077 </div>
...@@ -1186,7 +1184,7 @@ export function ResourceTelemetryDiagnostics({...@@ -1186,7 +1184,7 @@ export function ResourceTelemetryDiagnostics({
1186 value={String(snapshot.health.inaccessibleProcessCount)}1184 value={String(snapshot.health.inaccessibleProcessCount)}
1187 valueClassName={1185 valueClassName={
1188 snapshot.health.inaccessibleProcessCount > 01186 snapshot.health.inaccessibleProcessCount > 0
1189 ? "text-amber-600 dark:text-amber-300"1187 ? "text-warning-foreground"
1190 : undefined1188 : undefined
1191 }1189 }
1192 />1190 />
apps/web/src/components/settings/SnapShotSetupDialog.tsx+8-69
...@@ -5,7 +5,8 @@ import {...@@ -5,7 +5,8 @@ import {
5 type DesktopSnapShotSetupAction,5 type DesktopSnapShotSetupAction,
6 type DesktopSnapShotState,6 type DesktopSnapShotState,
7} from "@t3tools/contracts";7} from "@t3tools/contracts";
8import { useId, useState, type ReactNode } from "react";8import { useState, type ReactNode } from "react";
9import { MacAccessibilityIcon, MacScreenRecordingIcon } from "../Icons";
9import { CaptureShortcutConfig } from "./CaptureShortcutConfig";10import { CaptureShortcutConfig } from "./CaptureShortcutConfig";
10import { Button } from "../ui/button";11import { Button } from "../ui/button";
11import { Dialog, DialogDescription } from "../ui/dialog";12import { Dialog, DialogDescription } from "../ui/dialog";
...@@ -61,72 +62,6 @@ const GNOME_ACCESS_COPY = {...@@ -61,72 +62,6 @@ const GNOME_ACCESS_COPY = {
61 },62 },
62};63};
6364
64function ScreenRecordingIcon() {
65 const gradientId = useId();
66 return (
67 <svg
68 viewBox="0 0 32 32"
69 className="size-8 shrink-0 drop-shadow-[0_1px_1px_#0005]"
70 aria-hidden="true"
71 >
72 <defs>
73 <linearGradient id={gradientId} x2="0" y2="1">
74 <stop stopColor="#ff6972" />
75 <stop offset="1" stopColor="#ff2938" />
76 </linearGradient>
77 </defs>
78 <rect
79 x="0.5"
80 y="0.5"
81 width="31"
82 height="31"
83 rx="7"
84 fill={`url(#${gradientId})`}
85 stroke="#ffffff40"
86 />
87 <circle cx="16" cy="16" r="10" fill="none" stroke="#fff" strokeWidth="2" />
88 <circle cx="16" cy="16" r="4.5" fill="#fff" />
89 </svg>
90 );
91}
92
93function AccessibilityPermissionIcon() {
94 const gradientId = useId();
95 return (
96 <svg
97 viewBox="0 0 32 32"
98 className="size-8 shrink-0 drop-shadow-[0_1px_1px_#0005]"
99 aria-hidden="true"
100 >
101 <defs>
102 <linearGradient id={gradientId} x2="0" y2="1">
103 <stop stopColor="#48b6ff" />
104 <stop offset="1" stopColor="#0085ff" />
105 </linearGradient>
106 </defs>
107 <rect
108 x="0.5"
109 y="0.5"
110 width="31"
111 height="31"
112 rx="7"
113 fill={`url(#${gradientId})`}
114 stroke="#ffffff40"
115 />
116 <circle cx="16" cy="16" r="10" fill="none" stroke="#fff" strokeWidth="1.75" />
117 <circle cx="16" cy="10" r="1.6" fill="#fff" />
118 <path
119 d="m10 13 6 1 6-1M16 14v4m0 0-2.5 6m2.5-6 2.5 6"
120 fill="none"
121 stroke="#fff"
122 strokeWidth="1.6"
123 strokeLinecap="round"
124 strokeLinejoin="round"
125 />
126 </svg>
127 );
128}
129
130export function SnapShotSetupDialog({65export function SnapShotSetupDialog({
131 state,66 state,
132 initialStep,67 initialStep,
...@@ -333,7 +268,9 @@ export function SnapShotSetupDialog({...@@ -333,7 +268,9 @@ export function SnapShotSetupDialog({
333 permissions={[268 permissions={[
334 {269 {
335 id: "screenRecording",270 id: "screenRecording",
336 icon: <ScreenRecordingIcon />,271 icon: (
272 <MacScreenRecordingIcon className="size-8 shrink-0 drop-shadow-[0_1px_1px_#0005]" />
273 ),
337 title: "Screen Recording",274 title: "Screen Recording",
338 description: "Capture the window you're using.",275 description: "Capture the window you're using.",
339 granted: macPermissions.screenRecording,276 granted: macPermissions.screenRecording,
...@@ -341,7 +278,9 @@ export function SnapShotSetupDialog({...@@ -341,7 +278,9 @@ export function SnapShotSetupDialog({
341 },278 },
342 {279 {
343 id: "accessibility",280 id: "accessibility",
344 icon: <AccessibilityPermissionIcon />,281 icon: (
282 <MacAccessibilityIcon className="size-8 shrink-0 drop-shadow-[0_1px_1px_#0005]" />
283 ),
345 title: "Accessibility",284 title: "Accessibility",
346 description: includeAccessibility285 description: includeAccessibility
347 ? "Include text and controls from the captured app."286 ? "Include text and controls from the captured app."
apps/web/src/components/sidebar/DesktopUpdateStatusIcon.tsx+1-1
...@@ -67,7 +67,7 @@ function DesktopUpdateDownloadingIcon({ percent }: { readonly percent: number |...@@ -67,7 +67,7 @@ function DesktopUpdateDownloadingIcon({ percent }: { readonly percent: number |
67 cy="16"67 cy="16"
68 r={DOWNLOAD_PROGRESS_RADIUS}68 r={DOWNLOAD_PROGRESS_RADIUS}
69 fill="none"69 fill="none"
70 stroke="color-mix(in srgb, currentColor 22%, transparent)"70 className="stroke-current/22"
71 strokeWidth="1.5"71 strokeWidth="1.5"
72 />72 />
73 <circle73 <circle
apps/web/src/components/usage/UsagePage.tsx+1-1
...@@ -753,7 +753,7 @@ function UsageEnvironmentFilter({...@@ -753,7 +753,7 @@ function UsageEnvironmentFilter({
753 </>753 </>
754 ) : showUsageStatus && hasIssue ? (754 ) : showUsageStatus && hasIssue ? (
755 <CircleAlertIcon755 <CircleAlertIcon
756 className="size-3.5 text-amber-600 dark:text-amber-400"756 className="size-3.5 text-warning-foreground"
757 aria-label="Some environments could not report usage"757 aria-label="Some environments could not report usage"
758 />758 />
759 ) : (759 ) : (
apps/web/src/routes/_chat.pull-requests.tsx+1-1
...@@ -1819,7 +1819,7 @@ function PullRequestsRouteView() {...@@ -1819,7 +1819,7 @@ function PullRequestsRouteView() {
1819 )}1819 )}
18201820
1821 {listQuery.error && shownCount > 0 ? (1821 {listQuery.error && shownCount > 0 ? (
1822 <div className="flex items-center justify-between gap-3 rounded-lg border border-amber-500/30 bg-amber-500/5 px-3 py-2 text-xs">1822 <div className="flex items-center justify-between gap-3 rounded-lg border border-warning/30 bg-warning-surface px-3 py-2 text-xs">
1823 <span>{listQuery.error} Showing the last pull requests loaded.</span>1823 <span>{listQuery.error} Showing the last pull requests loaded.</span>
1824 <Button size="xs" variant="outline" onClick={() => listQuery.refresh()}>1824 <Button size="xs" variant="outline" onClick={() => listQuery.refresh()}>
1825 Retry1825 Retry
vite.config.ts+12
...@@ -203,6 +203,18 @@ export default defineConfig({...@@ -203,6 +203,18 @@ export default defineConfig({
203 files: ["apps/web/src/**"],203 files: ["apps/web/src/**"],
204 rules: { "shadcn/no-unknown-classes": "error" },204 rules: { "shadcn/no-unknown-classes": "error" },
205 },205 },
206 {
207 // Colors come from theme tokens so status tones follow custom themes. components/ui
208 // has no findings and stays covered too.
209 files: ["apps/web/src/**"],
210 rules: { "shadcn/no-raw-colors": "error" },
211 },
212 {
213 // Third-party marks (brand logos, the macOS permission panes, Codex's Computer Use
214 // mark) must keep their exact colors, so the files that hold them are exempt.
215 files: ["apps/web/src/components/Icons.tsx", "apps/web/src/components/JetBrainsIcons.tsx"],
216 rules: { "shadcn/no-raw-colors": "off" },
217 },
206 {218 {
207 // components/ui exports own their look. App code picks a variant or size instead219 // components/ui exports own their look. App code picks a variant or size instead
208 // of restyling with className; layout classes (width, flex, margin, position) stay220 // of restyling with className; layout classes (width, flex, margin, position) stay