The padding required to prevent the arrow from reaching the very edge of the popper.
Popover
Popover is a non-modal dialog that floats around a trigger.
The Popover
component is a multipart component. The styling needs to be
applied to each part specifically.
To learn more about styling multipart components, visit the Component Style page.
Anatomy#
- A:
content
- B:
header
- C:
body
- D:
footer
- E:
popper
- F:
arrow
- G:
closeButton
Theming properties#
The Popover
doesn't have any default properties that affect the theming,
however it is possible to create the following properties:
size
variant
colorScheme
Theming utilities#
createMultiStyleConfigHelpers
: a function that returns a set of utilities for creating style configs for a multipart component (definePartsStyle
anddefineMultiStyleConfig
).definePartsStyle
: a function used to create multipart style objects.defineMultiStyleConfig
: a function used to define the style configuration for a multipart component.
import { popoverAnatomy as parts } from '@chakra-ui/anatomy'import { createMultiStyleConfigHelpers } from '@chakra-ui/react'const { definePartsStyle, defineMultiStyleConfig } =createMultiStyleConfigHelpers(parts.keys)
Customizing the default theme#
import { popoverAnatomy as parts } from '@chakra-ui/anatomy'import { createMultiStyleConfigHelpers } from '@chakra-ui/react'const { definePartsStyle, defineMultiStyleConfig } =createMultiStyleConfigHelpers(parts.keys)const baseStyle = definePartsStyle({// define the part you're going to stylebody: {bg: 'gray.800', // change the background of the body to gray.800},content: {padding: 3, // change the padding of the content},})export const popoverTheme = defineMultiStyleConfig({ baseStyle })
After customizing the popover theme, we can import it in our theme file and add
it in the components
property:
import { extendTheme } from '@chakra-ui/react'import { popoverTheme } from './theme/components/popover.ts'export const theme = extendTheme({components: { Popover: popoverTheme },})
This is a crucial step to make sure that any changes that we make to the popover theme are applied.
Adding a custom size#
Let's assume we want to include an extra large popover size. Here's how we can do that:
import { popoverAnatomy as parts } from '@chakra-ui/anatomy'import { createMultiStyleConfigHelpers } from '@chakra-ui/react'const { definePartsStyle, defineMultiStyleConfig } =createMultiStyleConfigHelpers(parts.keys)const sizes = {xl: definePartsStyle({header: defineStyle({padding: 14}),content: defineStyle({fontSize: "2xl",marginLeft: 6})}),}export const popoverTheme = defineMultiStyleConfig({ sizes })// Now we can use the new `xl` size<Popover size="xl">...</Popover>
Every time you're adding anything new to the theme, you'd need to run the CLI command to get proper autocomplete in your IDE. You can learn more about the CLI tool here.
Adding a custom variant#
Let's assume we want to include a custom variant. Here's how we can do that:
import { popoverAnatomy as parts } from '@chakra-ui/anatomy'import { createMultiStyleConfigHelpers, defineStyle } from '@chakra-ui/react'const { definePartsStyle, defineMultiStyleConfig } =createMultiStyleConfigHelpers(parts.keys)const custom = definePartsStyle({content: defineStyle({padding: 7bg: "gray.700"}),footer: defineStyle({fontSize: "xl"})})export const popoverTheme = defineMultiStyleConfig({variants: { custom },})// Now we can use the new `custom` variant<Popover variant="custom">...</Popover>
Creating the default properties#
Let's assume we want to create the default property for the Popover
. Here's
how we can do that:
import { popoverAnatomy as parts } from '@chakra-ui/anatomy'import { createMultiStyleConfigHelpers, defineStyle } from '@chakra-ui/react'const { defineMultiStyleConfig } =createMultiStyleConfigHelpers(parts.keys)//Let's assume we need each popover to have red contentconst defaultVariant = definePartsStyle({content: {bg: "red.200"}})export const popoverTheme = defineMultiStyleConfig({variant: {default: defaultVariant}defaultProps: {variant: default},})//Now by default, each Popover will have a 'default' variant with red content.
Showcase#
import { Popover, PopoverTrigger, PopoverContent, PopoverHeader, PopoverBody, PopoverArrow, Button, Flex, Box, IconButton, useColorMode, Text, HStack, Avatar, AvatarBadge, VStack, StackDivider, } from "@chakra-ui/react"; import { FaMoon, FaSun } from "react-icons/fa"; const CustomButton = ({ label, notifications, colorMode }) => ( <Box h="40px" cursor="pointer" p={2} _hover={{ borderBottomWidth: "2px", borderBottomColor: colorMode === "light" ? "blue.600" : "blue.200", }} > <HStack> <Box> <Text fontSize={"sm"}>{label}</Text> </Box> {notifications && ( <Box bg={colorMode === "light" ? "blue.50" : "blue.300"} pl={1.5} pr={1.5} borderRadius="full" > <Text fontSize={"xs"}>{notifications}</Text> </Box> )} </HStack> </Box> ); const Notification = ({ name, src, action, time, hasBadge, colorMode, ...rest }) => ( <Box bg={ hasBadge ? colorMode === "light" ? "gray.100" : "gray.600" : "transparent" } {...rest} > <Flex gap={3} p={2}> <Box> <Avatar size="sm" name={name} src={src}> {hasBadge && ( <AvatarBadge placement="top-start" bg={colorMode === "light" ? "blue.600" : "blue.300"} borderWidth="2px" boxSize="12px" /> )} </Avatar> </Box> <VStack> <Box> <Text fontSize={"sm"}> <b>{name}</b> {action} </Text> </Box> <Box alignSelf={"flex-start"} mt="0 !important"> <Text fontSize={"xs"} fontWeight="lighter"> {time} </Text> </Box> </VStack> </Flex> </Box> ); const PopoverExample = ({ name, colorMode, ...rest }) => ( <Box> <Popover size="md" {...rest}> <PopoverTrigger> <Button variant="outline">{name}</Button> </PopoverTrigger> <PopoverContent> <PopoverArrow /> <PopoverHeader> <Flex justify="space-between" align="center" p={2}> <Box> <Text as="b">Notifications</Text> </Box> <Box> <Button size="xs" colorScheme={"blue"} variant="ghost"> Mark all as read </Button> </Box> </Flex> <Flex gap={4}> <CustomButton label={"All"} notifications={2} colorMode={colorMode} /> <CustomButton label={"Following"} colorMode={colorMode} /> <CustomButton label={"Archive"} colorMode={colorMode} /> </Flex> </PopoverHeader> <PopoverBody> <VStack justify="flex-start" divider={<StackDivider bg="gray.600" m={"0 !important"} />} align="stretch" > <Notification name="Segun Adebayo" action="created Chakra UI" time="10 min ago" src="https://bit.ly/sage-adebayo" hasBadge={true} colorMode={colorMode} /> <Notification name="Dan Abramov" action="created Redux" time="1 hour ago" src="https://bit.ly/dan-abramov" hasBadge={true} colorMode={colorMode} /> <Notification name="Gleb Koshcheev" action="added theme docs" time="12:10pm" colorMode={colorMode} /> <Notification name="Jacob Jones" action="deleted profile image" time="11:30am" colorMode={colorMode} /> </VStack> </PopoverBody> </PopoverContent> </Popover> </Box> ); export default function App() { const { toggleColorMode, colorMode } = useColorMode(); return ( <Box pos="relative"> <Flex direction="column" gap={3} align="center" p={8} alignItems={"center"} justify="center" > <PopoverExample name={"Themed Popover"} colorMode={colorMode} /> <PopoverExample name={"Themed XL Popover"} size="xl" colorMode={colorMode} /> <PopoverExample name={"Themed XL Rounded Popover"} size="xl" variant="rounded" colorMode={colorMode} /> </Flex> <Box> <IconButton aria-label="toggle theme" rounded="full" size="xs" position="fixed" bottom={4} left={4} onClick={toggleColorMode} icon={colorMode === "dark" ? <FaSun /> : <FaMoon />} /> </Box> </Box> ); }
Props#
Popover Props#
arrowPadding
arrowPadding
number
8
arrowShadowColor
arrowShadowColor
The `box-shadow` of the popover arrow
string
arrowSize
arrowSize
The size of the popover arrow
number
autoFocus
autoFocus
If true
, focus will be transferred to the first interactive element
when the popover opens
boolean
true
boundary
boundary
The boundary area for the popper. Used within the preventOverflow
modifier
HTMLElement | "clippingParents" | "scrollParent"
clippingParents
closeDelay
closeDelay
Delay in milliseconds before the popover closes after a trigger event. Only works when `trigger="hover"`
number
200
closeOnBlur
closeOnBlur
If true
, the popover will close when you blur out it by
clicking outside or tabbing out
boolean
true
closeOnEsc
closeOnEsc
If true
, the popover will close when you hit the Esc
key
boolean
true
computePositionOnMount
computePositionOnMount
If true
, the popover will be positioned when it mounts
(even if it's not open)
Note 🚨: We don't recommend using this in a popover/menu intensive UI or page
as it might affect scrolling performance.
boolean
defaultIsOpen
defaultIsOpen
If true
, the popover will be initially opened.
boolean
direction
direction
Theme direction ltr
or rtl
. Popper's placement will
be set accordingly
"ltr" | "rtl"
ltr
eventListeners
eventListeners
If provided, determines whether the popper will reposition itself on scroll
and resize
of the window.
type ONLY_FOR_FORMAT =
| boolean
| { scroll?: boolean | undefined resize?: boolean | undefined }
true
flip
flip
If true
, the popper will change its placement and flip when it's
about to overflow its boundary area.
boolean
true
gutter
gutter
The distance or margin between the reference and popper.
It is used internally to create an offset
modifier.
NB: If you define offset
prop, it'll override the gutter.
number
8
id
id
The html id
attribute of the popover.
If not provided, we generate a unique id.
This id
is also used to auto-generate the `aria-labelledby`
and `aria-describedby` attributes that points to the PopoverHeader
and PopoverBody
string
initialFocusRef
initialFocusRef
The ref
of the element that should receive focus when the popover opens.
RefObject<{ focus(): void }>
isLazy
isLazy
Performance 🚀:
If true
, the PopoverContent rendering will be deferred
until the popover is open.
boolean
isOpen
isOpen
If true
, the popover will be opened in controlled mode.
boolean
lazyBehavior
lazyBehavior
Performance 🚀: The lazy behavior of popover's content when not visible. Only works when `isLazy={true}` - "unmount": The popover's content is always unmounted when not open. - "keepMounted": The popover's content initially unmounted, but stays mounted when popover is open.
LazyMode
unmount
matchWidth
matchWidth
If true
, the popper will match the width of the reference at all times.
It's useful for autocomplete
, `date-picker` and select
patterns.
boolean
false
modifiers
modifiers
Array of popper.js modifiers. Check the docs to see the list of possible modifiers you can pass.
Partial<Modifier<string, any>>[]
offset
offset
The main and cross-axis offset to displace popper element from its reference element.
[number, number]
onClose
onClose
Callback fired when the popover closes
() => void
onOpen
onOpen
Callback fired when the popover opens
() => void
openDelay
openDelay
Delay in milliseconds before the popover opens after a trigger event. Only works when `trigger="hover"`
number
200
placement
placement
The placement of the popper relative to its reference.
PlacementWithLogical
bottom
preventOverflow
preventOverflow
If true
, will prevent the popper from being cut off and ensure
it's visible within the boundary area.
boolean
true
returnFocusOnClose
returnFocusOnClose
If true
, focus will be returned to the element that triggers the popover
when it closes
boolean
true
strategy
strategy
The CSS positioning strategy to use.
"fixed" | "absolute"
absolute
trigger
trigger
The interaction that triggers the popover.
hover
- means the popover will open when you hover with mouse or
focus with keyboard on the popover trigger
click
- means the popover will open on click or
press Enter
to Space
on keyboard
"click" | "hover"
click
Other Props#
PopoverContent
composesBox
and has the ability to smartly position itself. Thanks to popper.js.PopoverArrow
,PopoverHeader
,PopoverFooter
andPopoverBody
composesBox
.PopoverCloseButton
composesBox
component.
The Popover
component is a multipart component. The styling needs to be
applied to each part specifically.
To learn more about styling multipart components, visit the Component Style page.
Anatomy#
- A:
content
- B:
header
- C:
body
- D:
footer
- E:
popper
- F:
arrow
- G:
closeButton
Theming properties#
The Popover
doesn't have any default properties that affect the theming,
however it is possible to create the following properties:
size
variant
colorScheme
Theming utilities#
createMultiStyleConfigHelpers
: a function that returns a set of utilities for creating style configs for a multipart component (definePartsStyle
anddefineMultiStyleConfig
).definePartsStyle
: a function used to create multipart style objects.defineMultiStyleConfig
: a function used to define the style configuration for a multipart component.
import { popoverAnatomy as parts } from '@chakra-ui/anatomy'import { createMultiStyleConfigHelpers } from '@chakra-ui/react'const { definePartsStyle, defineMultiStyleConfig } =createMultiStyleConfigHelpers(parts.keys)
Customizing the default theme#
import { popoverAnatomy as parts } from '@chakra-ui/anatomy'import { createMultiStyleConfigHelpers } from '@chakra-ui/react'const { definePartsStyle, defineMultiStyleConfig } =createMultiStyleConfigHelpers(parts.keys)const baseStyle = definePartsStyle({// define the part you're going to stylebody: {bg: 'gray.800', // change the background of the body to gray.800},content: {padding: 3, // change the padding of the content},})export const popoverTheme = defineMultiStyleConfig({ baseStyle })
After customizing the popover theme, we can import it in our theme file and add
it in the components
property:
import { extendTheme } from '@chakra-ui/react'import { popoverTheme } from './theme/components/popover.ts'export const theme = extendTheme({components: { Popover: popoverTheme },})
This is a crucial step to make sure that any changes that we make to the popover theme are applied.
Adding a custom size#
Let's assume we want to include an extra large popover size. Here's how we can do that:
import { popoverAnatomy as parts } from '@chakra-ui/anatomy'import { createMultiStyleConfigHelpers } from '@chakra-ui/react'const { definePartsStyle, defineMultiStyleConfig } =createMultiStyleConfigHelpers(parts.keys)const sizes = {xl: definePartsStyle({header: defineStyle({padding: 14}),content: defineStyle({fontSize: "2xl",marginLeft: 6})}),}export const popoverTheme = defineMultiStyleConfig({ sizes })// Now we can use the new `xl` size<Popover size="xl">...</Popover>
Every time you're adding anything new to the theme, you'd need to run the CLI command to get proper autocomplete in your IDE. You can learn more about the CLI tool here.
Adding a custom variant#
Let's assume we want to include a custom variant. Here's how we can do that:
import { popoverAnatomy as parts } from '@chakra-ui/anatomy'import { createMultiStyleConfigHelpers, defineStyle } from '@chakra-ui/react'const { definePartsStyle, defineMultiStyleConfig } =createMultiStyleConfigHelpers(parts.keys)const custom = definePartsStyle({content: defineStyle({padding: 7bg: "gray.700"}),footer: defineStyle({fontSize: "xl"})})export const popoverTheme = defineMultiStyleConfig({variants: { custom },})// Now we can use the new `custom` variant<Popover variant="custom">...</Popover>
Creating the default properties#
Let's assume we want to create the default property for the Popover
. Here's
how we can do that:
import { popoverAnatomy as parts } from '@chakra-ui/anatomy'import { createMultiStyleConfigHelpers, defineStyle } from '@chakra-ui/react'const { defineMultiStyleConfig } =createMultiStyleConfigHelpers(parts.keys)//Let's assume we need each popover to have red contentconst defaultVariant = definePartsStyle({content: {bg: "red.200"}})export const popoverTheme = defineMultiStyleConfig({variant: {default: defaultVariant}defaultProps: {variant: default},})//Now by default, each Popover will have a 'default' variant with red content.
Showcase#
import { Popover, PopoverTrigger, PopoverContent, PopoverHeader, PopoverBody, PopoverArrow, Button, Flex, Box, IconButton, useColorMode, Text, HStack, Avatar, AvatarBadge, VStack, StackDivider, } from "@chakra-ui/react"; import { FaMoon, FaSun } from "react-icons/fa"; const CustomButton = ({ label, notifications, colorMode }) => ( <Box h="40px" cursor="pointer" p={2} _hover={{ borderBottomWidth: "2px", borderBottomColor: colorMode === "light" ? "blue.600" : "blue.200", }} > <HStack> <Box> <Text fontSize={"sm"}>{label}</Text> </Box> {notifications && ( <Box bg={colorMode === "light" ? "blue.50" : "blue.300"} pl={1.5} pr={1.5} borderRadius="full" > <Text fontSize={"xs"}>{notifications}</Text> </Box> )} </HStack> </Box> ); const Notification = ({ name, src, action, time, hasBadge, colorMode, ...rest }) => ( <Box bg={ hasBadge ? colorMode === "light" ? "gray.100" : "gray.600" : "transparent" } {...rest} > <Flex gap={3} p={2}> <Box> <Avatar size="sm" name={name} src={src}> {hasBadge && ( <AvatarBadge placement="top-start" bg={colorMode === "light" ? "blue.600" : "blue.300"} borderWidth="2px" boxSize="12px" /> )} </Avatar> </Box> <VStack> <Box> <Text fontSize={"sm"}> <b>{name}</b> {action} </Text> </Box> <Box alignSelf={"flex-start"} mt="0 !important"> <Text fontSize={"xs"} fontWeight="lighter"> {time} </Text> </Box> </VStack> </Flex> </Box> ); const PopoverExample = ({ name, colorMode, ...rest }) => ( <Box> <Popover size="md" {...rest}> <PopoverTrigger> <Button variant="outline">{name}</Button> </PopoverTrigger> <PopoverContent> <PopoverArrow /> <PopoverHeader> <Flex justify="space-between" align="center" p={2}> <Box> <Text as="b">Notifications</Text> </Box> <Box> <Button size="xs" colorScheme={"blue"} variant="ghost"> Mark all as read </Button> </Box> </Flex> <Flex gap={4}> <CustomButton label={"All"} notifications={2} colorMode={colorMode} /> <CustomButton label={"Following"} colorMode={colorMode} /> <CustomButton label={"Archive"} colorMode={colorMode} /> </Flex> </PopoverHeader> <PopoverBody> <VStack justify="flex-start" divider={<StackDivider bg="gray.600" m={"0 !important"} />} align="stretch" > <Notification name="Segun Adebayo" action="created Chakra UI" time="10 min ago" src="https://bit.ly/sage-adebayo" hasBadge={true} colorMode={colorMode} /> <Notification name="Dan Abramov" action="created Redux" time="1 hour ago" src="https://bit.ly/dan-abramov" hasBadge={true} colorMode={colorMode} /> <Notification name="Gleb Koshcheev" action="added theme docs" time="12:10pm" colorMode={colorMode} /> <Notification name="Jacob Jones" action="deleted profile image" time="11:30am" colorMode={colorMode} /> </VStack> </PopoverBody> </PopoverContent> </Popover> </Box> ); export default function App() { const { toggleColorMode, colorMode } = useColorMode(); return ( <Box pos="relative"> <Flex direction="column" gap={3} align="center" p={8} alignItems={"center"} justify="center" > <PopoverExample name={"Themed Popover"} colorMode={colorMode} /> <PopoverExample name={"Themed XL Popover"} size="xl" colorMode={colorMode} /> <PopoverExample name={"Themed XL Rounded Popover"} size="xl" variant="rounded" colorMode={colorMode} /> </Flex> <Box> <IconButton aria-label="toggle theme" rounded="full" size="xs" position="fixed" bottom={4} left={4} onClick={toggleColorMode} icon={colorMode === "dark" ? <FaSun /> : <FaMoon />} /> </Box> </Box> ); }