authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-09-17 20:29:11-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-17 20:29:11-07:00
logcc39ec1008ce584e088e79210b69d3359357463b
tree7f02722753b106875c506841ca37cc9ce451012c
parentc7fa1e96943f380a8893e89460d03a362285ab83
signature Signed by PGP key B5690EEEBB952194

fix(mobile): share request action button defaults (#12366)


4 files changed, 64 insertions(+), 43 deletions(-)

apps/mobile/src/features/threads/PendingApprovalCard.tsx+10-20
...@@ -1,9 +1,10 @@...@@ -1,9 +1,10 @@
1import { RequestActionButton } from "./RequestActionButton";
1import type {2import type {
2 ApprovalRequestId,3 ApprovalRequestId,
3 ProviderApprovalDecision,4 ProviderApprovalDecision,
4 ProviderApprovalOption,5 ProviderApprovalOption,
5} from "@t3tools/contracts";6} from "@t3tools/contracts";
6import { Pressable, View } from "react-native";7import { View } from "react-native";
78
8import { AppText as Text } from "../../components/AppText";9import { AppText as Text } from "../../components/AppText";
9import type { PendingApproval } from "../../lib/threadActivity";10import type { PendingApproval } from "../../lib/threadActivity";
...@@ -47,30 +48,19 @@ export function PendingApprovalCard(props: PendingApprovalCardProps) {...@@ -47,30 +48,19 @@ export function PendingApprovalCard(props: PendingApprovalCardProps) {
47 ) : null}48 ) : null}
48 <View className="flex-row flex-wrap gap-2.5">49 <View className="flex-row flex-wrap gap-2.5">
49 {options.map((option) => (50 {options.map((option) => (
50 <Pressable51 <RequestActionButton
51 key={option.decision}52 key={option.decision}
52 className={`items-center justify-center rounded-[14px] px-3.5 py-3 ${53 label={option.label}
54 tone={
53 option.decision === "accept"55 option.decision === "accept"
54 ? "bg-primary"56 ? "primary"
55 : option.decision === "decline"57 : option.decision === "decline"
56 ? "bg-danger"58 ? "danger"
57 : "bg-subtle-strong"59 : "secondary"
58 }`}60 }
59 disabled={props.respondingApprovalId === props.approval.requestId}61 disabled={props.respondingApprovalId === props.approval.requestId}
60 onPress={() => void props.onRespond(props.approval.requestId, option.decision)}62 onPress={() => void props.onRespond(props.approval.requestId, option.decision)}
61 >63 />
62 <Text
63 className={`text-sm ${
64 option.decision === "accept"
65 ? "font-t3-extrabold text-primary-foreground"
66 : option.decision === "decline"
67 ? "font-t3-bold text-danger-foreground"
68 : "font-t3-bold text-foreground"
69 }`}
70 >
71 {option.label}
72 </Text>
73 </Pressable>
74 ))}64 ))}
75 </View>65 </View>
76 </View>66 </View>
apps/mobile/src/features/threads/PendingUserInputCard.tsx+6-15
...@@ -1,3 +1,4 @@...@@ -1,3 +1,4 @@
1import { RequestActionButton } from "./RequestActionButton";
1import { QuestionAttachments } from "./QuestionAttachments";2import { QuestionAttachments } from "./QuestionAttachments";
2import type { ApprovalRequestId, UserInputQuestion } from "@t3tools/contracts";3import type { ApprovalRequestId, UserInputQuestion } from "@t3tools/contracts";
3import { useCallback, useRef } from "react";4import { useCallback, useRef } from "react";
...@@ -321,25 +322,15 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) {...@@ -321,25 +322,15 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) {
321 );322 );
322 })}323 })}
323 </ScrollView>324 </ScrollView>
324 <Pressable325 <RequestActionButton
325 className={cn(326 label="Submit answers"
326 "items-center justify-center rounded-2xl px-4 py-3.5",327 size="large"
327 props.answers ? "bg-primary" : "bg-subtle-strong",328 tone={props.answers ? "primary" : "secondary"}
328 )}
329 disabled={329 disabled={
330 props.answers === null || props.respondingUserInputId === props.pendingUserInput.requestId330 props.answers === null || props.respondingUserInputId === props.pendingUserInput.requestId
331 }331 }
332 onPress={() => void props.onSubmit()}332 onPress={() => void props.onSubmit()}
333 >333 />
334 <Text
335 className={cn(
336 "font-t3-extrabold text-sm",
337 props.answers ? "text-primary-foreground" : "text-foreground-muted",
338 )}
339 >
340 Submit answers
341 </Text>
342 </Pressable>
343 {props.pendingUserInput.dismissible ? (334 {props.pendingUserInput.dismissible ? (
344 <Pressable335 <Pressable
345 accessibilityRole="button"336 accessibilityRole="button"
apps/mobile/src/features/threads/RequestActionButton.tsx created+45
...@@ -0,0 +1,45 @@
1import type { ComponentProps } from "react";
2import { Pressable } from "react-native";
3
4import { AppText as Text } from "../../components/AppText";
5import { cn } from "../../lib/cn";
6
7/** Primary actions in the cards that replace the thread composer. */
8export function RequestActionButton({
9 label,
10 tone = "primary",
11 size = "default",
12 disabled,
13 ...props
14}: Omit<ComponentProps<typeof Pressable>, "children" | "className" | "style"> & {
15 label: string;
16 tone?: "primary" | "secondary" | "danger";
17 size?: "default" | "large";
18}) {
19 return (
20 <Pressable
21 {...props}
22 accessibilityRole="button"
23 accessibilityState={{ ...props.accessibilityState, disabled: Boolean(disabled) }}
24 disabled={disabled}
25 className={cn(
26 "items-center justify-center active:opacity-70 disabled:opacity-50",
27 size === "large" ? "rounded-2xl px-4 py-3.5" : "rounded-[14px] px-3.5 py-3",
28 tone === "primary" ? "bg-primary" : tone === "danger" ? "bg-danger" : "bg-subtle-strong",
29 )}
30 >
31 <Text
32 className={cn(
33 "text-sm",
34 tone === "primary"
35 ? "font-t3-extrabold text-primary-foreground"
36 : tone === "danger"
37 ? "font-t3-bold text-danger-foreground"
38 : "font-t3-bold text-foreground",
39 )}
40 >
41 {label}
42 </Text>
43 </Pressable>
44 );
45}
apps/mobile/src/features/threads/ThreadCreationFailedCard.tsx+3-8
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1import { Pressable, View } from "react-native";1import { RequestActionButton } from "./RequestActionButton";
2import { View } from "react-native";
23
3import { AppText as Text } from "../../components/AppText";4import { AppText as Text } from "../../components/AppText";
45
...@@ -23,13 +24,7 @@ export function ThreadCreationFailedCard(props: {...@@ -23,13 +24,7 @@ export function ThreadCreationFailedCard(props: {
23 Your prompt was kept in the project draft.24 Your prompt was kept in the project draft.
24 </Text>25 </Text>
25 <View className="flex-row">26 <View className="flex-row">
26 <Pressable27 <RequestActionButton label="Edit task" onPress={props.onEditTask} />
27 accessibilityRole="button"
28 className="items-center justify-center rounded-[14px] bg-blue-500 px-3.5 py-3"
29 onPress={props.onEditTask}
30 >
31 <Text className="text-sm font-t3-extrabold text-white">Edit task</Text>
32 </Pressable>
33 </View>28 </View>
34 </View>29 </View>
35 );30 );