1import * as React from 'react'
2import * as Kb from '../../../../../common-adapters'
3import * as Styles from '../../../../../styles'
4import * as Types from '../../../../../constants/types/chat2'
5
6const skinTones: Array<undefined | Types.EmojiSkinTone> = [
7  undefined,
8  '1F3FB',
9  '1F3FC',
10  '1F3FD',
11  '1F3FE',
12  '1F3FF',
13]
14
15const circle = (skinTone: undefined | Types.EmojiSkinTone, isExpanded: boolean, outerCircle: boolean) => {
16  return (
17    <Kb.Box style={{position: 'relative'}}>
18      {outerCircle && <Kb.Box style={styles.circleOuter} />}
19      <Kb.Box
20        style={Styles.collapseStyles([
21          !isExpanded && styles.circleCollapsed,
22          isExpanded && styles.circleExpanded,
23          {backgroundColor: Types.SkinToneToDotColor(skinTone)},
24        ])}
25      ></Kb.Box>
26    </Kb.Box>
27  )
28}
29
30type Props = {
31  currentSkinTone?: Types.EmojiSkinTone
32  onExpandChange?: (expanded: boolean) => void
33  setSkinTone: (skinTone: undefined | Types.EmojiSkinTone) => void
34}
35
36const reorderedSkinTones = (props: Props): Array<undefined | Types.EmojiSkinTone> =>
37  Styles.isMobile
38    ? skinTones
39    : [props.currentSkinTone, ...skinTones.filter(st => st !== props.currentSkinTone)]
40
41const SkinTonePicker = (props: Props) => {
42  const [expanded, _setExpanded] = React.useState(false)
43  const setExpanded = (toSet: boolean) => {
44    _setExpanded(toSet)
45    props.onExpandChange?.(toSet)
46  }
47  const optionSkinTones = reorderedSkinTones(props).map((skinTone, index) => (
48    <Kb.ClickableBox
49      key={index.toString()}
50      style={styles.dotContainerExpanded}
51      onClick={() => {
52        props.setSkinTone(skinTone)
53        setExpanded(false)
54      }}
55    >
56      {circle(skinTone, true, Styles.isMobile && skinTone === props.currentSkinTone)}
57    </Kb.ClickableBox>
58  ))
59  return Styles.isMobile ? (
60    expanded ? (
61      <Kb.Box2
62        direction="horizontal"
63        fullWidth={true}
64        alignItems="center"
65        style={styles.optionSkinTonesContainerMobile}
66      >
67        {optionSkinTones}
68      </Kb.Box2>
69    ) : (
70      <Kb.ClickableBox onClick={() => setExpanded(true)}>
71        <Kb.Box2 direction="horizontal" alignItems="center" gap="tiny">
72          {circle(props.currentSkinTone, false, false)}
73          <Kb.Text type="BodySmallSemibold">Skin tone</Kb.Text>
74        </Kb.Box2>
75      </Kb.ClickableBox>
76    )
77  ) : (
78    <Kb.Box style={styles.relative}>
79      {expanded ? (
80        <Kb.Animated to={{height: 126}} from={{height: 26}} config={reactSprintConfig}>
81          {({height}) => (
82            <Kb.Box2 direction="vertical" style={Styles.collapseStyles([styles.popupContainer, {height}])}>
83              {optionSkinTones}
84            </Kb.Box2>
85          )}
86        </Kb.Animated>
87      ) : (
88        <Kb.WithTooltip tooltip="Skin tone" containerStyle={styles.absolute}>
89          <Kb.ClickableBox style={styles.dotContainerDesktop} onClick={() => setExpanded(true)}>
90            {circle(props.currentSkinTone, false, false)}
91          </Kb.ClickableBox>
92        </Kb.WithTooltip>
93      )}
94      <Kb.Box style={styles.dotPlaceholder} />
95    </Kb.Box>
96  )
97}
98
99export default SkinTonePicker
100
101const styles = Styles.styleSheetCreate(() => ({
102  absolute: {position: 'absolute'},
103  circleCollapsed: {
104    borderRadius: Styles.globalMargins.small / 2,
105    height: Styles.globalMargins.small,
106    width: Styles.globalMargins.small,
107  },
108  circleExpanded: Styles.platformStyles({
109    isElectron: {
110      borderRadius: Styles.globalMargins.small / 2,
111      height: Styles.globalMargins.small,
112      width: Styles.globalMargins.small,
113    },
114    isMobile: {
115      borderRadius: (Styles.globalMargins.small + Styles.globalMargins.xtiny) / 2,
116      height: Styles.globalMargins.small + Styles.globalMargins.xtiny,
117      width: Styles.globalMargins.small + Styles.globalMargins.xtiny,
118    },
119  }),
120  circleOuter: {
121    backgroundColor: Styles.globalColors.white,
122    borderColor: Styles.globalColors.black_10,
123    borderRadius: (Styles.globalMargins.mediumLarge - Styles.globalMargins.xxtiny) / 2,
124    borderStyle: 'solid',
125    borderWidth: 1,
126    height: Styles.globalMargins.mediumLarge - Styles.globalMargins.xxtiny,
127    left: -5,
128    position: 'absolute',
129    top: -5,
130    width: Styles.globalMargins.mediumLarge - Styles.globalMargins.xxtiny,
131  },
132  dotContainerDesktop: {
133    padding: Styles.globalMargins.tiny,
134  },
135  dotContainerExpanded: {
136    padding: Styles.globalMargins.xxtiny,
137  },
138  dotPlaceholder: {
139    height: Styles.globalMargins.small * 2,
140    width: Styles.globalMargins.small * 2,
141  },
142  optionSkinTonesContainerMobile: {
143    justifyContent: 'space-between',
144  },
145  popupContainer: {
146    backgroundColor: Styles.globalColors.white,
147    borderColor: Styles.globalColors.black_10,
148    borderRadius: Styles.globalMargins.small,
149    borderStyle: 'solid',
150    borderWidth: 1,
151    marginLeft: Styles.globalMargins.xtiny - 1,
152    marginTop: Styles.globalMargins.xtiny - 1,
153    overflow: 'hidden',
154    padding: Styles.globalMargins.xxtiny,
155    position: 'absolute',
156    zIndex: 1,
157  },
158  relative: {position: 'relative'},
159}))
160
161const reactSprintConfig = {clamp: true, friction: 20, tension: 210}
162