packages/react-aria/docs/tooltip/useTooltipTrigger.mdx
{/* Copyright 2020 Adobe. All rights reserved. This file is licensed to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */}
import {Layout} from '@react-spectrum/docs'; export default Layout;
import docs from 'docs:@react-aria/tooltip'; import statelyDocs from 'docs:@react-stately/tooltip'; import {HeaderInfo, FunctionAPI, TypeContext, InterfaceType, TypeLink, PageDescription} from '@react-spectrum/docs'; import packageData from '@react-aria/tooltip/package.json'; import Anatomy from './anatomy.svg';
<PageDescription>{docs.exports.useTooltipTrigger.description}</PageDescription>
<HeaderInfo packageData={packageData} componentNames={['useTooltipTrigger', 'useTooltip']} sourceData={[ {type: 'W3C', url: 'https://www.w3.org/TR/wai-aria-1.2/#tooltip'} ]} />
The HTML title attribute can be used to create a tooltip, but it cannot be styled. Custom styled
tooltips can be hard to build in an accessible way. useTooltipTrigger and useTooltip help build
fully accessible tooltips that can be styled as needed.
A tooltip consists of two parts: the trigger element and the tooltip itself. Users may reveal the tooltip by hovering or focusing the trigger.
useTooltipTrigger returns props to be spread onto its target trigger and the tooltip:
<TypeContext.Provider value={docs.links}> <InterfaceType properties={docs.links[docs.exports.useTooltipTrigger.return.id].properties} /> </TypeContext.Provider>
useTooltip returns props to be spread onto the tooltip:
<TypeContext.Provider value={docs.links}> <InterfaceType properties={docs.links[docs.exports.useTooltip.return.id].properties} /> </TypeContext.Provider>
Tooltip state is managed by the <TypeLink links={statelyDocs.links} type={statelyDocs.exports.useTooltipTriggerState} />
hook in @react-stately/tooltip. The state object should be passed as an option to useTooltipTrigger and useTooltip.
This example implements a Tooltip that renders in an absolute position next to its target. The <TypeLink links={docs.links} type={docs.exports.useTooltip} /> hook applies the correct ARIA attributes to the tooltip, and useTooltipTrigger associates it to the trigger element.
Two instances of the example are rendered to demonstrate the behavior of the delay on hover. If you hover over the first button, the tooltip will be shown after a delay. Hovering over the second button shows the tooltip immediately. If you wait for a delay before hovering another element, the delay restarts.
import {useTooltip, useTooltipTrigger} from '@react-aria/tooltip';
import {useTooltipTriggerState} from '@react-stately/tooltip';
import {mergeProps} from '@react-aria/utils';
function Tooltip({state, ...props}) {
let {tooltipProps} = useTooltip(props, state);
return (
<span
style={{
position: 'absolute',
left: '5px',
top: '100%',
maxWidth: 150,
marginTop: '10px',
backgroundColor: 'white',
color: 'black',
padding: '5px',
border: '1px solid gray'
}}
{...mergeProps(props, tooltipProps)} >
{props.children}
</span>
);
}
function TooltipButton(props) {
let state = useTooltipTriggerState(props);
let ref = React.useRef(null);
// Get props for the trigger and its tooltip
let {triggerProps, tooltipProps} = useTooltipTrigger(props, state, ref);
return (
<span style={{position: 'relative'}}>
<button ref={ref} {...triggerProps} style={{fontSize: 18}} onClick={() => alert('Pressed button')}>{props.children}</button>
{state.isOpen && (
<Tooltip state={state} {...tooltipProps}>{props.tooltip}</Tooltip>
)}
</span>
);
}
<TooltipButton tooltip="Edit">✏️</TooltipButton>
<TooltipButton tooltip="Delete">🚮</TooltipButton>
The following examples show how to use the TooltipButton component created in the above example.
Tooltips appear after a short delay when hovering the trigger, or instantly when using keyboard focus. This delay can be adjusted for hover using the delay prop.
<TooltipButton tooltip="Save" delay={0}>💾</TooltipButton>
Tooltips disappear after a short delay when no longer hovering the trigger, or instantly when using keyboard focus. This delay can be adjusted for hover using the closeDelay prop.
<TooltipButton tooltip="Refresh" closeDelay={0}>🔄</TooltipButton>
By default, tooltips appear both on hover and on focus. The trigger prop can be set to "focus" to display the tooltip only on focus, and not on hover.
<TooltipButton tooltip="Burn CD" trigger="focus">💿</TooltipButton>
The open state of the tooltip can be controlled via the defaultOpen and isOpen props.
function Example() {
let [isOpen, setOpen] = React.useState(false);
return (
<>
<p>Tooltip is {isOpen ? 'showing' : 'not showing'}</p>
<TooltipButton tooltip="Notifications" isOpen={isOpen} onOpenChange={setOpen}>📣</TooltipButton>
</>
);
}
The isDisabled prop can be provided to a TooltipTrigger to disable the tooltip, without disabling the trigger it displays on.
<TooltipButton tooltip="Print" isDisabled>🖨</TooltipButton>
In right-to-left languages, tooltips should be mirrored across trigger. Ensure that your CSS and overlay positioning (if any) accounts for this.