import type { ReactNode } from "react"; import { Pressable, Text, View } from "react-native"; import type { StyleProp, ViewStyle } from "react-native"; import { StyleSheet, useUnistyles } from "react-native-unistyles"; type SegmentedControlSize = "sm" | "md"; type SegmentedControlIconRenderer = (props: { color: string; size: number }) => ReactNode; export type SegmentedControlOption = { value: T; label: string; icon?: SegmentedControlIconRenderer; disabled?: boolean; testID?: string; }; type SegmentedControlProps = { options: SegmentedControlOption[]; value: T; onValueChange: (value: T) => void; size?: SegmentedControlSize; hideLabels?: boolean; style?: StyleProp; testID?: string; }; export function SegmentedControl({ options, value, onValueChange, size = "md", hideLabels = false, style, testID, }: SegmentedControlProps) { const { theme } = useUnistyles(); const segmentSizeStyle = size === "sm" ? styles.segmentSm : styles.segmentMd; const labelSizeStyle = size === "sm" ? styles.labelSm : styles.labelMd; const iconSize = size === "sm" ? theme.iconSize.sm : theme.iconSize.md; return ( {options.map((option) => { const isSelected = option.value === value; const iconColor = isSelected ? theme.colors.foreground : theme.colors.foregroundMuted; return ( { if (!option.disabled && option.value !== value) { onValueChange(option.value); } }} style={({ hovered, pressed }) => [ styles.segment, segmentSizeStyle, isSelected && styles.segmentSelected, hovered && !isSelected && styles.segmentHover, pressed && !isSelected && styles.segmentPressed, option.disabled && styles.segmentDisabled, ]} > {option.icon ? ( {option.icon({ color: iconColor, size: iconSize })} ) : null} {hideLabels ? null : ( {option.label} )} ); })} ); } const styles = StyleSheet.create((theme) => ({ container: { flexDirection: "row", alignItems: "center", maxWidth: "100%", gap: 4, }, segment: { flexDirection: "row", alignItems: "center", justifyContent: "center", flexShrink: 0, borderRadius: theme.borderRadius.full, borderWidth: 1, borderColor: "transparent", gap: theme.spacing[1], }, segmentSm: { paddingVertical: theme.spacing[1], paddingHorizontal: theme.spacing[2], }, segmentMd: { paddingVertical: theme.spacing[2], paddingHorizontal: theme.spacing[3], }, segmentSelected: { backgroundColor: theme.colors.surface3, borderColor: theme.colors.border, }, segmentHover: { backgroundColor: theme.colors.surface3, borderColor: theme.colors.borderAccent, }, segmentPressed: { backgroundColor: theme.colors.surface3, borderColor: theme.colors.borderAccent, }, segmentDisabled: { opacity: theme.opacity[50], }, iconContainer: { alignItems: "center", justifyContent: "center", }, label: { color: theme.colors.foregroundMuted, fontWeight: theme.fontWeight.normal, }, labelSm: { fontSize: theme.fontSize.xs, }, labelMd: { fontSize: theme.fontSize.sm, }, labelSelected: { color: theme.colors.foreground, }, }));