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