1import { Host, Switch as ComposeSwitch } from "@expo/ui/jetpack-compose";
2import { View } from "react-native";
3import type { ThemedSwitchProps } from "./MaterialSwitch.types";
4
5import { useAppearancePreferences } from "../features/settings/appearance/AppearancePreferencesProvider";
6
7/** Material's native switch, with the same palette and accessibility contract as our RN controls. */
8export function MaterialSwitch(props: ThemedSwitchProps) {
9 const { themeAppearance, themeVariables: colors } = useAppearancePreferences();
10 const toggle = () => {
11 if (!props.disabled) props.onValueChange?.(!props.value);
12 };
13
14 return (
15 <View
16 accessible
17 accessibilityLabel={props.accessibilityLabel}
18 accessibilityHint={props.accessibilityHint}
19 accessibilityRole="switch"
20 accessibilityState={{ checked: Boolean(props.value), disabled: Boolean(props.disabled) }}
21 accessibilityActions={[{ name: "activate", label: "Toggle" }]}
22 onAccessibilityAction={toggle}
23 style={props.style}
24 testID={props.testID}
25 >
26 <View importantForAccessibility="no-hide-descendants">
27 <Host
28 colorScheme={themeAppearance}
29 ignoreSafeAreaKeyboardInsets
30 style={{ width: 52, height: 48 }}
31 >
32 <ComposeSwitch
33 value={Boolean(props.value)}
34 enabled={!props.disabled}
35 onCheckedChange={props.onValueChange ?? undefined}
36 colors={{
37 checkedTrackColor: colors["--color-switch-active-track"],
38 checkedThumbColor: colors["--color-switch-active-thumb"],
39 checkedBorderColor: colors["--color-switch-active-track"],
40 uncheckedTrackColor: colors["--color-switch-inactive-track"],
41 uncheckedThumbColor: colors["--color-switch-inactive-thumb"],
42 uncheckedBorderColor: colors["--color-switch-inactive-thumb"],
43 }}
44 />
45 </Host>
46 </View>
47 </View>
48 );
49}