fix: settings screen design tweaks for mobile

- Center settings cog icon vertically in host card
- Normalize icon sizes (relay/host/settings all use iconSize.sm)
- Hide theme picker labels on mobile (icon-only)
- Simplify audio test copy, remove verbose description
This commit is contained in:
Mohamed Boudra
2026-03-15 13:50:50 +07:00
parent d89f1ea663
commit 849f49b622
2 changed files with 20 additions and 16 deletions
@@ -23,6 +23,7 @@ type SegmentedControlProps<T extends string> = {
value: T; value: T;
onValueChange: (value: T) => void; onValueChange: (value: T) => void;
size?: SegmentedControlSize; size?: SegmentedControlSize;
hideLabels?: boolean;
style?: StyleProp<ViewStyle>; style?: StyleProp<ViewStyle>;
testID?: string; testID?: string;
}; };
@@ -32,6 +33,7 @@ export function SegmentedControl<T extends string>({
value, value,
onValueChange, onValueChange,
size = "md", size = "md",
hideLabels = false,
style, style,
testID, testID,
}: SegmentedControlProps<T>) { }: SegmentedControlProps<T>) {
@@ -72,12 +74,14 @@ export function SegmentedControl<T extends string>({
{option.icon({ color: iconColor, size: iconSize })} {option.icon({ color: iconColor, size: iconSize })}
</View> </View>
) : null} ) : null}
<Text {hideLabels ? null : (
style={[styles.label, labelSizeStyle, isSelected && styles.labelSelected]} <Text
numberOfLines={1} style={[styles.label, labelSizeStyle, isSelected && styles.labelSelected]}
> numberOfLines={1}
{option.label} >
</Text> {option.label}
</Text>
)}
</Pressable> </Pressable>
); );
})} })}
+10 -10
View File
@@ -78,16 +78,16 @@ function formatActiveConnectionBadge(input: {
return null; return null;
} }
if (activeConnection.type === "relay") { if (activeConnection.type === "relay") {
return { icon: <Globe size={theme.iconSize.xs} color={theme.colors.foregroundMuted} />, text: "Relay" }; return { icon: <Globe size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />, text: "Relay" };
} }
if (activeConnection.type === "directSocket") { if (activeConnection.type === "directSocket") {
return { icon: <Monitor size={theme.iconSize.xs} color={theme.colors.foregroundMuted} />, text: "Local" }; return { icon: <Monitor size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />, text: "Local" };
} }
if (activeConnection.type === "directPipe") { if (activeConnection.type === "directPipe") {
return { icon: <Monitor size={theme.iconSize.xs} color={theme.colors.foregroundMuted} />, text: "Local" }; return { icon: <Monitor size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />, text: "Local" };
} }
return { return {
icon: <Monitor size={theme.iconSize.xs} color={theme.colors.foregroundMuted} />, icon: <Monitor size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />,
text: activeConnection.display, text: activeConnection.display,
}; };
} }
@@ -230,6 +230,8 @@ const styles = StyleSheet.create((theme) => ({
borderRadius: theme.borderRadius.md, borderRadius: theme.borderRadius.md,
gap: 0, gap: 0,
marginLeft: theme.spacing[2], marginLeft: theme.spacing[2],
alignItems: "center",
justifyContent: "center",
}, },
advancedTrigger: { advancedTrigger: {
flexDirection: "row", flexDirection: "row",
@@ -685,7 +687,7 @@ export default function SettingsScreen() {
return Uint8Array.from(bytes).buffer; return Uint8Array.from(bytes).buffer;
}, },
}); });
setPlaybackTestResult("Playback command completed."); setPlaybackTestResult(null);
} catch (error) { } catch (error) {
const message = error instanceof Error ? error.message : String(error); const message = error instanceof Error ? error.message : String(error);
console.error("[Settings] Playback test failed", error); console.error("[Settings] Playback test failed", error);
@@ -878,6 +880,7 @@ export default function SettingsScreen() {
</View> </View>
<SegmentedControl <SegmentedControl
size="sm" size="sm"
hideLabels={Platform.OS !== "web"}
value={settings.theme} value={settings.theme}
onValueChange={handleThemeChange} onValueChange={handleThemeChange}
options={[ options={[
@@ -910,10 +913,7 @@ export default function SettingsScreen() {
<View style={[settingsStyles.card, styles.audioCard]}> <View style={[settingsStyles.card, styles.audioCard]}>
<View style={styles.audioRow}> <View style={styles.audioRow}>
<View style={styles.audioRowContent}> <View style={styles.audioRowContent}>
<Text style={styles.audioRowTitle}>Test audio playback</Text> <Text style={styles.audioRowTitle}>Test audio</Text>
<Text style={styles.aboutHintText}>
Plays a built-in PCM sample through the current app audio engine.
</Text>
{playbackTestResult ? ( {playbackTestResult ? (
<Text style={styles.aboutHintText}>{playbackTestResult}</Text> <Text style={styles.aboutHintText}>{playbackTestResult}</Text>
) : null} ) : null}
@@ -1463,7 +1463,7 @@ function DaemonCard({
> >
{({ hovered = false, pressed = false }) => ( {({ hovered = false, pressed = false }) => (
<Settings <Settings
size={theme.iconSize.md} size={theme.iconSize.sm}
color={ color={
hovered || pressed ? theme.colors.foreground : theme.colors.foregroundMuted hovered || pressed ? theme.colors.foreground : theme.colors.foregroundMuted
} }