1import { css } from '@emotion/react';
2import { useTheme, theme, shadows, typography } from '@expo/styleguide';
3import { borderRadius, breakpoints, spacing } from '@expo/styleguide-base';
4import {
5  ChevronDownIcon,
6  Moon01SolidIcon,
7  SunSolidIcon,
8  Contrast02SolidIcon,
9} from '@expo/styleguide-icons';
10import { useEffect, useState } from 'react';
11
12export const ThemeSelector = () => {
13  const { themeName, setAutoMode, setDarkMode, setLightMode } = useTheme();
14  const [isLoaded, setLoaded] = useState(false);
15
16  useEffect(function didMount() {
17    setLoaded(true);
18  }, []);
19
20  return (
21    <div className="relative">
22      <select
23        aria-label="Theme selector"
24        title="Select theme"
25        css={selectStyle}
26        value={themeName}
27        onChange={e => {
28          const option = e.target.value;
29          if (option === 'auto') setAutoMode();
30          if (option === 'dark') setDarkMode();
31          if (option === 'light') setLightMode();
32        }}>
33        <option value="auto">Auto</option>
34        <option value="light">Light</option>
35        <option value="dark">Dark</option>
36      </select>
37      {isLoaded && (
38        <>
39          {themeName === 'auto' && <Contrast02SolidIcon className={ICON_CLASSES} />}
40          {themeName === 'dark' && <Moon01SolidIcon className={ICON_CLASSES} />}
41          {themeName === 'light' && <SunSolidIcon className={ICON_CLASSES} />}
42        </>
43      )}
44      <ChevronDownIcon className="icon-xs text-icon-secondary absolute right-2 top-3 pointer-events-none" />
45    </div>
46  );
47};
48
49const ICON_CLASSES = 'icon-sm absolute left-2.5 top-2.5 text-icon-secondary pointer-events-none';
50
51const selectStyle = css`
52  ${typography.fontSizes[14]}
53  display: flex;
54  align-items: center;
55  justify-content: center;
56  height: 36px;
57  color: ${theme.text.default};
58  line-height: 1.3;
59  padding: 0;
60  width: 50px;
61  margin: 0;
62  border: 1px solid ${theme.border.default};
63  box-shadow: ${shadows.xs};
64  border-radius: ${borderRadius.md}px;
65  -moz-appearance: none;
66  -webkit-appearance: none;
67  appearance: none;
68  background-color: ${theme.background.default};
69  cursor: pointer;
70  text-indent: -9999px;
71
72  :hover {
73    background-color: ${theme.background.element};
74  }
75
76  :focus-visible {
77    background-color: ${theme.background.element};
78  }
79
80  @media screen and (max-width: ${(breakpoints.medium + breakpoints.large) / 2}px) {
81    width: auto;
82    min-width: 100px;
83    padding: 0 ${spacing[2]}px;
84    padding-left: ${spacing[8]}px;
85    color: ${theme.text.secondary};
86    text-indent: 0;
87  }
88`;
89