Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | 2x 12x 12x 12x 12x 12x 12x 12x 12x 12x | import {
Switch as RNSwitch,
Text,
TextStyle,
View,
ViewStyle,
} from "react-native";
import { makeStyles } from "@repo/ui/themes/makeStyles";
import { useTheme } from "@repo/ui/themes/ThemeContext";
export interface CustomSwitchProps {
value: boolean;
onValueChange: (value: boolean) => void;
label?: string;
disabled?: boolean;
disableLabelStyle?: boolean;
containerStyle?: ViewStyle;
labelStyle?: TextStyle;
errorMessage?: string;
testID?: string;
switchProps?: Omit<
React.ComponentProps<typeof RNSwitch>,
"value" | "onValueChange" | "disabled"
>;
}
export const Switch = ({
value,
onValueChange,
label,
disabled = false,
containerStyle,
labelStyle,
switchProps,
testID,
errorMessage,
}: CustomSwitchProps) => {
const { theme } = useTheme();
const styles = useStyles();
const resolvedValue = Boolean(value);
const switchRenderKey = resolvedValue ? "switch-on" : "switch-off";
const defaultTrackColor = {
false: theme.colors.gray50,
true: theme.colors.blue80,
};
const defaultThumbColor = resolvedValue
? theme.colors.white
: theme.colors.gray10;
const defaultIosBackgroundColor = theme.colors.gray50;
return (
<View style={[styles.container, containerStyle]}>
{label ? <Text style={[styles.label, labelStyle]}>{label}</Text> : null}
<RNSwitch
key={switchRenderKey}
{...switchProps}
testID={testID}
trackColor={{
...defaultTrackColor,
...switchProps?.trackColor,
}}
thumbColor={switchProps?.thumbColor ?? defaultThumbColor}
ios_backgroundColor={
switchProps?.ios_backgroundColor ?? defaultIosBackgroundColor
}
value={resolvedValue}
onValueChange={onValueChange}
disabled={disabled}
accessibilityState={{ checked: resolvedValue, disabled }}
/>
{errorMessage && (
<Text style={styles.error} accessibilityLiveRegion="polite">
{errorMessage}
</Text>
)}
</View>
);
};
const useStyles = makeStyles((theme) => ({
container: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
gap: theme.metrics.spacing[2],
marginVertical: theme.metrics.spacing[1],
},
label: {
fontSize: theme.metrics.textSize[16],
color: theme.colors.text.info,
flex: 1,
flexShrink: 1,
},
error: {
position: "absolute",
bottom: -theme.metrics.spacing[4.5],
fontSize: theme.metrics.textSize[12],
color: theme.colors.text.error,
},
}));
|