Popover

Popover is a non-modal dialog that floats around a trigger.

SourceTheme Source

Popover is a non-modal dialog component that floats around a trigger.

Import#

import { Popover } from '@chakra-ui/react'

Basic Usage#

It is used to display contextual information to the user, and should be paired with a clickable trigger element.

When Popover opens, focus is sent to Popover.Content. When it closes, focus is returned to the trigger.

Tip: When using this component, ensure the children passed to Popover.Trigger is focusable and has a forwarded ref.

<Popover.Root>
<Popover.Trigger asChild>
<Button>Trigger</Button>
</Popover.Trigger>
<Popover.Positioner>
<Popover.Content>
<Popover.Arrow>
<Popover.ArrowTip />
</Popover.Arrow>
<Popover.CloseTrigger />
<Popover.Header>Confirmation!</Popover.Header>
<Popover.Body>Are you sure you want to have that milkshake?</Popover.Body>
</Popover.Content>
</Popover.Positioner>
</Popover.Root>

Rendering the Popover in a Portal#

By default, the Popover doesn't render in a Portal. To make them display in a portal, wrap the Popover.Content in a Portal

You might need to Inspect Element to see this in action. Notice that Popover.Content is rendered as a child of <body>

<Popover.Root>
<Popover.Trigger asChild>
<Button>Trigger</Button>
</Popover.Trigger>
<Portal>
<Popover.Positioner>
<Popover.Content>
<Popover.Arrow />
<Popover.Header>Header</Popover.Header>
<Popover.CloseTrigger />
<Popover.Body>
<Button colorPalette='blue'>Button</Button>
</Popover.Body>
<Popover.Footer>This is the footer</Popover.Footer>
</Popover.Content>
</Popover.Positioner>
</Portal>
</Popover.Root>

Setting the initial focused element#

By default, focus is to set to Popover.Content when it opens. Pass the initialFocusRef prop to send focus to a specific element instead.

function Demo() {
const initialFocusRef = React.useRef()
return (
<Popover.Root initialFocusRef={initialFocusRef} placement='bottom'>
<Popover.Trigger asChild>
<Button>Trigger</Button>
</Popover.Trigger>
<Popover.Positioner>
<Popover.Content color='white' bg='blue.800' borderColor='blue.800'>
<Popover.Header pt={4} fontWeight='bold' border='0'>
Manage Your Channels
</Popover.Header>
<Popover.Arrow bg='blue.800' />
<Popover.CloseTrigger />
<Popover.Body>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
eiusmod tempor incididunt ut labore et dolore.
</Popover.Body>
<Popover.Footer
border='0'
display='flex'
alignItems='center'
justifyContent='space-between'
pb={4}
>
<Box fontSize='sm'>Step 2 of 4</Box>
<Group>
<Button size='sm' colorPalette='green'>
Setup Email
</Button>
<Button size='sm' colorPalette='blue' ref={initialFocusRef}>
Next
</Button>
</Group>
</Popover.Footer>
</Popover.Content>
</Popover.Positioner>
</Popover.Root>
)
}

Setting the popover anchor#

You can wrap your component with Popover.Anchor to prevent trigger any action. The wrapped component will become a position reference. Actions will only be triggered by components inside Popover.Trigger.

function Demo() {
const [isEditing, setIsEditing] = useBoolean()
const [color, setColor] = React.useState('red')
return (
<Popover.Root
open={isEditing}
onOpen={setIsEditing.on}
onClose={setIsEditing.off}
closeOnBlur={false}
lazyMount
lazyBehavior='keepMounted'
>
<HStack>
<Popover.Anchor>
<Input
color={color}
w='auto'
display='inline-flex'
disabled={!isEditing}
defaultValue='Popover Anchor'
/>
</Popover.Anchor>
<Popover.Trigger asChild>
<Button h='40px' colorPalette='pink'>
{isEditing ? 'Save' : 'Edit'}
</Button>
</Popover.Trigger>
</HStack>
<Popover.Content>
<Popover.Body>
Colors:
<RadioGroup.Root
value={color}
onChange={(newColor) => setColor(newColor)}
>
<RadioGroup.Item value='red'>red</RadioGroup.Item>
<RadioGroup.Item value='blue'>blue</RadioGroup.Item>
<RadioGroup.Item value='green'>green</RadioGroup.Item>
<RadioGroup.Item value='purple'>purple</RadioGroup.Item>
</RadioGroup.Root>
</Popover.Body>
</Popover.Content>
</Popover.Root>
)
}

