Arctic Design
Get StartedFoundationsComponentsExamples
K

Popover

Displays a floating, contextual overlay anchored to a trigger element, providing additional information or actions.

Usage
import { useState } from 'react';
import {
Popover,
PopoverClose,
PopoverContent,
PopoverDescription,
PopoverHeading,
PopoverOptions,
PopoverTrigger,
} from '@arctic-kit/snow';
function Demo() {
const [open, setOpen] = useState(false);
return (
<div>
<Popover placement="bottom-start" open={open} onOpenChange={setOpen}>
<PopoverTrigger onClick={() => setOpen((v) => !v)}>
My Trigger
</PopoverTrigger>
<PopoverContent>
<PopoverHeading>My popover heading</PopoverHeading>
<PopoverDescription>My popover description</PopoverDescription>
<PopoverClose>Close</PopoverClose>
</PopoverContent>
</Popover>
</div>
);
}
Custom Trigger
import {
Button,
Paper,
Popover,
PopoverContent,
PopoverTrigger,
Stack,
} from '@arctic-kit/snow';
import { useCallback, useState } from 'react';
import { ChevronDownIcon } from '@arctic-kit/icons';
import { styled } from '@pigment-css/react';
const UserRoles = [
{ name: 'Member', description: 'Can view resources' },
{ name: 'Viewer', description: 'Can view and comment' },
{ name: 'Developer', description: 'Can view, comment and edit' },
{ name: 'Billing', description: 'Can view, comment and manage billing' },
{ name: 'Owner', description: 'Admin-level access to all resources' },
];
const RoleContainer = styled.div(() => ({
display: 'flex',
flexDirection: 'column',
gap: 6,
padding: 8,
fontSize: 12,
'&:hover': {
backgroundColor: 'var(--snow-colors-grey-100)',
cursor: 'default',
},
'.title': {
fontWeight: 500,
},
'.description': {
fontWeight: 400,
color: 'var(--snow-colors-grey-700)',
},
'&.active': {
backgroundColor: 'var(--snow-colors-primary-50)',
},
}));
function UserRolePopover({
setOpen,
open,
selectedRole,
onRoleSelect,
}: {
setOpen: (value: boolean) => void;
open?: boolean;
selectedRole: string;
onRoleSelect: (role: string) => void;
}) {
return (
<Popover placement='bottom-start' open={open} onOpenChange={setOpen}>
<PopoverTrigger onClick={() => setOpen(!open)} asChild>
<Button
variant='outlined'
style={{ fontSize: 12 }}
suffix={<ChevronDownIcon style={{ width: 14 }} />}
noHighlights
>
{selectedRole}
</Button>
</PopoverTrigger>
<PopoverContent>
<Stack
style={{ maxHeight: 500, overflowY: 'auto', padding: 4 }}
spacing={2}
>
{UserRoles.map((role) => (
<RoleContainer
key={role.name}
onClick={() => onRoleSelect(role.name)}
className={role.name === selectedRole ? 'active' : ''}
>
<div className='title'>{role.name}</div>
<div className='description'>{role.description}</div>
</RoleContainer>
))}
</Stack>
</PopoverContent>
</Popover>
);
}
function Demo() {
const [open, setOpen] = useState(false);
const [selectedRole, setSelectedRole] = useState(UserRoles[0].name);
const onRoleSelect = useCallback((roleName: string) => {
setSelectedRole(roleName);
setOpen(false);
}, []);
return (
<UserRolePopover
open={open}
setOpen={setOpen}
selectedRole={selectedRole}
onRoleSelect={onRoleSelect}
/>
);
}

API Reference

PropsTypeDefault
initialOpenboolean | undefined---
modalboolean | undefinedfalse
onOpenChange((open: boolean) => void) | undefined---
openboolean | undefined---
placementPlacement---