Props
Accessibility
ARIA attributes
import { Fragment, useRef, useState } from 'react'; import { Box, Flex, Image, Layer, Mask, Popover, TapArea, Text } from 'gestalt'; export default function MenuButtonExample() { const [selected, setSelected] = useState(false); const anchorRef = useRef(null); return ( <Box padding={8} height="100%" display="flex" alignItems="center" justifyContent="center" > <Fragment> <TapArea accessibilityLabel="Open the options menu" accessibilityControls="menu" accessibilityExpanded={selected} accessibilityHaspopup onTap={() => setSelected(!selected)} > <Box ref={anchorRef} borderStyle="sm" display="inlineBlock" alignItems="center" rounding={1} padding={2} > <Flex gap={{ column: 0, row: 2 }}> <Box height={50} width={50}> <Mask rounding={1}> <Image alt="Antelope Canyon" naturalHeight={1} naturalWidth={1} src="https://i.ibb.co/FY2MKr5/stock6.jpg" /> </Mask> </Box> <Text weight="bold" align="center"> Menu </Text> </Flex> </Box> </TapArea> {selected && ( <Layer> <Popover anchor={anchorRef.current} idealDirection="down" onDismiss={() => setSelected(false)} positionRelativeToAnchor={false} size="md" > <Box id="menu" direction="column" display="flex" padding={2}> <Box padding={2}> <Text weight="bold">Option 1</Text> </Box> <Box padding={2}> <Text weight="bold">Option 2</Text> </Box> </Box> </Popover> </Layer> )} </Fragment> </Box> ); }
Localization
Localize the accessibilityLabel.
Variants
Link/Button within TapArea
import { useState } from 'react'; import { Box, Image, Link, Mask, TapArea, Text } from 'gestalt'; export default function TapAreaExample() { const [touches, setTouches] = useState(0); return ( <Box padding={8} height="100%" display="flex" alignItems="center" justifyContent="center" > <Box width={200}> <TapArea onTap={() => setTouches(touches + 1)} rounding={2}> <Box color="selected" rounding={4} borderStyle="sm"> <Mask rounding={2}> <Image alt="Antelope Canyon" naturalHeight={1} naturalWidth={1} src="https://i.ibb.co/DwYrGy6/stock14.jpg" /> </Mask> <Box paddingY={2}> <Link href="https://www.pinterest.com/search/pins/?rs=ac&len=2&q=antelope%20canyon%20arizona&eq=Antelope%20Canyon" onClick={({ event }) => event.stopPropagation()} rounding="pill" target="blank" > <Text align="center" color="inverse"> Find More on Pinterest </Text> </Link> </Box> </Box> </TapArea> <Box paddingY={2}> <Text color="subtle" align="center"> Touched {touches} {touches === 1 ? 'time' : 'times'} </Text> </Box> </Box> </Box> ); }
If you have a Link
or Button
inside of TapArea, you can apply e.stopPropagation()
so the onTap
doesn't get triggered.
TapArea with link interaction can be paired with GlobalEventsHandlerProvider. See GlobalEventsHandlerProvider to learn more about link navigation.
Compress behavior
import { useState } from 'react'; import { Box, Flex, Image, Label, Mask, Switch, TapArea, Text } from 'gestalt'; export default function Example() { const [disabled, setDisabled] = useState(false); const [compressed, setCompressed] = useState('compress'); const [touches, setTouches] = useState(0); const [tabIndex, setTabIndex] = useState(false); return ( <Box padding={8} height="100%" display="flex" alignItems="center" justifyContent="center" > <Flex alignItems="start" direction="column" gap={{ column: 6, row: 0 }}> <Flex gap={6} wrap> <TapArea tapStyle={compressed} disabled={disabled} onTap={() => setTouches(touches + 1)} tabIndex={tabIndex ? -1 : 0} > <Box padding={3} column={12} borderStyle="lg" width={200}> <Mask rounding={2}> <Image alt="Antelope Canyon" naturalHeight={1} naturalWidth={1} src="https://i.ibb.co/DwYrGy6/stock14.jpg" /> </Mask> <Text align="center"> Touched {touches} {touches === 1 ? 'time' : 'times'} </Text> </Box> </TapArea> </Flex> <Flex gap={{ column: 0, row: 2 }}> <Switch onChange={() => setCompressed(compressed === 'compress' ? 'none' : 'compress') } id="compress-buttons" switched={compressed === 'compress'} /> <Box paddingX={2} flex="grow"> <Label htmlFor="compress-buttons"> <Text>Compress TapArea</Text> </Label> </Box> </Flex> <Flex gap={{ column: 0, row: 2 }}> <Switch onChange={() => setDisabled(!disabled)} id="disable-buttons" switched={disabled} /> <Box paddingX={2} flex="grow"> <Label htmlFor="disable-buttons"> <Text>Disable TapArea</Text> </Label> </Box> </Flex> <Flex gap={{ column: 0, row: 2 }}> <Switch onChange={() => setTabIndex(!tabIndex)} id="unreachable-buttons" switched={tabIndex} /> <Box paddingX={2} flex="grow"> <Label htmlFor="unreachable-buttons"> <Text>Remove from keyboard navigation with tabIndex</Text> </Label> </Box> </Flex> </Flex> </Box> ); }
Height & width
import { Box, Flex, TapArea, Text } from 'gestalt'; export default function Example() { return ( <Box padding={8} height="100%" display="flex" alignItems="center" justifyContent="center" > <Flex gap={6} wrap maxWidth={500} height={250}> <Box borderStyle="sm" margin={3} width="100%" height="100%"> <TapArea fullHeight> <Box height="100%" color="secondary"> <Text align="center">Full parent height</Text> </Box> </TapArea> </Box> <Box borderStyle="sm" margin={3} width="100%" height="100%"> <TapArea> <Box height="100%" color="secondary"> <Text align="center">Child height only</Text> </Box> </TapArea> </Box> </Flex> </Box> ); }
import { Box, TapArea } from 'gestalt'; export default function Example() { return ( <Box height="100%" width="100%" color="secondary"> <TapArea fullHeight fullWidth onTap={() => {}} /> </Box> ); }
Inline usage
import { Box, Flex, TapArea, Text } from 'gestalt'; export default function Example() { return ( <Box padding={8} height="100%" display="flex" alignItems="center" justifyContent="center" > <Box color="warningBase" height={250} padding={3} maxWidth={500}> <Flex direction="column" gap={{ column: 6, row: 0 }}> <Flex.Item> <Text color="inverse" inline> Other content </Text> <Box borderStyle="sm" margin={3} column={6}> <TapArea> <Box height="100%" color="secondary"> <Text align="center">Default behavior (block)</Text> </Box> </TapArea> </Box> </Flex.Item> <Flex.Item> <Text color="inverse" inline> Other content </Text> <Box borderStyle="sm" display="inlineBlock" margin={3} column={6}> <TapArea> <Box height="100%" color="secondary"> <Text align="center">Inline behavior</Text> </Box> </TapArea> </Box> </Flex.Item> </Flex> </Box> </Box> ); }
While TapArea doesn't provide an inline
prop, this behavior can be achieved by wrapping with <Box display="inlineBlock">
.
Mouse cursor
import { Box, Flex, TapArea, Text } from 'gestalt'; export default function TapAreaExample() { return ( <Flex wrap gap={2}> {[ 'copy', 'grab', 'grabbing', 'move', 'noDrop', 'pointer', 'zoomIn', 'zoomOut', ].map((cursor) => ( <TapArea key={cursor} mouseCursor={cursor} fullWidth={false}> <Box borderStyle="lg" padding={4} width={250} height={100}> <Text size="200">hover here </Text> <Text size="200" weight="bold"> {`mouseCursor="${cursor}"`} </Text> </Box> </TapArea> ))} </Flex> ); }
Rounding
In ordee to observe TapArea's border radius, focus on each component below navigating with the keyboard. fullWidth={false}
might be required to wrap to the children component. Make the sure the children components match the rounding as well.
Component quality checklist
Quality item | Status | Status description |
---|---|---|
Figma Library | Component is not currently available in Figma. | |
Responsive Web | Ready | Component responds to changing viewport sizes in web and mobile web. |
Related
GlobalEventsHandlerProvider
GlobalEventsHandlerProvider allows external link navigation control across all children components with link behavior.