Attention
Attention shows information that highlight content.
Web only
For the iOS and Android implementation of Attention, see Components - Callout and Components - Tooltip.
React
releasedVue
releasedElements
releasedAndroid
unsupportediOS
unsupportedExamples
Usage
Design Guidelines
See Figma:
Warp - Components / Callout
Warp - Components / Tooltip
Warp - Components / Popover
Questions?
Feel free to ask any questions on usage in the Warp DS Slack channel: #nmp-warp-design-system
Frameworks
Import
You can import the component like so:
import { Attention } from '@warp-ds/react'
or import it individually to optimize your JS bundle size by adding only the components you need:
import { Attention } from '@warp-ds/react/components/attention'
Visual options
Callout
<div>
<Box info>
<h1 aria-details='callout-bubbletext'>I am a box full of info</h1>
</Box>
<Attention callout placement='right' isShowing={true}>
<p id='callout-bubbletext'>
I'm a callout because that box over there is new or something
</p>
</Attention>
</div>
Tooltip
function Example() {
const [show, setShow] = React.useState(false)
const targetEl = React.useRef()
return (
<div>
<Button
ref={targetEl}
utility
aria-describedby='tooltip-bubbletext'
aria-expanded={show}
onMouseEnter={() => setShow(true)}
onMouseLeave={() => setShow(false)}
onFocus={() => setShow(true)}
onBlur={() => setShow(false)}
>
hover this for useless info
</Button>
<Attention
tooltip
placement='right'
flip={true}
targetEl={targetEl}
isShowing={show}
>
<p id='tooltip-bubbletext'>I am a tooltip</p>
</Attention>
</div>
)
}
Popover
function Example() {
const [show, setShow] = React.useState(false)
const targetEl = React.useRef()
return (
<div>
<Button
small
aria-expanded={show}
aria-controls='popover-attention-example'
aria-details='popover-bubbletext'
utility
onClick={() => setShow(!show)}
ref={targetEl}
>
Open menu
</Button>
<Attention
popover
placement='right'
flip={true}
crossAxis={true}
fallbackPlacements={['left', 'bottom', 'top']}
targetEl={targetEl}
isShowing={show}
id='popover-attention-example'
>
<ul id='popover-bubbletext'>
<li>Hello</li>
<li>World</li>
</ul>
</Attention>
</div>
)
}
Popover with icon as target element
function PopoverIconAsTargetEl() {
const [show, setShow] = React.useState(false)
const containerRef = React.useRef<HTMLDivElement>(null)
const targetEl = React.useRef<any>(null);
React.useEffect(() => {
function onBlurHandler(e) {
if (containerRef.current && !containerRef.current.contains(e.target)) {
setShow(false)
}
}
document.addEventListener('mousedown', onBlurHandler)
return () => {
document.removeEventListener('mousedown', onBlurHandler)
}
})
return (
<div className='flex items-center justify-center'>
<div ref={containerRef}>
<Button
small
aria-expanded={show}
aria-controls='popover-icon-target-el-attention-example'
utility
quiet
onClick={() => setShow(!show)}
className='w-max mb-0'
ref={targetEl}
>
<IconInfo16 />
</Button>
<Attention
popover
placement='right-end'
distance={-8}
skidding={27}
targetEl={targetEl}
isShowing={show}
>
<ul className='bg-white w-full text-center'>
<li
tabIndex={0}
className='p-2 px-40 hover:bg-blue-200 hover:text-blue-500 cursor-pointer'
>
Hello
</li>
<li
tabIndex={0}
className='p-2 px-40 hover:bg-blue-200 hover:text-blue-500 cursor-pointer'
>
World
</li>
</ul>
</Attention>
</div>
</div>
)
}
Highlight (with optional close button)
function DismissibleHighlight() {
const [show, setShow] = React.useState(false)
const targetEl = React.useRef()
return (
<div className='flex flex-col justify-between h-[200]'>
<Button
small
aria-expanded={show}
aria-controls='highlight-attention-example'
utility
onClick={() => setShow(!show)}
className='w-max mb-0'
>
Show an onboarding hint
</Button>
<div>
<div ref={targetEl} className="w-2/3" aria-details='highlight-bubble-text'>
<Box info>
<h1>I am a box full of info</h1>
</Box>
</div>
<Attention
highlight
canClose
onDismiss={() => setShow(false)}
placement='bottom'
isShowing={show}
targetEl={targetEl}
flip={true}
fallbackPlacements={['top']}
id='highlight-attention-example'
>
<p id='highlight-bubble-text'>
I'm a highlight that can dismiss itself
</p>
</Attention>
</div>
</div>
)
}
Flip prop
The attention component uses the Floating-ui library to calculate its position. By default, the flip
prop is set to false
, which means that the attention component will not flip its position to the opposite side.
Try to scroll and see how the attention component doesn't move:
When flip
is set to true
, it will instead trigger Floating-ui's flip() function that will make sure that the attention component stays in viewport, by flipping it to the opposite side.
Try to scroll and see how the attention component moves its position to the opposite side to keep itself in viewport as long as possible:
CrossAxis prop
The crossAxis
prop decides whether to check for cross axis overflow or not when flip
is set to true
. By default, the crossAxis
prop is set to false
, which means that the attention component will ignore cross axis overflow.
Read more: Floating-ui crossAxis
FallbackPlacements prop
By default, fallbackPlacements
is undefined
. If flip
is set to true
, then you have the option to also use fallbackPlacements
prop and pass in an array of preferred placements that you want the attention component to try if there is no longer any space left to position it to the initial placement
, e.g. ['right', 'top']
.
Read more: Floating-ui fallbackPlacements
Try to scroll and see how the attention component's position starts at the bottom
but then moves to the right
and then to the top
:
Accessibility
The attention component handles accessibility automatically by wrapping its slotted content with a div
that has a default role
attribute (role="tooltip"
for tooltip and role="img"
otherwise), and a default localized aria-label
.
It is possible to remove the default role
and override the aria-label
attribute:
<Attention tooltip placement='right' isShowing={true} role='' aria-label=''>
<p id='tooltip-bubbletext' role='tooltip'>
I'm a tooltip speech bubble with overridden role and aria-label attributes
pointing up.
</p>
</Attention>
If the user chooses to remove the role
and/or override the aria-label
attributes then it is important to also add aria-details
on the target element.
Read more: MDN aria-details
Props
Required props
name | type | default | notes |
---|---|---|---|
targetEl | MutableRefObject | The reference container to which the Attention component is positioned relative to. Optional if |
Optional Props
name | type | default | notes |
---|---|---|---|
isShowing | boolean | false | Whether Attention component is shown Used for tooltip |
placement | 'top-start' | 'top' | 'top-end' | 'bottom-start' | 'bottom' | 'bottom-end' | 'left-start' | 'left' | 'left-end' | 'right-start' | 'right' | 'right-end' | 'bottom' | Placement according to the target element. The arrow will point to the opposite side of this position |
children | Element | Element[] | Elements inside of the Attention component | |
className | string | Extend the Attention component container styling | |
tooltip | boolean | false | Whether Attention component is rendered as a tooltip |
callout | boolean | false | Whether Attention component is rendered as a callout |
popover | boolean | false | Whether Attention component is rendered as a popover |
highlight | boolean | false | Whether Attention component is rendered as a highlight |
role | string | Allows the user to remove the default ARIA role attribute for the Attention component, by supplying an empty role ( | |
aria-label | string | Allows the user to override the default aria-label attribute for the Attention component | |
noArrow | boolean | false | Render Attention component without arrow |
canClose | boolean | false | Whether a close button is shown |
distance | number | 8 | Distance from which to offset the Attention component from the targetEl vertically |
skidding | number | 0 | Distance from which to offset the Attention component along its targetEl horizontally. |
flip | boolean | false | Whether Attention element should flip its placement in order to keep it in view |
crossAxis | boolean | false | Whether Attention element should ignore cross axis overflow when flip is enabled. Can only be used when |
fallbackPlacements | array | undefined | Choose which preferred placements the Attention element should flip to. Can only be used when |
Events
name | when | ||
---|---|---|---|
onDismiss | () => void | Called when user clicks the close button or presses Escape when the button is in focus. |