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 alignItems="center" display="flex" height="100%" justifyContent="center" padding={8} > <Fragment> <TapArea accessibilityControls="menu" accessibilityExpanded={selected} accessibilityHaspopup accessibilityLabel="Open the options menu" onTap={() => setSelected(!selected)} > <Box ref={anchorRef} alignItems="center" borderStyle="sm" display="inlineBlock" padding={2} rounding={1} > <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 align="center" weight="bold"> Menu </Text> </Flex> </Box> </TapArea> {selected && ( <Layer> <Popover anchor={anchorRef.current} idealDirection="down" onDismiss={() => setSelected(false)} positionRelativeToAnchor={false} size="md" > <Box direction="column" display="flex" id="menu" 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
Be sure to localize all text strings. Note that localization can lengthen text by 20 to 30 percent.
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 alignItems="center" display="flex" height="100%" justifyContent="center" padding={8} > <Box width={200}> <TapArea onTap={() => setTouches(touches + 1)} rounding={2}> <Box borderStyle="sm" color="selected" rounding={4}> <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 align="center" color="subtle"> 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 alignItems="center" display="flex" height="100%" justifyContent="center" padding={8} > <Flex alignItems="start" direction="column" gap={{ column: 6, row: 0 }}> <Flex gap={6} wrap> <TapArea disabled={disabled} onTap={() => setTouches(touches + 1)} tabIndex={tabIndex ? -1 : 0} tapStyle={compressed} > <Box borderStyle="lg" column={12} padding={3} 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 id="compress-buttons" onChange={() => setCompressed(compressed === 'compress' ? 'none' : 'compress') } switched={compressed === 'compress'} /> <Box flex="grow" paddingX={2}> <Label htmlFor="compress-buttons"> <Text>Compress TapArea</Text> </Label> </Box> </Flex> <Flex gap={{ column: 0, row: 2 }}> <Switch id="disable-buttons" onChange={() => setDisabled(!disabled)} switched={disabled} /> <Box flex="grow" paddingX={2}> <Label htmlFor="disable-buttons"> <Text>Disable TapArea</Text> </Label> </Box> </Flex> <Flex gap={{ column: 0, row: 2 }}> <Switch id="unreachable-buttons" onChange={() => setTabIndex(!tabIndex)} switched={tabIndex} /> <Box flex="grow" paddingX={2}> <Label htmlFor="unreachable-buttons"> <Text>Remove from keyboard navigation with tabIndex</Text> </Label> </Box> </Flex> </Flex> </Box> ); }
Focus style
import { Box, Flex, TapArea, Text } from 'gestalt'; export default function TapAreaExample() { return ( <Box padding={8} width="100%"> <Flex gap={6} width="100%"> <Flex direction="column" gap={6} width="100%"> <Box alignItems="center" borderStyle="sm" color="light" display="flex" height={150} justifyContent="center" width={150} > <TapArea focusColor="lightBackground" fullHeight={false} fullWidth={false} > <Box height={100} width={100}> <Text color="dark" size="100"> focusColor=lightBackground </Text> </Box> </TapArea> </Box> <Box alignItems="center" borderStyle="sm" color="dark" display="flex" height={150} justifyContent="center" width={150} > <TapArea focusColor="darkBackground" fullHeight={false} fullWidth={false} > <Box height={100} width={100}> <Text color="light" size="100"> focusColor=darkBackground </Text> </Box> </TapArea> </Box> </Flex> <Flex direction="column" gap={6} width="100%"> <Box alignItems="center" borderStyle="sm" color="light" display="flex" height={150} justifyContent="center" width={150} > <TapArea focusColor="lightBackground" fullHeight={false} fullWidth={false} innerFocusColor="default" > <Box height={100} width={100}> <Text color="dark" size="100"> focusColor=lightBackground & innerFocusColor=default </Text> </Box> </TapArea> </Box> <Box alignItems="center" borderStyle="sm" color="dark" display="flex" height={150} justifyContent="center" width={150} > <TapArea focusColor="darkBackground" fullHeight={false} fullWidth={false} innerFocusColor="default" > <Box height={100} width={100}> <Text color="light" size="100"> focusColor=darkBackground & innerFocusColor=default </Text> </Box> </TapArea> </Box> </Flex> <Flex direction="column" gap={6} width="100%"> <Box alignItems="center" borderStyle="sm" color="light" display="flex" height={150} justifyContent="center" width={150} > <TapArea focusColor="lightBackground" fullHeight={false} fullWidth={false} innerFocusColor="inverse" > <Box height={100} width={100}> <Text color="dark" size="100"> focusColor=lightBackground & innerFocusColor=inverse </Text> </Box> </TapArea> </Box> <Box alignItems="center" borderStyle="sm" color="dark" display="flex" height={150} justifyContent="center" width={150} > <TapArea focusColor="darkBackground" fullHeight={false} fullWidth={false} innerFocusColor="inverse" > <Box height={100} width={100}> <Text color="light" size="100"> focusColor=darkBackground & innerFocusColor=inverse </Text> </Box> </TapArea> </Box> </Flex> </Flex> </Box> ); }
Height & width
import { Box, Flex, TapArea, Text } from 'gestalt'; export default function Example() { return ( <Box alignItems="center" display="flex" height="100%" justifyContent="center" padding={8} > <Flex gap={6} height={250} maxWidth={500} wrap> <Box borderStyle="sm" height="100%" margin={3} width="100%"> <TapArea fullHeight> <Box color="secondary" height="100%"> <Text align="center">Full parent height</Text> </Box> </TapArea> </Box> <Box borderStyle="sm" height="100%" margin={3} width="100%"> <TapArea> <Box color="secondary" height="100%"> <Text align="center">Child height only</Text> </Box> </TapArea> </Box> </Flex> </Box> ); }
import { Box, TapArea } from 'gestalt'; export default function Example() { return ( <Box color="secondary" height="100%" width="100%"> <TapArea fullHeight fullWidth onTap={() => {}} /> </Box> ); }
Inline usage
import { Box, Flex, TapArea, Text } from 'gestalt'; export default function Example() { return ( <Box alignItems="center" display="flex" height="100%" justifyContent="center" padding={8} > <Box color="warningBase" height={250} maxWidth={500} padding={3}> <Flex direction="column" gap={{ column: 6, row: 0 }}> <Flex.Item> <Text color="inverse" inline> Other content </Text> <Box borderStyle="sm" column={6} margin={3}> <TapArea> <Box color="secondary" height="100%"> <Text align="center">Default behavior (block)</Text> </Box> </TapArea> </Box> </Flex.Item> <Flex.Item> <Text color="inverse" inline> Other content </Text> <Box borderStyle="sm" column={6} display="inlineBlock" margin={3}> <TapArea> <Box color="secondary" height="100%"> <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
Change the cursor on TapArea for different click interactions
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. |
Internal documentation
Related
TapAreaLink
Use TapAreaLink when a link is needed instead of an action.