Files
native/src/components/ToggleSwitch.tsx
T
Linus Rath cf3f919fa2 feat: enhance SettingsScreen with dynamic localization and theming
- Integrated useColors hook for dynamic theming in SettingsScreen.
- Updated tab labels and titles to use localized strings.
- Refactored styles to utilize theme palette for consistent styling.
- Improved locale subscription to re-render labels on language change.

feat: implement useSheetDrag hook for bottom sheet gesture handling

- Added useSheetDrag hook to manage drag-to-dismiss functionality for bottom sheets.
- Configured pan responder for handling drag gestures and dismissing the sheet based on distance and velocity.

refactor: restructure color and token management

- Introduced useColors and useResolvedTheme hooks for better theme management.
- Separated light and dark color palettes for improved maintainability.
- Updated tokens to reflect new theming structure and ensure consistency across components.
2026-04-27 13:30:45 +02:00

68 lines
1.7 KiB
TypeScript

import React from 'react';
import { Pressable, View, StyleSheet } from 'react-native';
import { radius, componentSizes, type ThemePalette } from '../theme/tokens';
import { useColors } from '../theme/colors';
interface ToggleSwitchProps {
value: boolean;
onValueChange: (val: boolean) => void;
disabled?: boolean;
}
/**
* Matches webmail ToggleSwitch:
* - h-6 w-11 rounded-full
* - checked: bg-primary, unchecked: bg-muted
* - thumb: h-4 w-4 rounded-full bg-background
* - translate-x-6 (checked) / translate-x-1 (unchecked)
*/
export default function ToggleSwitch({ value, onValueChange, disabled = false }: ToggleSwitchProps) {
const c = useColors();
const styles = React.useMemo(() => makeStyles(c), [c]);
return (
<Pressable
style={[
styles.track,
value ? styles.trackOn : styles.trackOff,
disabled && styles.disabled,
]}
onPress={() => !disabled && onValueChange(!value)}
accessibilityRole="switch"
accessibilityState={{ checked: value, disabled }}
>
<View
style={[
styles.thumb,
{ transform: [{ translateX: value ? 24 : 4 }] },
]}
/>
</Pressable>
);
}
function makeStyles(c: ThemePalette) {
return StyleSheet.create({
track: {
width: componentSizes.toggleWidth, // w-11 = 44
height: componentSizes.toggleHeight, // h-6 = 24
borderRadius: radius.full,
justifyContent: 'center',
},
trackOn: {
backgroundColor: c.primary,
},
trackOff: {
backgroundColor: c.muted,
},
thumb: {
width: componentSizes.toggleThumb, // h-4 w-4 = 16
height: componentSizes.toggleThumb,
borderRadius: radius.full,
backgroundColor: c.background,
},
disabled: {
opacity: 0.5,
},
});
}