about summary refs log tree commit diff
path: root/src/view/com/util/forms/ToggleButton.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/com/util/forms/ToggleButton.tsx')
-rw-r--r--src/view/com/util/forms/ToggleButton.tsx165
1 files changed, 165 insertions, 0 deletions
diff --git a/src/view/com/util/forms/ToggleButton.tsx b/src/view/com/util/forms/ToggleButton.tsx
new file mode 100644
index 000000000..77e8fa203
--- /dev/null
+++ b/src/view/com/util/forms/ToggleButton.tsx
@@ -0,0 +1,165 @@
+import React from 'react'
+import {StyleProp, StyleSheet, TextStyle, View, ViewStyle} from 'react-native'
+import {Text} from '../text/Text'
+import {Button, ButtonType} from './Button'
+import {useTheme} from '../../../lib/ThemeContext'
+import {choose} from '../../../../lib/functions'
+import {colors} from '../../../lib/styles'
+
+export function ToggleButton({
+  type = 'default-light',
+  label,
+  isSelected,
+  style,
+  onPress,
+}: {
+  type?: ButtonType
+  label: string
+  isSelected: boolean
+  style?: StyleProp<ViewStyle>
+  onPress: () => void
+}) {
+  const theme = useTheme()
+  const circleStyle = choose<TextStyle, Record<ButtonType, TextStyle>>(type, {
+    primary: {
+      borderColor: theme.palette.primary.text,
+    },
+    secondary: {
+      borderColor: theme.palette.secondary.text,
+    },
+    inverted: {
+      borderColor: theme.palette.inverted.text,
+    },
+    'primary-outline': {
+      borderColor: theme.palette.primary.border,
+    },
+    'secondary-outline': {
+      borderColor: theme.palette.secondary.border,
+    },
+    'primary-light': {
+      borderColor: theme.palette.primary.border,
+    },
+    'secondary-light': {
+      borderColor: theme.palette.secondary.border,
+    },
+    'default-light': {
+      borderColor: theme.palette.default.border,
+    },
+  })
+  const circleFillStyle = choose<TextStyle, Record<ButtonType, TextStyle>>(
+    type,
+    {
+      primary: {
+        backgroundColor: theme.palette.primary.text,
+        opacity: isSelected ? 1 : 0.33,
+      },
+      secondary: {
+        backgroundColor: theme.palette.secondary.text,
+        opacity: isSelected ? 1 : 0.33,
+      },
+      inverted: {
+        backgroundColor: theme.palette.inverted.text,
+        opacity: isSelected ? 1 : 0.33,
+      },
+      'primary-outline': {
+        backgroundColor: theme.palette.primary.background,
+        opacity: isSelected ? 1 : 0.5,
+      },
+      'secondary-outline': {
+        backgroundColor: theme.palette.secondary.background,
+        opacity: isSelected ? 1 : 0.5,
+      },
+      'primary-light': {
+        backgroundColor: theme.palette.primary.background,
+        opacity: isSelected ? 1 : 0.5,
+      },
+      'secondary-light': {
+        backgroundColor: theme.palette.secondary.background,
+        opacity: isSelected ? 1 : 0.5,
+      },
+      'default-light': {
+        backgroundColor: isSelected
+          ? theme.palette.primary.background
+          : colors.gray3,
+      },
+    },
+  )
+  const labelStyle = choose<TextStyle, Record<ButtonType, TextStyle>>(type, {
+    primary: {
+      color: theme.palette.primary.text,
+      fontWeight: theme.palette.primary.isLowContrast ? '500' : undefined,
+    },
+    secondary: {
+      color: theme.palette.secondary.text,
+      fontWeight: theme.palette.secondary.isLowContrast ? '500' : undefined,
+    },
+    inverted: {
+      color: theme.palette.inverted.text,
+      fontWeight: theme.palette.inverted.isLowContrast ? '500' : undefined,
+    },
+    'primary-outline': {
+      color: theme.palette.primary.textInverted,
+      fontWeight: theme.palette.primary.isLowContrast ? '500' : undefined,
+    },
+    'secondary-outline': {
+      color: theme.palette.secondary.textInverted,
+      fontWeight: theme.palette.secondary.isLowContrast ? '500' : undefined,
+    },
+    'primary-light': {
+      color: theme.palette.primary.textInverted,
+      fontWeight: theme.palette.primary.isLowContrast ? '500' : undefined,
+    },
+    'secondary-light': {
+      color: theme.palette.secondary.textInverted,
+      fontWeight: theme.palette.secondary.isLowContrast ? '500' : undefined,
+    },
+    'default-light': {
+      color: theme.palette.default.text,
+      fontWeight: theme.palette.default.isLowContrast ? '500' : undefined,
+    },
+  })
+  return (
+    <Button type={type} onPress={onPress} style={style}>
+      <View style={styles.outer}>
+        <View style={[circleStyle, styles.circle]}>
+          <View
+            style={[
+              circleFillStyle,
+              styles.circleFill,
+              isSelected ? styles.circleFillSelected : undefined,
+            ]}
+          />
+        </View>
+        <Text type="button" style={[labelStyle, styles.label]}>
+          {label}
+        </Text>
+      </View>
+    </Button>
+  )
+}
+
+const styles = StyleSheet.create({
+  outer: {
+    flexDirection: 'row',
+    alignItems: 'center',
+  },
+  circle: {
+    width: 42,
+    height: 26,
+    borderRadius: 15,
+    padding: 4,
+    borderWidth: 1,
+    marginRight: 10,
+  },
+  circleFill: {
+    width: 16,
+    height: 16,
+    borderRadius: 10,
+  },
+  circleFillSelected: {
+    marginLeft: 16,
+  },
+  label: {
+    flex: 1,
+  },
+})