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