1import { css } from '@emotion/react'; 2import { Button, shadows, theme } from '@expo/styleguide'; 3import { spacing } from '@expo/styleguide-base'; 4import { SearchSmIcon } from '@expo/styleguide-icons'; 5import { Dispatch, SetStateAction, useEffect, useState } from 'react'; 6 7import { isAppleDevice } from './utils'; 8 9import { CALLOUT, KBD } from '~/ui/components/Text'; 10 11type Props = { 12 setOpen: Dispatch<SetStateAction<boolean>>; 13}; 14 15export const CommandMenuTrigger = ({ setOpen }: Props) => { 16 const [isMac, setIsMac] = useState<boolean | null>(null); 17 18 useEffect(() => { 19 setIsMac(typeof navigator !== 'undefined' && isAppleDevice()); 20 }, []); 21 22 useEffect(() => { 23 if (isMac !== null) { 24 const keyDownListener = (e: KeyboardEvent) => { 25 if (e.key === 'k' && (isMac ? e.metaKey : e.ctrlKey)) { 26 e.preventDefault(); 27 setOpen(open => !open); 28 } 29 }; 30 document.addEventListener('keydown', keyDownListener, false); 31 return () => document.removeEventListener('keydown', keyDownListener); 32 } 33 }, [isMac]); 34 35 return ( 36 <Button theme="secondary" css={buttonStyle} onClick={() => setOpen(true)}> 37 <SearchSmIcon /> 38 <CALLOUT theme="secondary" crawlable={false}> 39 Search 40 </CALLOUT> 41 {isMac !== null && ( 42 <div className="ml-auto max-lg-gutters:hidden"> 43 <KBD>{isMac ? '⌘' : 'Ctrl'}</KBD> <KBD>K</KBD> 44 </div> 45 )} 46 </Button> 47 ); 48}; 49 50const buttonStyle = css({ 51 backgroundColor: theme.background.default, 52 padding: `0 ${spacing[3]}px 0 ${spacing[2.5]}px`, 53 borderColor: theme.border.default, 54 boxShadow: shadows.xs, 55 marginBottom: spacing[2.5], 56 minHeight: spacing[10], 57 display: 'flex', 58 59 '&:focus': { 60 boxShadow: shadows.xs, 61 }, 62 63 '> span': { 64 width: '100%', 65 gap: spacing[2], 66 alignItems: 'center', 67 }, 68 69 kbd: { 70 height: 20, 71 lineHeight: '19px', 72 }, 73}); 74