authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-09-05 19:22:39-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-05 19:22:39-07:00
logb438447f67b6b61bbe6f564d8b78fd90702117c5
tree452b22de63e9976c1d13ce3f3bd8732c870fe16b
parenteee05575ebd514db36f61d7eb05d2258a10c96bd
signature Signed by PGP key B5690EEEBB952194

fix(mobile): use selected theme across input forms and controls (#10239)


27 files changed, 184 insertions(+), 116 deletions(-)

apps/mobile/generated-uniwind-default-theme-variables.json+6
...@@ -28,6 +28,9 @@...@@ -28,6 +28,9 @@
28 "--color-switch-active-thumb": "#ffffff",28 "--color-switch-active-thumb": "#ffffff",
29 "--color-switch-inactive-track": "rgba(0, 0, 0, 0.08)",29 "--color-switch-inactive-track": "rgba(0, 0, 0, 0.08)",
30 "--color-switch-inactive-thumb": "#8e8e93",30 "--color-switch-inactive-thumb": "#8e8e93",
31 "--color-warning": "#fffbeb",
32 "--color-warning-border": "#fde68a",
33 "--color-warning-foreground": "#b45309",
31 "--color-danger": "#fef2f2",34 "--color-danger": "#fef2f2",
32 "--color-danger-border": "rgba(239, 68, 68, 0.12)",35 "--color-danger-border": "rgba(239, 68, 68, 0.12)",
33 "--color-danger-foreground": "#dc2626",36 "--color-danger-foreground": "#dc2626",
...@@ -95,6 +98,9 @@...@@ -95,6 +98,9 @@
95 "--color-switch-active-thumb": "#ffffff",98 "--color-switch-active-thumb": "#ffffff",
96 "--color-switch-inactive-track": "rgba(255, 255, 255, 0.06)",99 "--color-switch-inactive-track": "rgba(255, 255, 255, 0.06)",
97 "--color-switch-inactive-thumb": "#8e8e93",100 "--color-switch-inactive-thumb": "#8e8e93",
101 "--color-warning": "rgba(69, 26, 3, 0.4)",
102 "--color-warning-border": "rgba(120, 53, 15, 0.6)",
103 "--color-warning-foreground": "#fcd34d",
98 "--color-danger": "rgba(239, 68, 68, 0.14)",104 "--color-danger": "rgba(239, 68, 68, 0.14)",
99 "--color-danger-border": "rgba(248, 113, 113, 0.18)",105 "--color-danger-border": "rgba(248, 113, 113, 0.18)",
100 "--color-danger-foreground": "#fca5a5",106 "--color-danger-foreground": "#fca5a5",
apps/mobile/generated-uniwind-themes.css+30
...@@ -150,6 +150,9 @@...@@ -150,6 +150,9 @@
150 --color-switch-active-thumb: #ffffff;150 --color-switch-active-thumb: #ffffff;
151 --color-switch-inactive-track: #f1c4e6;151 --color-switch-inactive-track: #f1c4e6;
152 --color-switch-inactive-thumb: #8d1255;152 --color-switch-inactive-thumb: #8d1255;
153 --color-warning: #fcf0ea;
154 --color-warning-border: rgba(245, 158, 11, 0.32);
155 --color-warning-foreground: #b05109;
153 --color-danger: #fde4f1;156 --color-danger: #fde4f1;
154 --color-danger-border: rgba(247, 8, 108, 0.32);157 --color-danger-border: rgba(247, 8, 108, 0.32);
155 --color-danger-foreground: #9d174d;158 --color-danger-foreground: #9d174d;
...@@ -275,6 +278,9 @@...@@ -275,6 +278,9 @@
275 --color-switch-active-thumb: #fbd0e8;278 --color-switch-active-thumb: #fbd0e8;
276 --color-switch-inactive-track: #362d3d;279 --color-switch-inactive-track: #362d3d;
277 --color-switch-inactive-thumb: #e7d0dd;280 --color-switch-inactive-thumb: #e7d0dd;
281 --color-warning: #412f20;
282 --color-warning-border: rgba(245, 158, 11, 0.32);
283 --color-warning-foreground: #fbbf24;
278 --color-danger: #331a2b;284 --color-danger: #331a2b;
279 --color-danger-border: rgba(157, 23, 77, 0.32);285 --color-danger-border: rgba(157, 23, 77, 0.32);
280 --color-danger-foreground: #fbd0e8;286 --color-danger-foreground: #fbd0e8;
...@@ -400,6 +406,9 @@...@@ -400,6 +406,9 @@
400 --color-switch-active-thumb: #fffaff;406 --color-switch-active-thumb: #fffaff;
401 --color-switch-inactive-track: #e2ede7;407 --color-switch-inactive-track: #e2ede7;
402 --color-switch-inactive-thumb: #6e696f;408 --color-switch-inactive-thumb: #6e696f;
409 --color-warning: #f4f0e1;
410 --color-warning-border: rgba(254, 154, 0, 0.32);
411 --color-warning-foreground: #b64a00;
403 --color-danger: #f4e7e5;412 --color-danger: #f4e7e5;
404 --color-danger-border: rgba(251, 44, 54, 0.32);413 --color-danger-border: rgba(251, 44, 54, 0.32);
405 --color-danger-foreground: #c10007;414 --color-danger-foreground: #c10007;
...@@ -525,6 +534,9 @@...@@ -525,6 +534,9 @@
525 --color-switch-active-thumb: #241523;534 --color-switch-active-thumb: #241523;
526 --color-switch-inactive-track: #2a4b39;535 --color-switch-inactive-track: #2a4b39;
527 --color-switch-inactive-thumb: #9da5a2;536 --color-switch-inactive-thumb: #9da5a2;
537 --color-warning: #3f3a1c;
538 --color-warning-border: rgba(254, 154, 0, 0.32);
539 --color-warning-foreground: #ffb900;
528 --color-danger: #3f2c28;540 --color-danger: #3f2c28;
529 --color-danger-border: rgba(251, 65, 74, 0.32);541 --color-danger-border: rgba(251, 65, 74, 0.32);
530 --color-danger-foreground: #ff6668;542 --color-danger-foreground: #ff6668;
...@@ -650,6 +662,9 @@...@@ -650,6 +662,9 @@
650 --color-switch-active-thumb: #fffaff;662 --color-switch-active-thumb: #fffaff;
651 --color-switch-inactive-track: #e4ecf2;663 --color-switch-inactive-track: #e4ecf2;
652 --color-switch-inactive-thumb: #6f6873;664 --color-switch-inactive-thumb: #6f6873;
665 --color-warning: #f6efe4;
666 --color-warning-border: rgba(254, 154, 0, 0.32);
667 --color-warning-foreground: #b74b00;
653 --color-danger: #f5e6e9;668 --color-danger: #f5e6e9;
654 --color-danger-border: rgba(251, 44, 54, 0.32);669 --color-danger-border: rgba(251, 44, 54, 0.32);
655 --color-danger-foreground: #c10007;670 --color-danger-foreground: #c10007;
...@@ -775,6 +790,9 @@...@@ -775,6 +790,9 @@
775 --color-switch-active-thumb: #241523;790 --color-switch-active-thumb: #241523;
776 --color-switch-inactive-track: #293f52;791 --color-switch-inactive-track: #293f52;
777 --color-switch-inactive-thumb: #969ca6;792 --color-switch-inactive-thumb: #969ca6;
793 --color-warning: #3c3424;
794 --color-warning-border: rgba(254, 154, 0, 0.32);
795 --color-warning-foreground: #ffb900;
778 --color-danger: #3c2630;796 --color-danger: #3c2630;
779 --color-danger-border: rgba(251, 65, 74, 0.32);797 --color-danger-border: rgba(251, 65, 74, 0.32);
780 --color-danger-foreground: #ff6467;798 --color-danger-foreground: #ff6467;
...@@ -900,6 +918,9 @@...@@ -900,6 +918,9 @@
900 --color-switch-active-thumb: #fffaff;918 --color-switch-active-thumb: #fffaff;
901 --color-switch-inactive-track: #f3eae5;919 --color-switch-inactive-track: #f3eae5;
902 --color-switch-inactive-thumb: #74686f;920 --color-switch-inactive-thumb: #74686f;
921 --color-warning: #f9efe2;
922 --color-warning-border: rgba(254, 154, 0, 0.32);
923 --color-warning-foreground: #b84b00;
903 --color-danger: #f9e7e6;924 --color-danger: #f9e7e6;
904 --color-danger-border: rgba(251, 44, 54, 0.32);925 --color-danger-border: rgba(251, 44, 54, 0.32);
905 --color-danger-foreground: #c10007;926 --color-danger-foreground: #c10007;
...@@ -1025,6 +1046,9 @@...@@ -1025,6 +1046,9 @@
1025 --color-switch-active-thumb: #241523;1046 --color-switch-active-thumb: #241523;
1026 --color-switch-inactive-track: #513728;1047 --color-switch-inactive-track: #513728;
1027 --color-switch-inactive-thumb: #a59996;1048 --color-switch-inactive-thumb: #a59996;
1049 --color-warning: #4b3215;
1050 --color-warning-border: rgba(254, 154, 0, 0.32);
1051 --color-warning-foreground: #ffb900;
1028 --color-danger: #4a2321;1052 --color-danger: #4a2321;
1029 --color-danger-border: rgba(251, 65, 74, 0.32);1053 --color-danger-border: rgba(251, 65, 74, 0.32);
1030 --color-danger-foreground: #ff6467;1054 --color-danger-foreground: #ff6467;
...@@ -1150,6 +1174,9 @@...@@ -1150,6 +1174,9 @@
1150 --color-switch-active-thumb: #fffaff;1174 --color-switch-active-thumb: #fffaff;
1151 --color-switch-inactive-track: #edeaf4;1175 --color-switch-inactive-track: #edeaf4;
1152 --color-switch-inactive-thumb: #726874;1176 --color-switch-inactive-thumb: #726874;
1177 --color-warning: #f8efe5;
1178 --color-warning-border: rgba(254, 154, 0, 0.32);
1179 --color-warning-foreground: #b84b00;
1153 --color-danger: #f8e6ea;1180 --color-danger: #f8e6ea;
1154 --color-danger-border: rgba(251, 44, 54, 0.32);1181 --color-danger-border: rgba(251, 44, 54, 0.32);
1155 --color-danger-foreground: #c10007;1182 --color-danger-foreground: #c10007;
...@@ -1275,6 +1302,9 @@...@@ -1275,6 +1302,9 @@
1275 --color-switch-active-thumb: #241523;1302 --color-switch-active-thumb: #241523;
1276 --color-switch-inactive-track: #362d51;1303 --color-switch-inactive-track: #362d51;
1277 --color-switch-inactive-thumb: #9690a1;1304 --color-switch-inactive-thumb: #9690a1;
1305 --color-warning: #412e23;
1306 --color-warning-border: rgba(254, 154, 0, 0.32);
1307 --color-warning-foreground: #ffb900;
1278 --color-danger: #40202e;1308 --color-danger: #40202e;
1279 --color-danger-border: rgba(251, 65, 74, 0.32);1309 --color-danger-border: rgba(251, 65, 74, 0.32);
1280 --color-danger-foreground: #ff6467;1310 --color-danger-foreground: #ff6467;
apps/mobile/global.css+10
...@@ -52,6 +52,11 @@...@@ -52,6 +52,11 @@
52 --color-switch-inactive-track: rgba(0, 0, 0, 0.08);52 --color-switch-inactive-track: rgba(0, 0, 0, 0.08);
53 --color-switch-inactive-thumb: #8e8e93;53 --color-switch-inactive-thumb: #8e8e93;
5454
55 /* Warning */
56 --color-warning: #fffbeb;
57 --color-warning-border: #fde68a;
58 --color-warning-foreground: #b45309;
59
55 /* Danger */60 /* Danger */
56 --color-danger: #fef2f2;61 --color-danger: #fef2f2;
57 --color-danger-border: rgba(239, 68, 68, 0.12);62 --color-danger-border: rgba(239, 68, 68, 0.12);
...@@ -151,6 +156,11 @@...@@ -151,6 +156,11 @@
151 --color-switch-inactive-track: rgba(255, 255, 255, 0.06);156 --color-switch-inactive-track: rgba(255, 255, 255, 0.06);
152 --color-switch-inactive-thumb: #8e8e93;157 --color-switch-inactive-thumb: #8e8e93;
153158
159 /* Warning */
160 --color-warning: rgba(69, 26, 3, 0.4);
161 --color-warning-border: rgba(120, 53, 15, 0.6);
162 --color-warning-foreground: #fcd34d;
163
154 /* Danger */164 /* Danger */
155 --color-danger: rgba(239, 68, 68, 0.14);165 --color-danger: rgba(239, 68, 68, 0.14);
156 --color-danger-border: rgba(248, 113, 113, 0.18);166 --color-danger-border: rgba(248, 113, 113, 0.18);
apps/mobile/src/components/AppText.tsx+2
...@@ -35,6 +35,8 @@ export function AppTextInput({ className, ref, ...props }: AppTextInputProps) {...@@ -35,6 +35,8 @@ export function AppTextInput({ className, ref, ...props }: AppTextInputProps) {
35 className,35 className,
36 )}36 )}
37 placeholderTextColorClassName="accent-placeholder"37 placeholderTextColorClassName="accent-placeholder"
38 selectionColorClassName="accent-foreground-secondary"
39 cursorColorClassName="accent-foreground-secondary"
38 {...props}40 {...props}
39 />41 />
40 );42 );
apps/mobile/src/components/ComposerAttachmentStrip.tsx+1-1
...@@ -195,7 +195,7 @@ function ComposerAttachmentContent(props: ComposerAttachmentThumbnailProps) {...@@ -195,7 +195,7 @@ function ComposerAttachmentContent(props: ComposerAttachmentThumbnailProps) {
195 <SymbolView195 <SymbolView
196 name="doc.text"196 name="doc.text"
197 size={props.compact ? 15 : 22}197 size={props.compact ? 15 : 22}
198 tintColor="#a3a3a3"198 tintColorClassName="accent-icon-subtle"
199 type="monochrome"199 type="monochrome"
200 />200 />
201 {!props.compact ? (201 {!props.compact ? (
apps/mobile/src/components/ErrorBanner.tsx+2-2
...@@ -3,8 +3,8 @@ import { View } from "react-native";...@@ -3,8 +3,8 @@ import { View } from "react-native";
3import { AppText as Text } from "./AppText";3import { AppText as Text } from "./AppText";
4export function ErrorBanner(props: { readonly message: string }) {4export function ErrorBanner(props: { readonly message: string }) {
5 return (5 return (
6 <View className="rounded-2xl border border-adaptive-rose-300-a70-400-a28 bg-adaptive-rose-100-a80-500-a12 px-3.5 py-3">6 <View className="rounded-2xl border border-danger-border bg-danger px-3.5 py-3">
7 <Text className="font-t3-medium text-sm text-adaptive-rose-700-300">{props.message}</Text>7 <Text className="font-t3-medium text-sm text-danger-foreground">{props.message}</Text>
8 </View>8 </View>
9 );9 );
10}10}
apps/mobile/src/features/connection/CloudEnvironmentRows.tsx+1-1
...@@ -299,7 +299,7 @@ function CloudEnvironmentRowShell(props: {...@@ -299,7 +299,7 @@ function CloudEnvironmentRowShell(props: {
299 traceId: props.connectionErrorTraceId,299 traceId: props.connectionErrorTraceId,
300 });300 });
301 const statusClassName = props.connectionError301 const statusClassName = props.connectionError
302 ? "text-adaptive-rose-500-400"302 ? "text-danger-foreground"
303 : "text-foreground-muted";303 : "text-foreground-muted";
304 const [errorMeasurement, setErrorMeasurement] = useState<{304 const [errorMeasurement, setErrorMeasurement] = useState<{
305 readonly text: string;305 readonly text: string;
apps/mobile/src/features/connection/ConnectionEnvironmentRow.tsx+1-1
...@@ -96,7 +96,7 @@ export function ConnectionEnvironmentRow(props: {...@@ -96,7 +96,7 @@ export function ConnectionEnvironmentRow(props: {
96 <Text96 <Text
97 className={cn(97 className={cn(
98 "text-xs",98 "text-xs",
99 hasConnectionFailure ? "text-adaptive-rose-500-400" : "text-foreground-muted",99 hasConnectionFailure ? "text-danger-foreground" : "text-foreground-muted",
100 )}100 )}
101 numberOfLines={props.expanded ? undefined : 1}101 numberOfLines={props.expanded ? undefined : 1}
102 selectable={props.expanded}102 selectable={props.expanded}
apps/mobile/src/features/connection/connectionTone.ts+10-10
...@@ -12,32 +12,32 @@ export function connectionTone(state: RemoteClientConnectionState): StatusTone {...@@ -12,32 +12,32 @@ export function connectionTone(state: RemoteClientConnectionState): StatusTone {
12 case "reconnecting":12 case "reconnecting":
13 return {13 return {
14 label: "Reconnecting",14 label: "Reconnecting",
15 pillClassName: "bg-adaptive-amber-500-a12-a16",15 pillClassName: "bg-warning",
16 textClassName: "text-adaptive-amber-700-300",16 textClassName: "text-warning-foreground",
17 };17 };
18 case "connecting":18 case "connecting":
19 return {19 return {
20 label: "Connecting",20 label: "Connecting",
21 pillClassName: "bg-adaptive-sky-500-a12-a16",21 pillClassName: "bg-primary/10",
22 textClassName: "text-adaptive-sky-700-300",22 textClassName: "text-foreground-secondary",
23 };23 };
24 case "error":24 case "error":
25 return {25 return {
26 label: "Connection failed",26 label: "Connection failed",
27 pillClassName: "bg-adaptive-rose-500-a12-a16",27 pillClassName: "bg-danger",
28 textClassName: "text-adaptive-rose-700-300",28 textClassName: "text-danger-foreground",
29 };29 };
30 case "offline":30 case "offline":
31 return {31 return {
32 label: "Offline",32 label: "Offline",
33 pillClassName: "bg-adaptive-rose-500-a12-a16",33 pillClassName: "bg-danger",
34 textClassName: "text-adaptive-rose-700-300",34 textClassName: "text-danger-foreground",
35 };35 };
36 case "available":36 case "available":
37 return {37 return {
38 label: "Available",38 label: "Available",
39 pillClassName: "bg-adaptive-neutral-500-a10-a16",39 pillClassName: "bg-subtle",
40 textClassName: "text-adaptive-neutral-600-300",40 textClassName: "text-foreground-secondary",
41 };41 };
42 }42 }
43}43}
apps/mobile/src/features/files/ThreadFilesRouteScreen.tsx+3-3
...@@ -190,11 +190,11 @@ function FileContent(props: {...@@ -190,11 +190,11 @@ function FileContent(props: {
190 return (190 return (
191 <View className="flex-1 bg-sheet">191 <View className="flex-1 bg-sheet">
192 {props.truncated ? (192 {props.truncated ? (
193 <View className="border-b border-adaptive-amber-200-900-a60 bg-adaptive-amber-50-950-a40 px-4 py-2">193 <View className="border-b border-warning-border bg-warning px-4 py-2">
194 <Text className="text-2xs font-t3-bold uppercase text-adaptive-amber-700-300">194 <Text className="text-2xs font-t3-bold uppercase text-warning-foreground">
195 Partial file195 Partial file
196 </Text>196 </Text>
197 <Text className="text-xs leading-snug text-adaptive-amber-800-200">197 <Text className="text-xs leading-snug text-warning-foreground">
198 Preview limited to the first 1 MB of a truncated file.198 Preview limited to the first 1 MB of a truncated file.
199 </Text>199 </Text>
200 </View>200 </View>
apps/mobile/src/features/home/thread-swipe-actions.tsx+25-8
...@@ -62,7 +62,7 @@ interface ThreadSwipeAction {...@@ -62,7 +62,7 @@ interface ThreadSwipeAction {
62}62}
6363
64interface ThreadSwipeSecondaryAction extends ThreadSwipeAction {64interface ThreadSwipeSecondaryAction extends ThreadSwipeAction {
65 readonly backgroundColor: string;65 readonly tone: "primary" | "secondary" | "danger";
66}66}
6767
68function swipeActionsWidth(hasSecondaryAction: boolean) {68function swipeActionsWidth(hasSecondaryAction: boolean) {
...@@ -80,7 +80,7 @@ function resolveSecondaryAction(input: {...@@ -80,7 +80,7 @@ function resolveSecondaryAction(input: {
80 if (input.secondaryAction === undefined) {80 if (input.secondaryAction === undefined) {
81 return {81 return {
82 accessibilityLabel: `Delete ${input.threadTitle}`,82 accessibilityLabel: `Delete ${input.threadTitle}`,
83 backgroundColor: "#ff2d55",83 tone: "danger",
84 icon: "trash",84 icon: "trash",
85 label: "Delete",85 label: "Delete",
86 onPress: () => {86 onPress: () => {
...@@ -92,7 +92,7 @@ function resolveSecondaryAction(input: {...@@ -92,7 +92,7 @@ function resolveSecondaryAction(input: {
92 const action = input.secondaryAction;92 const action = input.secondaryAction;
93 return {93 return {
94 ...action,94 ...action,
95 backgroundColor: "#5856d6",95 tone: "secondary",
96 menu:96 menu:
97 action.menu === undefined97 action.menu === undefined
98 ? undefined98 ? undefined
...@@ -359,7 +359,7 @@ export function ThreadSwipeable(props: {...@@ -359,7 +359,7 @@ export function ThreadSwipeable(props: {
359function SwipeActionButton(props: {359function SwipeActionButton(props: {
360 readonly accessibilityLabel: string;360 readonly accessibilityLabel: string;
361 readonly actionsWidth: number;361 readonly actionsWidth: number;
362 readonly backgroundColor: string;362 readonly tone: "primary" | "secondary" | "danger";
363 readonly compact: boolean;363 readonly compact: boolean;
364 readonly entryRange: readonly [number, number];364 readonly entryRange: readonly [number, number];
365 readonly fullSwipeThreshold: number;365 readonly fullSwipeThreshold: number;
...@@ -462,9 +462,15 @@ function SwipeActionButton(props: {...@@ -462,9 +462,15 @@ function SwipeActionButton(props: {
462 >462 >
463 <View style={{ height: circleSize, width: circleSize }}>463 <View style={{ height: circleSize, width: circleSize }}>
464 <Animated.View464 <Animated.View
465 className={
466 props.tone === "danger"
467 ? "bg-danger"
468 : props.tone === "secondary"
469 ? "bg-secondary"
470 : "bg-primary"
471 }
465 style={[472 style={[
466 {473 {
467 backgroundColor: props.backgroundColor,
468 borderRadius: 999,474 borderRadius: 999,
469 height: circleSize,475 height: circleSize,
470 left: 0,476 left: 0,
...@@ -488,7 +494,18 @@ function SwipeActionButton(props: {...@@ -488,7 +494,18 @@ function SwipeActionButton(props: {
488 iconStyle,494 iconStyle,
489 ]}495 ]}
490 >496 >
491 <SymbolView name={props.icon} size={iconSize} tintColor="#ffffff" type="monochrome" />497 <SymbolView
498 name={props.icon}
499 size={iconSize}
500 tintColorClassName={
501 props.tone === "danger"
502 ? "accent-danger-foreground"
503 : props.tone === "secondary"
504 ? "accent-secondary-foreground"
505 : "accent-primary-foreground"
506 }
507 type="monochrome"
508 />
492 </Animated.View>509 </Animated.View>
493 </View>510 </View>
494 <Animated.View511 <Animated.View
...@@ -568,7 +585,7 @@ export function ThreadSwipeActions(props: {...@@ -568,7 +585,7 @@ export function ThreadSwipeActions(props: {
568 <SwipeActionButton585 <SwipeActionButton
569 accessibilityLabel={props.primaryAction.accessibilityLabel}586 accessibilityLabel={props.primaryAction.accessibilityLabel}
570 actionsWidth={actionsWidth}587 actionsWidth={actionsWidth}
571 backgroundColor="#007aff"588 tone="primary"
572 compact={props.compact}589 compact={props.compact}
573 entryRange={590 entryRange={
574 secondaryAction === null591 secondaryAction === null
...@@ -586,7 +603,7 @@ export function ThreadSwipeActions(props: {...@@ -586,7 +603,7 @@ export function ThreadSwipeActions(props: {
586 <SwipeActionButton603 <SwipeActionButton
587 accessibilityLabel={secondaryAction.accessibilityLabel}604 accessibilityLabel={secondaryAction.accessibilityLabel}
588 actionsWidth={actionsWidth}605 actionsWidth={actionsWidth}
589 backgroundColor={secondaryAction.backgroundColor}606 tone={secondaryAction.tone}
590 compact={props.compact}607 compact={props.compact}
591 entryRange={[8, ACTION_ITEM_WIDTH * 0.72]}608 entryRange={[8, ACTION_ITEM_WIDTH * 0.72]}
592 fullSwipeThreshold={props.fullSwipeThreshold}609 fullSwipeThreshold={props.fullSwipeThreshold}
apps/mobile/src/features/review/ReviewSheet.tsx+3-5
...@@ -80,11 +80,9 @@ const SHOWCASE_ENABLED = process.env.EXPO_PUBLIC_SHOWCASE === "1";...@@ -80,11 +80,9 @@ const SHOWCASE_ENABLED = process.env.EXPO_PUBLIC_SHOWCASE === "1";
8080
81const ReviewNotice = memo(function ReviewNotice(props: { readonly notice: string }) {81const ReviewNotice = memo(function ReviewNotice(props: { readonly notice: string }) {
82 return (82 return (
83 <View className="border-b border-adaptive-amber-200-900-a60 bg-adaptive-amber-50-950-a40 px-4 py-3">83 <View className="border-b border-warning-border bg-warning px-4 py-3">
84 <Text className="text-xs font-t3-bold uppercase text-adaptive-amber-700-300">84 <Text className="text-xs font-t3-bold uppercase text-warning-foreground">Partial diff</Text>
85 Partial diff85 <Text className="text-xs leading-normal text-warning-foreground">{props.notice}</Text>
86 </Text>
87 <Text className="text-xs leading-normal text-adaptive-amber-800-200">{props.notice}</Text>
88 </View>86 </View>
89 );87 );
90});88});
apps/mobile/src/features/settings/appearance/components/FontSizeSliderRow.tsx+1-2
...@@ -176,10 +176,9 @@ export function FontSizeSliderRow(props: {...@@ -176,10 +176,9 @@ export function FontSizeSliderRow(props: {
176 />176 />
177 </View>177 </View>
178 <Animated.View178 <Animated.View
179 className="absolute left-0 rounded-full bg-white"179 className="absolute left-0 rounded-full border-border bg-primary-foreground"
180 style={[180 style={[
181 {181 {
182 borderColor: "rgba(0, 0, 0, 0.06)",
183 borderWidth: 1,182 borderWidth: 1,
184 height: THUMB_SIZE,183 height: THUMB_SIZE,
185 marginTop: -THUMB_SIZE / 2,184 marginTop: -THUMB_SIZE / 2,
apps/mobile/src/features/threads/GitActionProgressOverlay.tsx+3-5
...@@ -143,9 +143,7 @@ function OverlayContent(props: { readonly progress: GitActionProgress }) {...@@ -143,9 +143,7 @@ function OverlayContent(props: { readonly progress: GitActionProgress }) {
143 }143 }
144144
145 const bgClass =145 const bgClass =
146 progress.phase === "error"146 progress.phase === "error" ? "border-danger-border bg-danger" : "bg-card border-border";
147 ? "border-adaptive-red-200-800 bg-adaptive-red-50-950-a80"
148 : "bg-card border-border";
149147
150 return (148 return (
151 <Animated.View149 <Animated.View
...@@ -169,11 +167,11 @@ function OverlayIcon(props: { readonly phase: GitActionProgress["phase"] }) {...@@ -169,11 +167,11 @@ function OverlayIcon(props: { readonly phase: GitActionProgress["phase"] }) {
169 );167 );
170 case "error":168 case "error":
171 return (169 return (
172 <View className="h-6 w-6 items-center justify-center rounded-full bg-red-500">170 <View className="h-6 w-6 items-center justify-center rounded-full bg-danger">
173 <SymbolView171 <SymbolView
174 name="exclamationmark.triangle"172 name="exclamationmark.triangle"
175 size={12}173 size={12}
176 tintColor="white"174 tintColorClassName="accent-danger-foreground"
177 type="monochrome"175 type="monochrome"
178 />176 />
179 </View>177 </View>
apps/mobile/src/features/threads/PendingApprovalCard.tsx+11-13
...@@ -30,22 +30,20 @@ export function PendingApprovalCard(props: PendingApprovalCardProps) {...@@ -30,22 +30,20 @@ export function PendingApprovalCard(props: PendingApprovalCardProps) {
30 // Opaque for the same reason as PendingUserInputCard: nothing blurs the feed30 // Opaque for the same reason as PendingUserInputCard: nothing blurs the feed
31 // behind this card, so a translucent surface bleeds messages through it.31 // behind this card, so a translucent surface bleeds messages through it.
32 return (32 return (
33 <View className="gap-2.5 rounded-[20px] border border-adaptive-neutral-200-white-a6 bg-adaptive-neutral-100-900 p-4">33 <View className="gap-2.5 rounded-[20px] border border-border bg-card-alt p-4">
34 <Text className="font-t3-bold text-2xs uppercase tracking-[1.1px] text-adaptive-sky-700-300">34 <Text className="font-t3-bold text-2xs uppercase tracking-[1.1px] text-foreground-secondary">
35 Approval needed35 Approval needed
36 </Text>36 </Text>
37 <Text className="font-t3-bold text-lg text-adaptive-neutral-950-50">37 <Text className="font-t3-bold text-lg text-foreground">
38 {props.approval.appName ?? props.approval.requestKind}38 {props.approval.appName ?? props.approval.requestKind}
39 </Text>39 </Text>
40 {props.approval.detail ? (40 {props.approval.detail ? (
41 <Text className="font-sans text-sm leading-normal text-adaptive-neutral-600-400">41 <Text className="font-sans text-sm leading-normal text-foreground-secondary">
42 {props.approval.detail}42 {props.approval.detail}
43 </Text>43 </Text>
44 ) : null}44 ) : null}
45 {warning ? (45 {warning ? (
46 <Text className="font-sans text-xs leading-normal text-adaptive-amber-700-300">46 <Text className="font-sans text-xs leading-normal text-warning-foreground">{warning}</Text>
47 {warning}
48 </Text>
49 ) : null}47 ) : null}
50 <View className="flex-row flex-wrap gap-2.5">48 <View className="flex-row flex-wrap gap-2.5">
51 {options.map((option) => (49 {options.map((option) => (
...@@ -53,10 +51,10 @@ export function PendingApprovalCard(props: PendingApprovalCardProps) {...@@ -53,10 +51,10 @@ export function PendingApprovalCard(props: PendingApprovalCardProps) {
53 key={option.decision}51 key={option.decision}
54 className={`items-center justify-center rounded-[14px] px-3.5 py-3 ${52 className={`items-center justify-center rounded-[14px] px-3.5 py-3 ${
55 option.decision === "accept"53 option.decision === "accept"
56 ? "bg-blue-500"54 ? "bg-primary"
57 : option.decision === "decline"55 : option.decision === "decline"
58 ? "bg-adaptive-rose-100-500-a18"56 ? "bg-danger"
59 : "bg-adaptive-neutral-200-800"57 : "bg-subtle-strong"
60 }`}58 }`}
61 disabled={props.respondingApprovalId === props.approval.requestId}59 disabled={props.respondingApprovalId === props.approval.requestId}
62 onPress={() => void props.onRespond(props.approval.requestId, option.decision)}60 onPress={() => void props.onRespond(props.approval.requestId, option.decision)}
...@@ -64,10 +62,10 @@ export function PendingApprovalCard(props: PendingApprovalCardProps) {...@@ -64,10 +62,10 @@ export function PendingApprovalCard(props: PendingApprovalCardProps) {
64 <Text62 <Text
65 className={`text-sm ${63 className={`text-sm ${
66 option.decision === "accept"64 option.decision === "accept"
67 ? "font-t3-extrabold text-white"65 ? "font-t3-extrabold text-primary-foreground"
68 : option.decision === "decline"66 : option.decision === "decline"
69 ? "font-t3-bold text-adaptive-rose-700-300"67 ? "font-t3-bold text-danger-foreground"
70 : "font-t3-bold text-adaptive-neutral-950-50"68 : "font-t3-bold text-foreground"
71 }`}69 }`}
72 >70 >
73 {option.label}71 {option.label}
apps/mobile/src/features/threads/PendingUserInputCard.tsx+22-21
...@@ -161,7 +161,7 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) {...@@ -161,7 +161,7 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) {
161 pointerEvents={props.collapsed ? "auto" : "none"}161 pointerEvents={props.collapsed ? "auto" : "none"}
162 accessibilityElementsHidden={!props.collapsed}162 accessibilityElementsHidden={!props.collapsed}
163 importantForAccessibility={props.collapsed ? "auto" : "no-hide-descendants"}163 importantForAccessibility={props.collapsed ? "auto" : "no-hide-descendants"}
164 className="flex-row items-center gap-2 rounded-full border border-adaptive-neutral-200-white-a6 bg-adaptive-neutral-100-900 py-1.5 pl-4 pr-1.5"164 className="flex-row items-center gap-2 rounded-full border border-border bg-card-alt py-1.5 pl-4 pr-1.5"
165 >165 >
166 <Pressable166 <Pressable
167 accessibilityRole="button"167 accessibilityRole="button"
...@@ -171,10 +171,10 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) {...@@ -171,10 +171,10 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) {
171 onPress={props.onToggleCollapsed}171 onPress={props.onToggleCollapsed}
172 className="min-h-10 flex-1 flex-row items-center gap-2 active:opacity-70"172 className="min-h-10 flex-1 flex-row items-center gap-2 active:opacity-70"
173 >173 >
174 <Text className="font-t3-bold text-2xs uppercase tracking-[1.1px] text-adaptive-sky-700-300">174 <Text className="font-t3-bold text-2xs uppercase tracking-[1.1px] text-foreground-secondary">
175 User input needed175 User input needed
176 </Text>176 </Text>
177 <Text className="font-sans text-xs text-adaptive-neutral-500-400">177 <Text className="font-sans text-xs text-foreground-muted">
178 {questionCount} question{questionCount === 1 ? "" : "s"}178 {questionCount} question{questionCount === 1 ? "" : "s"}
179 </Text>179 </Text>
180 <View className="flex-1" />180 <View className="flex-1" />
...@@ -216,7 +216,7 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) {...@@ -216,7 +216,7 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) {
216 : FadeOutDown.duration(USER_INPUT_TOGGLE_DURATION_MS).easing(Easing.out(Easing.cubic))216 : FadeOutDown.duration(USER_INPUT_TOGGLE_DURATION_MS).easing(Easing.out(Easing.cubic))
217 }217 }
218 layout={CARD_LAYOUT_TRANSITION}218 layout={CARD_LAYOUT_TRANSITION}
219 className="overflow-hidden gap-2.5 rounded-[20px] border border-adaptive-neutral-200-white-a6 bg-adaptive-neutral-100-900 p-4"219 className="overflow-hidden gap-2.5 rounded-[20px] border border-border bg-card-alt p-4"
220 style={220 style={
221 EXPANDED_CARD_IS_OVERLAY221 EXPANDED_CARD_IS_OVERLAY
222 ? [{ maxHeight: props.maxHeight }, cardAnimatedStyle]222 ? [{ maxHeight: props.maxHeight }, cardAnimatedStyle]
...@@ -230,14 +230,12 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) {...@@ -230,14 +230,12 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) {
230 className="flex-row items-start gap-2"230 className="flex-row items-start gap-2"
231 >231 >
232 <View className="flex-1 gap-2.5">232 <View className="flex-1 gap-2.5">
233 <Text className="font-t3-bold text-2xs uppercase tracking-[1.1px] text-adaptive-sky-700-300">233 <Text className="font-t3-bold text-2xs uppercase tracking-[1.1px] text-foreground-secondary">
234 User input needed234 User input needed
235 </Text>235 </Text>
236 <Text className="font-t3-bold text-lg text-adaptive-neutral-950-50">236 <Text className="font-t3-bold text-lg text-foreground">Fill in the pending answers</Text>
237 Fill in the pending answers
238 </Text>
239 </View>237 </View>
240 <View className="h-8 w-8 items-center justify-center rounded-full bg-adaptive-neutral-200-a70-white-a8">238 <View className="h-8 w-8 items-center justify-center rounded-full bg-subtle-strong">
241 <SymbolView239 <SymbolView
242 name="chevron.down"240 name="chevron.down"
243 size={13}241 size={13}
...@@ -259,10 +257,10 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) {...@@ -259,10 +257,10 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) {
259 const draft = props.drafts[question.id];257 const draft = props.drafts[question.id];
260 return (258 return (
261 <View key={question.id} className="gap-2 pt-1">259 <View key={question.id} className="gap-2 pt-1">
262 <Text className="font-t3-bold text-xs uppercase tracking-[1px] text-neutral-500">260 <Text className="font-t3-bold text-xs uppercase tracking-[1px] text-foreground-muted">
263 {question.header}261 {question.header}
264 </Text>262 </Text>
265 <Text className="font-sans text-base leading-snug text-adaptive-neutral-950-50">263 <Text className="font-sans text-base leading-snug text-foreground">
266 {question.question}264 {question.question}
267 </Text>265 </Text>
268 <View className="gap-2">266 <View className="gap-2">
...@@ -276,9 +274,7 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) {...@@ -276,9 +274,7 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) {
276 key={optionValue}274 key={optionValue}
277 className={cn(275 className={cn(
278 "min-h-12 w-full rounded-2xl border px-3.5 py-3",276 "min-h-12 w-full rounded-2xl border px-3.5 py-3",
279 selected277 selected ? "border-primary bg-primary/10" : "border-border bg-input",
280 ? "border-adaptive-blue-300-a50-blue-400-a28 bg-adaptive-blue-50-blue-400-a14"
281 : "border-adaptive-neutral-200-white-a6 bg-adaptive-white-neutral-950-a70",
282 )}278 )}
283 onPress={() =>279 onPress={() =>
284 props.onSelectOption(280 props.onSelectOption(
...@@ -292,15 +288,13 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) {...@@ -292,15 +288,13 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) {
292 <Text288 <Text
293 className={cn(289 className={cn(
294 "font-t3-bold text-sm",290 "font-t3-bold text-sm",
295 selected291 selected ? "text-foreground" : "text-foreground-secondary",
296 ? "text-adaptive-sky-700-300"
297 : "text-adaptive-neutral-600-300",
298 )}292 )}
299 >293 >
300 {option.label}294 {option.label}
301 </Text>295 </Text>
302 {description ? (296 {description ? (
303 <Text className="font-sans text-sm leading-5 text-adaptive-neutral-500-400">297 <Text className="font-sans text-sm leading-5 text-foreground-muted">
304 {description}298 {description}
305 </Text>299 </Text>
306 ) : null}300 ) : null}
...@@ -318,7 +312,7 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) {...@@ -318,7 +312,7 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) {
318 onFocus={() => props.onInputFocusChange?.(true)}312 onFocus={() => props.onInputFocusChange?.(true)}
319 onBlur={() => props.onInputFocusChange?.(false)}313 onBlur={() => props.onInputFocusChange?.(false)}
320 placeholder="Or type a custom answer"314 placeholder="Or type a custom answer"
321 className="min-h-[54px] rounded-2xl border border-adaptive-neutral-200-white-a8 bg-adaptive-white-neutral-950-a70 px-3.5 py-3 font-sans text-base text-adaptive-neutral-950-50"315 className="min-h-[54px] rounded-2xl border border-input-border bg-input px-3.5 py-3 font-sans text-base text-foreground"
322 />316 />
323 ) : null}317 ) : null}
324 </View>318 </View>
...@@ -328,14 +322,21 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) {...@@ -328,14 +322,21 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) {
328 <Pressable322 <Pressable
329 className={cn(323 className={cn(
330 "items-center justify-center rounded-2xl px-4 py-3.5",324 "items-center justify-center rounded-2xl px-4 py-3.5",
331 props.answers ? "bg-blue-500" : "bg-adaptive-neutral-200-700-a60",325 props.answers ? "bg-primary" : "bg-subtle-strong",
332 )}326 )}
333 disabled={327 disabled={
334 props.answers === null || props.respondingUserInputId === props.pendingUserInput.requestId328 props.answers === null || props.respondingUserInputId === props.pendingUserInput.requestId
335 }329 }
336 onPress={() => void props.onSubmit()}330 onPress={() => void props.onSubmit()}
337 >331 >
338 <Text className="font-t3-extrabold text-sm text-white">Submit answers</Text>332 <Text
333 className={cn(
334 "font-t3-extrabold text-sm",
335 props.answers ? "text-primary-foreground" : "text-foreground-muted",
336 )}
337 >
338 Submit answers
339 </Text>
339 </Pressable>340 </Pressable>
340 </Animated.View>341 </Animated.View>
341 ) : null;342 ) : null;
apps/mobile/src/features/threads/ThreadFeed.tsx+12-7
...@@ -504,7 +504,12 @@ function MessageAttachmentFile(props: {...@@ -504,7 +504,12 @@ function MessageAttachmentFile(props: {
504function MessageAttachmentUnknown(props: { readonly name: string }) {504function MessageAttachmentUnknown(props: { readonly name: string }) {
505 return (505 return (
506 <View className="flex-row items-center gap-2 py-1">506 <View className="flex-row items-center gap-2 py-1">
507 <SymbolView name="doc.text" size={16} tintColor="#a3a3a3" type="monochrome" />507 <SymbolView
508 name="doc.text"
509 size={16}
510 tintColorClassName="accent-icon-subtle"
511 type="monochrome"
512 />
508 <Text className="min-w-0 flex-1 text-sm text-foreground" numberOfLines={1}>513 <Text className="min-w-0 flex-1 text-sm text-foreground" numberOfLines={1}>
509 {props.name}514 {props.name}
510 </Text>515 </Text>
...@@ -1352,7 +1357,7 @@ function renderFeedEntry(...@@ -1352,7 +1357,7 @@ function renderFeedEntry(
1352 accessibilityState={{ expanded: entry.expanded }}1357 accessibilityState={{ expanded: entry.expanded }}
1353 onPress={() => props.onToggleTurnFold(entry.turnId)}1358 onPress={() => props.onToggleTurnFold(entry.turnId)}
1354 hitSlop={4}1359 hitSlop={4}
1355 className="mb-1 min-h-11 flex-row items-center gap-2 border-b border-adaptive-neutral-200-a80-white-a8 px-2"1360 className="mb-1 min-h-11 flex-row items-center gap-2 border-b border-border px-2"
1356 style={{1361 style={{
1357 minHeight: Math.max(TURN_FOLD_HEIGHT - 3.5, props.workRowSizing.estimatedRowHeight),1362 minHeight: Math.max(TURN_FOLD_HEIGHT - 3.5, props.workRowSizing.estimatedRowHeight),
1358 }}1363 }}
...@@ -1406,7 +1411,7 @@ function renderFeedEntry(...@@ -1406,7 +1411,7 @@ function renderFeedEntry(
1406 accessibilityLabel={label}1411 accessibilityLabel={label}
1407 className="mb-3 flex-row items-center gap-3 px-1 py-1"1412 className="mb-3 flex-row items-center gap-3 px-1 py-1"
1408 >1413 >
1409 <View className="h-px flex-1 bg-adaptive-neutral-200-a80-white-a8" />1414 <View className="h-px flex-1 bg-border" />
1410 <View className="shrink-0 flex-row items-center gap-1.5">1415 <View className="shrink-0 flex-row items-center gap-1.5">
1411 <SymbolView1416 <SymbolView
1412 name="arrow.down.right.and.arrow.up.left"1417 name="arrow.down.right.and.arrow.up.left"
...@@ -1416,7 +1421,7 @@ function renderFeedEntry(...@@ -1416,7 +1421,7 @@ function renderFeedEntry(
1416 />1421 />
1417 <Text className="font-t3-medium text-xs text-foreground-muted">{label}</Text>1422 <Text className="font-t3-medium text-xs text-foreground-muted">{label}</Text>
1418 </View>1423 </View>
1419 <View className="h-px flex-1 bg-adaptive-neutral-200-a80-white-a8" />1424 <View className="h-px flex-1 bg-border" />
1420 </View>1425 </View>
1421 );1426 );
1422 }1427 }
...@@ -1503,7 +1508,7 @@ function renderFeedEntry(...@@ -1503,7 +1508,7 @@ function renderFeedEntry(
1503 })}1508 })}
1504 </View>1509 </View>
1505 <View className="mt-1 flex-row items-center justify-end gap-1 pr-0.5">1510 <View className="mt-1 flex-row items-center justify-end gap-1 pr-0.5">
1506 <Text className="font-t3-medium text-xs tabular-nums text-adaptive-neutral-600-400">1511 <Text className="font-t3-medium text-xs tabular-nums text-foreground-secondary">
1507 {timestampLabel}1512 {timestampLabel}
1508 </Text>1513 </Text>
1509 {message.text.trim().length > 0 ? (1514 {message.text.trim().length > 0 ? (
...@@ -1552,7 +1557,7 @@ function renderFeedEntry(...@@ -1552,7 +1557,7 @@ function renderFeedEntry(
1552 attachmentId={attachment.id}1557 attachmentId={attachment.id}
1553 name={attachment.name}1558 name={attachment.name}
1554 mimeType={attachment.mimeType}1559 mimeType={attachment.mimeType}
1555 className="mt-1.5 aspect-[1.3] w-full rounded-[18px] bg-adaptive-neutral-200-800"1560 className="mt-1.5 aspect-[1.3] w-full rounded-[18px] bg-subtle-strong"
1556 onPressPreview={props.onPressPreview}1561 onPressPreview={props.onPressPreview}
1557 />1562 />
1558 ) : isFileAttachment(attachment) ? (1563 ) : isFileAttachment(attachment) ? (
...@@ -1576,7 +1581,7 @@ function renderFeedEntry(...@@ -1576,7 +1581,7 @@ function renderFeedEntry(
1576 buttonSize={28}1581 buttonSize={28}
1577 iconSize={13}1582 iconSize={13}
1578 />1583 />
1579 <Text className="font-t3-medium text-xs tabular-nums text-adaptive-neutral-600-400">1584 <Text className="font-t3-medium text-xs tabular-nums text-foreground-secondary">
1580 {timestampLabel}1585 {timestampLabel}
1581 </Text>1586 </Text>
1582 </View>1587 </View>
apps/mobile/src/features/threads/git/GitCommitSheet.tsx+1-1
...@@ -85,7 +85,7 @@ export function GitCommitSheet(_props: GitCommitSheetProps) {...@@ -85,7 +85,7 @@ export function GitCommitSheet(_props: GitCommitSheetProps) {
85 </Text>85 </Text>
86 </View>86 </View>
87 {isDefaultRef ? (87 {isDefaultRef ? (
88 <Text className="text-xs leading-normal text-adaptive-amber-700-400">88 <Text className="text-xs leading-normal text-warning-foreground">
89 Warning: this is the default branch.89 Warning: this is the default branch.
90 </Text>90 </Text>
91 ) : null}91 ) : null}
apps/mobile/src/features/threads/thread-list-items.tsx+2-2
...@@ -297,8 +297,8 @@ export const PendingTaskListRow = memo(function PendingTaskListRow(props: {...@@ -297,8 +297,8 @@ export const PendingTaskListRow = memo(function PendingTaskListRow(props: {
297 );297 );
298298
299 const statusPill = (299 const statusPill = (
300 <View className="rounded-full bg-adaptive-zinc-500-a12-a16 px-1.5 py-0.5">300 <View className="rounded-full bg-subtle px-1.5 py-0.5">
301 <Text className="text-3xs font-t3-bold text-adaptive-zinc-600-300">Pending</Text>301 <Text className="text-3xs font-t3-bold text-foreground-muted">Pending</Text>
302 </View>302 </View>
303 );303 );
304304
apps/mobile/src/features/threads/thread-list-v2-items.tsx+9-14
...@@ -23,7 +23,6 @@ import { useUniwindTheme } from "../../lib/useUniwindTheme";...@@ -23,7 +23,6 @@ import { useUniwindTheme } from "../../lib/useUniwindTheme";
23import type { PendingNewTask } from "../../state/use-pending-new-tasks";23import type { PendingNewTask } from "../../state/use-pending-new-tasks";
24import { useThreadPr } from "../../state/use-thread-pr";24import { useThreadPr } from "../../state/use-thread-pr";
25import { ThreadSwipeable } from "../home/thread-swipe-actions";25import { ThreadSwipeable } from "../home/thread-swipe-actions";
26import { useAppearancePreferences } from "../settings/appearance/AppearancePreferencesProvider";
27import { buildThreadTitleRegenerationMenuItems } from "./thread-title-regeneration-menu";26import { buildThreadTitleRegenerationMenuItems } from "./thread-title-regeneration-menu";
28import {27import {
29 resolveThreadListV2SnoozeMenuSelection,28 resolveThreadListV2SnoozeMenuSelection,
...@@ -53,10 +52,10 @@ const MONO_FONT = Platform.select({...@@ -53,10 +52,10 @@ const MONO_FONT = Platform.select({
53const STATUS_LABEL_BY_STATUS: Partial<52const STATUS_LABEL_BY_STATUS: Partial<
54 Record<ThreadListV2Status, { label: string; className: string }>53 Record<ThreadListV2Status, { label: string; className: string }>
55> = {54> = {
56 approval: { label: "Approval", className: "text-adaptive-amber-700-300" },55 approval: { label: "Approval", className: "text-warning-foreground" },
57 input: { label: "Input", className: "text-adaptive-indigo-600-300" },56 input: { label: "Input", className: "text-foreground-secondary" },
58 working: { label: "Working", className: "text-adaptive-sky-600-400" },57 working: { label: "Working", className: "text-foreground-secondary" },
59 failed: { label: "Failed", className: "text-adaptive-red-700-300" },58 failed: { label: "Failed", className: "text-danger-foreground" },
60};59};
6160
62function threadTimeLabel(thread: EnvironmentThreadShell): string {61function threadTimeLabel(thread: EnvironmentThreadShell): string {
...@@ -107,9 +106,6 @@ export const ThreadListV2SectionDivider = memo(function ThreadListV2SectionDivid...@@ -107,9 +106,6 @@ export const ThreadListV2SectionDivider = memo(function ThreadListV2SectionDivid
107 );106 );
108});107});
109108
110const SNOOZE_ACCENT_LIGHT = "#2563eb";
111const SNOOZE_ACCENT_DARK = "#60a5fa";
112
113export const ThreadListV2SnoozedShelfHeader = memo(function ThreadListV2SnoozedShelfHeader(props: {109export const ThreadListV2SnoozedShelfHeader = memo(function ThreadListV2SnoozedShelfHeader(props: {
114 readonly count: number;110 readonly count: number;
115 readonly disabled?: boolean;111 readonly disabled?: boolean;
...@@ -117,7 +113,6 @@ export const ThreadListV2SnoozedShelfHeader = memo(function ThreadListV2SnoozedS...@@ -117,7 +113,6 @@ export const ThreadListV2SnoozedShelfHeader = memo(function ThreadListV2SnoozedS
117 readonly onToggle: () => void;113 readonly onToggle: () => void;
118 readonly pane?: "screen" | "sidebar";114 readonly pane?: "screen" | "sidebar";
119}) {115}) {
120 const { themeAppearance: colorScheme } = useAppearancePreferences();
121 return (116 return (
122 <Pressable117 <Pressable
123 accessibilityHint={118 accessibilityHint={
...@@ -134,14 +129,14 @@ export const ThreadListV2SnoozedShelfHeader = memo(function ThreadListV2SnoozedS...@@ -134,14 +129,14 @@ export const ThreadListV2SnoozedShelfHeader = memo(function ThreadListV2SnoozedS
134 onPress={props.onToggle}129 onPress={props.onToggle}
135 style={({ pressed }) => ({ opacity: pressed ? 0.6 : 1 })}130 style={({ pressed }) => ({ opacity: pressed ? 0.6 : 1 })}
136 >131 >
137 <Text className="text-xs font-t3-medium text-adaptive-blue-600-400">132 <Text className="text-xs font-t3-medium text-foreground-secondary">
138 {props.expanded ? "Snoozed" : `Snoozed (${props.count})`}133 {props.expanded ? "Snoozed" : `Snoozed (${props.count})`}
139 </Text>134 </Text>
140 <View className="h-px flex-1 bg-adaptive-blue-500-a20-blue-400-a15" />135 <View className="h-px flex-1 bg-primary/20" />
141 <SymbolView136 <SymbolView
142 name="chevron.down"137 name="chevron.down"
143 size={10}138 size={10}
144 tintColor={colorScheme === "dark" ? SNOOZE_ACCENT_DARK : SNOOZE_ACCENT_LIGHT}139 tintColorClassName="accent-icon-muted"
145 type="monochrome"140 type="monochrome"
146 style={{ transform: [{ rotate: props.expanded ? "180deg" : "0deg" }] }}141 style={{ transform: [{ rotate: props.expanded ? "180deg" : "0deg" }] }}
147 />142 />
...@@ -737,7 +732,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: {...@@ -737,7 +732,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: {
737 <Text732 <Text
738 className={cn(733 className={cn(
739 "flex-1 text-xs",734 "flex-1 text-xs",
740 selected ? "text-user-bubble-foreground-muted" : "text-adaptive-red-600-a80-400-a80",735 selected ? "text-user-bubble-foreground-muted" : "text-danger-foreground",
741 )}736 )}
742 numberOfLines={1}737 numberOfLines={1}
743 >738 >
...@@ -919,7 +914,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: {...@@ -919,7 +914,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: {
919 selected914 selected
920 ? "text-user-bubble-foreground-muted"915 ? "text-user-bubble-foreground-muted"
921 : snoozedRow916 : snoozedRow
922 ? "text-adaptive-blue-600-400"917 ? "text-foreground-secondary"
923 : "text-foreground-tertiary",918 : "text-foreground-tertiary",
924 )}919 )}
925 style={{ fontFamily: MONO_FONT }}920 style={{ fontFamily: MONO_FONT }}
apps/mobile/src/features/threads/thread-search-match.tsx+1-1
...@@ -65,7 +65,7 @@ export function ThreadSearchMatchExcerpt(props: {...@@ -65,7 +65,7 @@ export function ThreadSearchMatchExcerpt(props: {
65 props.selected65 props.selected
66 ? "text-user-bubble-foreground"66 ? "text-user-bubble-foreground"
67 : isUser67 : isUser
68 ? "text-adaptive-blue-500-400"68 ? "text-foreground-secondary"
69 : "text-adaptive-emerald-600-400",69 : "text-adaptive-emerald-600-400",
70 )}70 )}
71 >71 >
apps/mobile/src/features/threads/thread-work-log.tsx+3-3
...@@ -773,7 +773,7 @@ const ThreadWorkLogRow = memo(function ThreadWorkLogRow(...@@ -773,7 +773,7 @@ const ThreadWorkLogRow = memo(function ThreadWorkLogRow(
773 color={props.iconSubtleColor}773 color={props.iconSubtleColor}
774 colorClassName={774 colorClassName={
775 iconIsDestructive775 iconIsDestructive
776 ? "accent-adaptive-rose-600-400"776 ? "accent-danger-foreground"
777 : failed777 : failed
778 ? "accent-danger-foreground/40"778 ? "accent-danger-foreground/40"
779 : undefined779 : undefined
...@@ -784,7 +784,7 @@ const ThreadWorkLogRow = memo(function ThreadWorkLogRow(...@@ -784,7 +784,7 @@ const ThreadWorkLogRow = memo(function ThreadWorkLogRow(
784 <Text784 <Text
785 className={cn(785 className={cn(
786 "min-w-0 flex-1 text-sm text-foreground-muted",786 "min-w-0 flex-1 text-sm text-foreground-muted",
787 iconIsDestructive && "font-t3-medium text-adaptive-rose-600-400",787 iconIsDestructive && "font-t3-medium text-danger-foreground",
788 )}788 )}
789 numberOfLines={1}789 numberOfLines={1}
790 >790 >
...@@ -832,7 +832,7 @@ const ThreadWorkLogRow = memo(function ThreadWorkLogRow(...@@ -832,7 +832,7 @@ const ThreadWorkLogRow = memo(function ThreadWorkLogRow(
832 entering={WORK_LOG_DETAIL_ENTER_TRANSITION}832 entering={WORK_LOG_DETAIL_ENTER_TRANSITION}
833 exiting={WORK_LOG_DETAIL_EXIT_TRANSITION}833 exiting={WORK_LOG_DETAIL_EXIT_TRANSITION}
834 layout={WORK_LOG_LAYOUT_TRANSITION}834 layout={WORK_LOG_LAYOUT_TRANSITION}
835 className="ml-7 border-l border-adaptive-neutral-300-a60-white-a12 pb-1 pl-3 pt-0.5"835 className="ml-7 border-l border-border pb-1 pl-3 pt-0.5"
836 >836 >
837 {viewedImagePath ? (837 {viewedImagePath ? (
838 <View className="pb-1.5">838 <View className="pb-1.5">
apps/mobile/src/features/threads/threadPresentation.ts+12-12
...@@ -42,8 +42,8 @@ export function resolveThreadStatus(...@@ -42,8 +42,8 @@ export function resolveThreadStatus(
42 return {42 return {
43 kind: "pending-approval",43 kind: "pending-approval",
44 label: "Needs Approval",44 label: "Needs Approval",
45 pillClassName: "bg-adaptive-amber-500-a12-a16",45 pillClassName: "bg-warning",
46 textClassName: "text-adaptive-amber-700-300",46 textClassName: "text-warning-foreground",
47 iconColor: "#ff9f0a",47 iconColor: "#ff9f0a",
48 iconBackground: "rgba(255,159,10,0.22)",48 iconBackground: "rgba(255,159,10,0.22)",
49 pulse: false,49 pulse: false,
...@@ -54,8 +54,8 @@ export function resolveThreadStatus(...@@ -54,8 +54,8 @@ export function resolveThreadStatus(
54 return {54 return {
55 kind: "awaiting-input",55 kind: "awaiting-input",
56 label: "Awaiting Input",56 label: "Awaiting Input",
57 pillClassName: "bg-adaptive-indigo-500-a12-a16",57 pillClassName: "bg-primary/10",
58 textClassName: "text-adaptive-indigo-700-300",58 textClassName: "text-foreground-secondary",
59 iconColor: "#5e5ce6",59 iconColor: "#5e5ce6",
60 iconBackground: "rgba(94,92,230,0.22)",60 iconBackground: "rgba(94,92,230,0.22)",
61 pulse: false,61 pulse: false,
...@@ -66,8 +66,8 @@ export function resolveThreadStatus(...@@ -66,8 +66,8 @@ export function resolveThreadStatus(
66 return {66 return {
67 kind: "working",67 kind: "working",
68 label: "Working",68 label: "Working",
69 pillClassName: "bg-adaptive-sky-500-a12-a16",69 pillClassName: "bg-primary/10",
70 textClassName: "text-adaptive-sky-700-300",70 textClassName: "text-foreground-secondary",
71 iconColor: "#0a84ff",71 iconColor: "#0a84ff",
72 iconBackground: "rgba(10,132,255,0.22)",72 iconBackground: "rgba(10,132,255,0.22)",
73 pulse: true,73 pulse: true,
...@@ -78,8 +78,8 @@ export function resolveThreadStatus(...@@ -78,8 +78,8 @@ export function resolveThreadStatus(
78 return {78 return {
79 kind: "connecting",79 kind: "connecting",
80 label: "Connecting",80 label: "Connecting",
81 pillClassName: "bg-adaptive-sky-500-a12-a16",81 pillClassName: "bg-primary/10",
82 textClassName: "text-adaptive-sky-700-300",82 textClassName: "text-foreground-secondary",
83 iconColor: "#0a84ff",83 iconColor: "#0a84ff",
84 iconBackground: "rgba(10,132,255,0.22)",84 iconBackground: "rgba(10,132,255,0.22)",
85 pulse: true,85 pulse: true,
...@@ -90,8 +90,8 @@ export function resolveThreadStatus(...@@ -90,8 +90,8 @@ export function resolveThreadStatus(
90 return {90 return {
91 kind: "error",91 kind: "error",
92 label: "Error",92 label: "Error",
93 pillClassName: "bg-adaptive-rose-500-a12-a16",93 pillClassName: "bg-danger",
94 textClassName: "text-adaptive-rose-700-300",94 textClassName: "text-danger-foreground",
95 iconColor: "#ff453a",95 iconColor: "#ff453a",
96 iconBackground: "rgba(255,69,58,0.22)",96 iconBackground: "rgba(255,69,58,0.22)",
97 pulse: false,97 pulse: false,
...@@ -106,8 +106,8 @@ export function resolveThreadStatus(...@@ -106,8 +106,8 @@ export function resolveThreadStatus(
106 return {106 return {
107 kind: "plan-ready",107 kind: "plan-ready",
108 label: "Plan Ready",108 label: "Plan Ready",
109 pillClassName: "bg-adaptive-violet-500-a12-a16",109 pillClassName: "bg-primary/10",
110 textClassName: "text-adaptive-violet-700-300",110 textClassName: "text-foreground-secondary",
111 iconColor: "#bf5af2",111 iconColor: "#bf5af2",
112 iconBackground: "rgba(191,90,242,0.22)",112 iconBackground: "rgba(191,90,242,0.22)",
113 pulse: false,113 pulse: false,
apps/mobile/src/lib/mobileTheme.test.ts+7-1
...@@ -153,10 +153,16 @@ describe("mobile themes", () => {...@@ -153,10 +153,16 @@ describe("mobile themes", () => {
153153
154 it("maps semantic palette roles onto every mobile color variable", () => {154 it("maps semantic palette roles onto every mobile color variable", () => {
155 const variables = createMobileThemeVariables(BUILT_IN_THEMES[0].colors, "light");155 const variables = createMobileThemeVariables(BUILT_IN_THEMES[0].colors, "light");
156 expect(Object.keys(variables)).toHaveLength(65);156 expect(Object.keys(variables)).toHaveLength(68);
157 expect(variables["--color-sheet-solid"]).toBe(157 expect(variables["--color-sheet-solid"]).toBe(
158 themeColorToNativeColor(BUILT_IN_THEMES[0].colors.chrome),158 themeColorToNativeColor(BUILT_IN_THEMES[0].colors.chrome),
159 );159 );
160 expect(variables["--color-warning"]).toBe(
161 themeColorToNativeColor(BUILT_IN_THEMES[0].colors.warningSurface),
162 );
163 expect(variables["--color-warning-foreground"]).toBe(
164 themeColorToNativeColor(BUILT_IN_THEMES[0].colors.warningForeground),
165 );
160 expect(variables["--color-primary"]).not.toBe(variables["--color-screen"]);166 expect(variables["--color-primary"]).not.toBe(variables["--color-screen"]);
161 expect(variables["--color-primary-shadow"]).toBe("#000000");167 expect(variables["--color-primary-shadow"]).toBe("#000000");
162 expect(variables["--color-backdrop"]).toBe("rgba(0, 0, 0, 0.22)");168 expect(variables["--color-backdrop"]).toBe("rgba(0, 0, 0, 0.22)");
apps/mobile/src/lib/mobileTheme.ts+3
...@@ -239,6 +239,9 @@ export function createMobileThemeVariables(...@@ -239,6 +239,9 @@ export function createMobileThemeVariables(
239 "--color-switch-active-thumb": c.accentForeground,239 "--color-switch-active-thumb": c.accentForeground,
240 "--color-switch-inactive-track": c.secondary,240 "--color-switch-inactive-track": c.secondary,
241 "--color-switch-inactive-thumb": c.mutedForeground,241 "--color-switch-inactive-thumb": c.mutedForeground,
242 "--color-warning": c.warningSurface,
243 "--color-warning-border": withAlpha(c.warning, 0.32),
244 "--color-warning-foreground": c.warningForeground,
242 "--color-danger": c.errorSurface,245 "--color-danger": c.errorSurface,
243 "--color-danger-border": withAlpha(c.error, 0.32),246 "--color-danger-border": withAlpha(c.error, 0.32),
244 "--color-danger-foreground": c.errorForeground,247 "--color-danger-foreground": c.errorForeground,
apps/mobile/src/state/thread-pr-presentation.ts+2-2
...@@ -20,7 +20,7 @@ export interface ThreadPrPresentation {...@@ -20,7 +20,7 @@ export interface ThreadPrPresentation {
20const PR_STATE_TEXT_CLASS: Record<ThreadPr["state"], string> = {20const PR_STATE_TEXT_CLASS: Record<ThreadPr["state"], string> = {
21 open: "text-adaptive-emerald-600-400",21 open: "text-adaptive-emerald-600-400",
22 merged: "text-adaptive-violet-600-400",22 merged: "text-adaptive-violet-600-400",
23 closed: "text-adaptive-zinc-500-400",23 closed: "text-foreground-muted",
24};24};
2525
26export function presentThreadPr(26export function presentThreadPr(
...@@ -37,6 +37,6 @@ export function presentThreadPr(...@@ -37,6 +37,6 @@ export function presentThreadPr(
37 url: pr.url,37 url: pr.url,
38 label: String(pr.number),38 label: String(pr.number),
39 accessibilityLabel: `#${pr.number} ${presentation.longName} ${isDraft ? "draft" : pr.state}`,39 accessibilityLabel: `#${pr.number} ${presentation.longName} ${isDraft ? "draft" : pr.state}`,
40 textClassName: isDraft ? "text-adaptive-zinc-500-400" : PR_STATE_TEXT_CLASS[pr.state],40 textClassName: isDraft ? "text-foreground-muted" : PR_STATE_TEXT_CLASS[pr.state],
41 };41 };
42}42}
apps/mobile/src/state/use-thread-pr.test.ts+1-1
...@@ -39,7 +39,7 @@ describe("presentThreadPr", () => {...@@ -39,7 +39,7 @@ describe("presentThreadPr", () => {
39 presentThreadPr({ ...pullRequest, state: "open", isDraft: true }, undefined),39 presentThreadPr({ ...pullRequest, state: "open", isDraft: true }, undefined),
40 ).toMatchObject({40 ).toMatchObject({
41 accessibilityLabel: "#3774 pull request draft",41 accessibilityLabel: "#3774 pull request draft",
42 textClassName: "text-adaptive-zinc-500-400",42 textClassName: "text-foreground-muted",
43 });43 });
44 });44 });
45});45});