fix(app): close theme split escape hatches

This commit is contained in:
Mohamed Boudra
2026-04-18 16:25:23 +07:00
parent fa41ba76cd
commit 4de4e90325
10 changed files with 120 additions and 72 deletions
@@ -22,7 +22,6 @@ import {
ShieldAlert,
ShieldOff,
} from "lucide-react-native";
import { theme as defaultTheme } from "@/styles/theme";
import type {
AgentMode,
AgentModelDefinition,
@@ -86,6 +85,8 @@ export function DropdownField({
renderTrigger,
testID,
}: DropdownFieldProps): ReactElement {
const { theme } = useUnistyles();
if (renderTrigger) {
return (
<>
@@ -115,7 +116,7 @@ export function DropdownField({
<Text style={value ? styles.dropdownValue : styles.dropdownPlaceholder} numberOfLines={1}>
{value || placeholder}
</Text>
<ChevronDown size={defaultTheme.iconSize.md} color={defaultTheme.colors.foregroundMuted} />
<ChevronDown size={theme.iconSize.md} color={theme.colors.foregroundMuted} />
</Pressable>
{errorMessage ? <Text style={styles.errorText}>{errorMessage}</Text> : null}
{warningMessage ? <Text style={styles.warningText}>{warningMessage}</Text> : null}
@@ -151,6 +152,8 @@ export function SelectField({
valueEllipsizeMode,
testID,
}: SelectFieldProps): ReactElement {
const { theme } = useUnistyles();
const getWebKey = useCallback((event: unknown): string | null => {
if (!event || typeof event !== "object") return null;
const eventWithNative = event as { nativeEvent?: unknown; key?: unknown };
@@ -210,7 +213,7 @@ export function SelectField({
{value || placeholder || "Select..."}
</Text>
</View>
<ChevronRight size={defaultTheme.iconSize.lg} color={defaultTheme.colors.foregroundMuted} />
<ChevronRight size={theme.iconSize.lg} color={theme.colors.foregroundMuted} />
</Pressable>
{errorMessage ? <Text style={styles.errorText}>{errorMessage}</Text> : null}
{warningMessage ? <Text style={styles.warningText}>{warningMessage}</Text> : null}
@@ -229,7 +232,21 @@ interface DropdownSheetProps {
}
function DropdownSheetBackground({ style }: BottomSheetBackgroundProps) {
return <Animated.View pointerEvents="none" style={[style, styles.bottomSheetBackground]} />;
const { theme } = useUnistyles();
return (
<Animated.View
pointerEvents="none"
style={[
style,
{
backgroundColor: theme.colors.surface2,
borderTopLeftRadius: theme.borderRadius["2xl"],
borderTopRightRadius: theme.borderRadius["2xl"],
},
]}
/>
);
}
export function DropdownSheet({
@@ -238,6 +255,7 @@ export function DropdownSheet({
onClose,
children,
}: DropdownSheetProps): ReactElement {
const { theme } = useUnistyles();
const bottomSheetRef = useRef<BottomSheetModal>(null);
const snapPoints = useMemo(() => ["60%", "90%"], []);
@@ -280,12 +298,12 @@ export function DropdownSheet({
backdropComponent={renderBackdrop}
enablePanDownToClose
backgroundComponent={DropdownSheetBackground}
handleIndicatorStyle={styles.bottomSheetHandle}
handleIndicatorStyle={{ backgroundColor: theme.colors.palette.zinc[600] }}
keyboardBehavior="extend"
keyboardBlurBehavior="restore"
>
<View style={styles.bottomSheetHeader}>
<Text style={styles.dropdownSheetTitle}>{title}</Text>
<Text style={[styles.dropdownSheetTitle, { color: theme.colors.foreground }]}>{title}</Text>
<Pressable
accessibilityRole="button"
accessibilityLabel="Close sheet"
@@ -293,7 +311,7 @@ export function DropdownSheet({
hitSlop={10}
testID="dropdown-sheet-close"
>
<X size={defaultTheme.iconSize.md} color={defaultTheme.colors.foregroundMuted} />
<X size={theme.iconSize.md} color={theme.colors.foregroundMuted} />
</Pressable>
</View>
<BottomSheetScrollView
@@ -413,6 +431,8 @@ export function FormSelectTrigger({
valueEllipsizeMode,
testID,
}: CompactSelectFieldProps): ReactElement {
const { theme } = useUnistyles();
const getWebKey = useCallback((event: unknown): string | null => {
if (!event || typeof event !== "object") return null;
const eventWithNative = event as { nativeEvent?: unknown; key?: unknown };
@@ -469,7 +489,7 @@ export function FormSelectTrigger({
<View style={styles.compactSelectValueContainer}>
{showLabel ? <Text style={styles.compactSelectLabel}>{label}</Text> : null}
{isLoading ? (
<ActivityIndicator size="small" color={defaultTheme.colors.foregroundMuted} />
<ActivityIndicator size="small" color={theme.colors.foregroundMuted} />
) : (
<Text
style={hasConcreteValue ? styles.compactSelectValue : styles.compactSelectPlaceholder}
@@ -480,7 +500,7 @@ export function FormSelectTrigger({
</Text>
)}
</View>
<ChevronDown size={defaultTheme.iconSize.md} color={defaultTheme.colors.foregroundMuted} />
<ChevronDown size={theme.iconSize.md} color={theme.colors.foregroundMuted} />
</Pressable>
);
}
@@ -518,6 +538,8 @@ export function AgentConfigRow({
onSelectThinkingOption,
disabled,
}: AgentConfigRowProps): ReactElement {
const { theme } = useUnistyles();
const providerOptions: ComboSelectOption[] = useMemo(
() =>
providerDefinitions.map((def) => ({
@@ -576,7 +598,7 @@ export function AgentConfigRow({
placeholder={providerOptions.length > 0 ? "Select..." : "No providers available"}
disabled={disabled || providerOptions.length === 0}
onSelect={onSelectProvider}
icon={<Bot size={defaultTheme.iconSize.md} color={defaultTheme.colors.foregroundMuted} />}
icon={<Bot size={theme.iconSize.md} color={theme.colors.foregroundMuted} />}
showLabel={false}
testID="draft-provider-select"
/>
@@ -591,9 +613,7 @@ export function AgentConfigRow({
disabled={disabled}
isLoading={isModelLoading}
onSelect={onSelectModel}
icon={
<Brain size={defaultTheme.iconSize.md} color={defaultTheme.colors.foregroundMuted} />
}
icon={<Brain size={theme.iconSize.md} color={theme.colors.foregroundMuted} />}
showLabel={false}
testID="draft-model-select"
/>
@@ -607,7 +627,7 @@ export function AgentConfigRow({
placeholder="Default"
disabled={disabled || modeOptions.length === 0}
onSelect={onSelectMode}
icon={<ModeIcon size={defaultTheme.iconSize.md} color={modeIconColor} />}
icon={<ModeIcon size={theme.iconSize.md} color={modeIconColor} />}
showLabel={false}
testID="draft-mode-select"
/>
@@ -622,9 +642,7 @@ export function AgentConfigRow({
placeholder="Select..."
disabled={disabled}
onSelect={onSelectThinkingOption}
icon={
<Brain size={defaultTheme.iconSize.md} color={defaultTheme.colors.foregroundMuted} />
}
icon={<Brain size={theme.iconSize.md} color={theme.colors.foregroundMuted} />}
showLabel={false}
/>
</View>
@@ -969,6 +987,8 @@ export function GitOptionsSection({
attachWorktreeError,
onSelectWorktreePath,
}: GitOptionsSectionProps): ReactElement {
const { theme } = useUnistyles();
const isLoading = status === "loading";
const isCreateMode = worktreeMode === "create";
const isAttachMode = worktreeMode === "attach";
@@ -1103,7 +1123,7 @@ export function GitOptionsSection({
autoCapitalize="none"
autoCorrect={false}
placeholder="branch name"
placeholderTextColor={defaultTheme.colors.foregroundMuted}
placeholderTextColor={theme.colors.foregroundMuted}
onSubmitEditing={handleConfirmEdit}
/>
<Pressable
@@ -1111,19 +1131,16 @@ export function GitOptionsSection({
hitSlop={8}
style={styles.baseBranchIconButton}
>
<Check
size={defaultTheme.iconSize.md}
color={defaultTheme.colors.palette.green[500]}
/>
<Check size={theme.iconSize.md} color={theme.colors.palette.green[500]} />
</Pressable>
<Pressable onPress={handleCancelEdit} hitSlop={8} style={styles.baseBranchIconButton}>
<X size={defaultTheme.iconSize.md} color={defaultTheme.colors.foregroundMuted} />
<X size={theme.iconSize.md} color={theme.colors.foregroundMuted} />
</Pressable>
</View>
) : (
<Pressable onPress={handleStartEdit} style={styles.baseBranchValueRow}>
<Text style={styles.baseBranchValue}>{displayBranch}</Text>
<Pencil size={defaultTheme.iconSize.sm} color={defaultTheme.colors.foregroundMuted} />
<Pencil size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />
</Pressable>
)}
</View>
@@ -1171,14 +1188,6 @@ const styles = StyleSheet.create((theme) => ({
color: theme.colors.foregroundMuted,
fontSize: theme.fontSize.base,
},
bottomSheetBackground: {
backgroundColor: theme.colors.surface2,
borderTopLeftRadius: theme.borderRadius["2xl"],
borderTopRightRadius: theme.borderRadius["2xl"],
},
bottomSheetHandle: {
backgroundColor: theme.colors.palette.zinc[600],
},
bottomSheetHeader: {
flexDirection: "row",
alignItems: "center",