Accessing Internal state#

Chakra provides access to two internal details: open and onClose. Use the render prop pattern to gain access to them.

function Demo() {
const ref = React.useRef()
return (
<Popover.Root closeOnBlur={false} placement='left' initialFocusRef={ref}>
{(state) => (
<>
<Popover.Trigger asChild>
<Button>Click to {state.open ? 'close' : 'open'}</Button>
</Popover.Trigger>
<Portal>
<Popover.Content>
<Popover.Header>This is the header</Popover.Header>
<Popover.CloseTrigger />
<Popover.Body>
<Input ref={ref} placeholder='Enter value' />
<Box>
Hello. Nice to meet you! This is the body of the popover
</Box>
</Popover.Body>
<Popover.Footer>This is the footer</Popover.Footer>
</Popover.Content>
</Portal>
</>
)}
</Popover.Root>
)
}

Customizing the Popover#

Chakra exports all the components you need to customize the look and feel of the popover. You can change the background, arrow size, box shadow and so on.

<Popover.Root>
<Popover.Trigger asChild>
<Box
tabIndex='0'
role='button'
aria-label='Some box'
p={5}
w='120px'
bg='gray.300'
children='Click'
/>
</Popover.Trigger>
<Popover.Content bg='tomato' color='white'>
<Popover.Header fontWeight='semibold'>Customization</Popover.Header>
<Popover.Arrow bg='pink.500' />
<Popover.CloseTrigger />
<Popover.Body>
Tadaa!! The arrow color and background color is customized. Check the
props for each component.
</Popover.Body>
</Popover.Content>
</Popover.Root>

Changing the placement of the Popover#

<Popover.Root placement='top-start'>
<Popover.Trigger asChild>
<Button>Click me</Button>
</Popover.Trigger>
<Popover.Content>
<Popover.Header fontWeight='semibold'>Popover placement</Popover.Header>
<Popover.Arrow />
<Popover.CloseTrigger />
<Popover.Body>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore.
</Popover.Body>
</Popover.Content>
</Popover.Root>

Lazily mounting Popover#

By default, the Popover component renders children of Popover.Content to the DOM, meaning that invisible popover contents are still rendered but are hidden by styles.

If you want to defer rendering of popover content until that Popover is opened, you can use the lazyMount prop. This is useful if your Popover.Content needs to be extra performant, or make network calls on mount that should only happen when the component is displayed.

<Popover.Root lazyMount>
<Popover.Trigger asChild>
<Button>Click me</Button>
</Popover.Trigger>
<Popover.Content>
<Popover.Header fontWeight='semibold'>Popover placement</Popover.Header>
<Popover.Arrow />
<Popover.CloseTrigger />
<Popover.Body>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore.
</Popover.Body>
</Popover.Content>
</Popover.Root>

Accessibility#

When you see the word "trigger", it is referring to the children of Popover.Trigger

Keyboard and Focus#

  • When the popover is opened, focus is moved to the Popover.Content. If the initialFocusRef is set, then focus moves to the element with that ref.
  • When the popover is closed, focus returns to the trigger. If you set returnFocusOnClose to false, focus will not return.
  • If trigger is set to hover:
    • Focusing on or mousing over the trigger will open the popover.
    • Blurring or mousing out of the trigger will close the popover. If you move your mouse into the Popover.Content, it'll remain visible.
  • If trigger is set to click:
    • Clicking the trigger or using the Space or Enter when focus is on the trigger will open the popover.
    • Clicking the trigger again will close the popover.
  • Hitting the Esc key while the popover is open and focus is within the Popover.Content, will close the popover. If you set closeOnEsc to false, it will not close.
  • Clicking outside or blurring out of the Popover.Content closes the popover. If you set closeOnBlur to false, it will not close.

ARIA Attributes#

  • If the trigger is set to click, the Popover.Content element has role set to dialog. If the trigger is set to hover, the Popover.Content has role set to tooltip.
  • The Popover.Content has aria-labelledby set to the id of the Popover.Header.
  • The Popover.Content has aria-describedby set to the id of the Popover.Body.
  • The Popover.Content has aria-hidden set to true or false depending on the open/closed state of the popover.
  • The trigger has aria-haspopup set to true to denote that it triggers a popover.
  • The trigger has aria-controls set to the id of the Popover.Content to associate the popover and the trigger.
  • The trigger has aria-expanded set to true or false depending on the open/closed state of the popover.
Edit this page on GitHub

Proudly made inNigeria by Segun Adebayo

Deployed by â–² Vercel