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