eletrotupi / tcc/ frontend/components/ui/CategoryChips.tsxf2e8f9009eea845da1d93f97d5e52c5d780b0f0e
2.1 KB | 96 lines Raw
1
import {
2
  TouchableOpacity,
3
  View,
4
  StyleSheet,
5
} from 'react-native';
6
import { Text } from '@/components/ui/Text';
7
import { Colors } from '@/constants/theme';
8

9
export type CategoryOption<T extends string = string> = {
10
  label: string;
11
  value: T;
12
  icon: React.ReactNode;
13
};
14

15
type Props<T extends string = string> = {
16
  options: CategoryOption<T>[];
17
  active: T | null;
18
  onChange: (value: T) => void;
19
  columns?: number;
20
};
21

22
export function CategoryChips<T extends string = string>({
23
  options,
24
  active,
25
  onChange,
26
  columns = 2,
27
}: Props<T>) {
28
  return (
29
    <View style={styles.grid}>
30
      {options.map((option) => {
31
        const isActive = option.value === active;
32
        return (
33
          <TouchableOpacity
34
            key={option.value}
35
            onPress={() => onChange(option.value)}
36
            activeOpacity={0.7}
37
            style={[
38
              styles.chip,
39
              { width: `${100 / columns - 2}%` as any },
40
              isActive && styles.chipActive,
41
            ]}
42
          >
43
            <View style={styles.chipInner}>
44
              <View style={styles.iconWrapper}>{option.icon}</View>
45
              <Text style={[styles.label, isActive && styles.labelActive]}>
46
                {option.label}
47
              </Text>
48
            </View>
49
          </TouchableOpacity>
50
        );
51
      })}
52
    </View>
53
  );
54
}
55

56
const styles = StyleSheet.create({
57
  grid: {
58
    flexDirection: 'row',
59
    flexWrap: 'wrap',
60
    gap: 10,
61
    paddingHorizontal: 16,
62
    paddingVertical: 8,
63
  },
64
  chip: {
65
    paddingHorizontal: 16,
66
    paddingVertical: 12,
67
    borderRadius: 999,
68
    backgroundColor: '#fff',
69
    borderWidth: 1.5,
70
    borderColor: 'transparent',
71
  },
72
  chipActive: {
73
    backgroundColor: Colors.light.tint + '1A', // ~10% opacity tint background
74
    borderColor: Colors.light.tint,
75
  },
76
  chipInner: {
77
    flexDirection: 'row',
78
    alignItems: 'center',
79
    gap: 8,
80
  },
81
  iconWrapper: {
82
    width: 20,
83
    height: 20,
84
    alignItems: 'center',
85
    justifyContent: 'center',
86
  },
87
  label: {
88
    fontSize: 14,
89
    fontWeight: '500',
90
    color: '#3C3C43',
91
    letterSpacing: -0.1,
92
  },
93
  labelActive: {
94
    fontWeight: '600',
95
  },
96
});