{"id":24911427,"url":"https://github.com/accessible-ui/popover","last_synced_at":"2025-10-16T22:30:30.789Z","repository":{"id":36472278,"uuid":"226786332","full_name":"accessible-ui/popover","owner":"accessible-ui","description":"🅰 An accessible and versatile popover component for React","archived":false,"fork":false,"pushed_at":"2023-01-06T02:20:06.000Z","size":915,"stargazers_count":9,"open_issues_count":14,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-13T20:59:22.328Z","etag":null,"topics":["a11y","accessibility","accessible-react","hook","popover","popover-component","react","react-a11y","react-accessibility","tooltip","tooltip-component"],"latest_commit_sha":null,"homepage":"https://codesandbox.io/s/accessiblepopover-example-6l3u0","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/accessible-ui.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-12-09T04:43:31.000Z","updated_at":"2024-08-15T17:39:35.000Z","dependencies_parsed_at":"2023-01-17T02:01:04.403Z","dependency_job_id":null,"html_url":"https://github.com/accessible-ui/popover","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/accessible-ui%2Fpopover","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/accessible-ui%2Fpopover/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/accessible-ui%2Fpopover/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/accessible-ui%2Fpopover/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/accessible-ui","download_url":"https://codeload.github.com/accessible-ui/popover/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":236750102,"owners_count":19198810,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["a11y","accessibility","accessible-react","hook","popover","popover-component","react","react-a11y","react-accessibility","tooltip","tooltip-component"],"created_at":"2025-02-02T04:20:06.810Z","updated_at":"2025-10-16T22:30:25.483Z","avatar_url":"https://github.com/accessible-ui.png","language":"TypeScript","readme":"\u003chr\u003e\n\u003cdiv align=\"center\"\u003e\n  \u003ch1 align=\"center\"\u003e\n    \u0026lt;Popover\u0026gt;\n  \u003c/h1\u003e\n\u003c/div\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://bundlephobia.com/result?p=@accessible/popover\"\u003e\n    \u003cimg alt=\"Bundlephobia\" src=\"https://img.shields.io/bundlephobia/minzip/@accessible/popover?style=for-the-badge\u0026labelColor=24292e\"\u003e\n  \u003c/a\u003e\n  \u003ca aria-label=\"Types\" href=\"https://www.npmjs.com/package/@accessible/popover\"\u003e\n    \u003cimg alt=\"Types\" src=\"https://img.shields.io/npm/types/@accessible/popover?style=for-the-badge\u0026labelColor=24292e\"\u003e\n  \u003c/a\u003e\n  \u003ca aria-label=\"Code coverage report\" href=\"https://codecov.io/gh/accessible-ui/popover\"\u003e\n    \u003cimg alt=\"Code coverage\" src=\"https://img.shields.io/codecov/c/gh/accessible-ui/popover?style=for-the-badge\u0026labelColor=24292e\"\u003e\n  \u003c/a\u003e\n  \u003ca aria-label=\"Build status\" href=\"https://travis-ci.org/accessible-ui/popover\"\u003e\n    \u003cimg alt=\"Build status\" src=\"https://img.shields.io/travis/accessible-ui/popover?style=for-the-badge\u0026labelColor=24292e\"\u003e\n  \u003c/a\u003e\n  \u003ca aria-label=\"NPM version\" href=\"https://www.npmjs.com/package/@accessible/popover\"\u003e\n    \u003cimg alt=\"NPM Version\" src=\"https://img.shields.io/npm/v/@accessible/popover?style=for-the-badge\u0026labelColor=24292e\"\u003e\n  \u003c/a\u003e\n  \u003ca aria-label=\"License\" href=\"https://jaredlunde.mit-license.org/\"\u003e\n    \u003cimg alt=\"MIT License\" src=\"https://img.shields.io/npm/l/@accessible/popover?style=for-the-badge\u0026labelColor=24292e\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cpre align=\"center\"\u003enpm i @accessible/popover\u003c/pre\u003e\n\u003chr\u003e\n\nAn accessible, \"batteries included\", popover component for React.\n\n## Features\n\n- **Several placement options** You can render the popover anywhere! Top, top-left, bottom, center, inside, outside,\n  literally anywhere!\n- **Containment policies** The popover is configured to contain itself inside the window using\n  a containment policy. It's also optional, so you can turn it off.\n- **Auto-repositioning** Use the props `repositionOnScroll` or `repositionOnResize` to reposition\n  the popover automatically when the scroll position or size of the window changes.\n- **Style-agnostic** You can use this component with the styling library of your choice. It\n  works with CSS-in-JS, SASS, plain CSS, plain `style` objects, anything!\n- **Portal-friendly** The popover will render into React portals of your choice when configured\n  to do so.\n- **a11y/aria-compliant** This component works with screen readers out of the box and manages\n  focus for you.\n\n## Quick Start\n\n[Check out the example on CodeSandbox](https://codesandbox.io/s/accessiblepopover-example-6l3u0)\n\n```jsx harmony\nimport {Popover, Target, Trigger} from '@accessible/popover'\n\nconst Component = () =\u003e (\n  \u003cPopover repositionOnScroll repositionOnResize\u003e\n    \u003cTarget placement=\"bottomLeft\"\u003e\n      \u003cdiv className=\"my-popover\"\u003eHello world\u003c/div\u003e\n    \u003c/Target\u003e\n\n    \u003cTrigger on=\"hover\"\u003e\n      \u003ca href=\"/profile/me\"\u003e\n        \u003cimg src=\"avatar.jpg\" /\u003e\n      \u003c/a\u003e\n    \u003c/Trigger\u003e\n  \u003c/Popover\u003e\n)\n```\n\n## API\n\n### Components\n\n| Component               | Description                                                                                                     |\n| ----------------------- | --------------------------------------------------------------------------------------------------------------- |\n| [`\u003cPopover\u003e`](#popover) | This component creates the context for your popover target and trigger and contains some configuration options. |\n| [`\u003cTarget\u003e`](#target)   | This component wraps any React element and turns it into a popover target.                                      |\n| [`\u003cTrigger\u003e`](#trigger) | This component wraps any React element and turns it into a popover trigger.                                     |\n| [`\u003cClose\u003e`](#close)     | This is a convenience component that wraps any React element and adds an onClick handler to close the popover.  |  |\n\n### Hooks\n\n| Hook                              | Description                                                                                       |\n| --------------------------------- | ------------------------------------------------------------------------------------------------- |\n| [`usePopover()`](#usepopover)     | This hook provides the value of the popover's [PopoverContextValue object](#popovercontextvalue). |\n| [`useControls()`](#usecontrols)   | This hook provides access to the popover's `open`, `close`, `toggle`, and `reposition` functions. |\n| [`usePlacement()`](#useplacement) | This hook provides access to the popover's rendered placement.                                    |\n| [`useIsOpen()`](#useisopen)       | This hook provides access to the popover's `isOpen` value.                                        |\n\n### `\u003cPopover\u003e`\n\nThis component creates the context for your popover target and trigger and contains some\nconfiguration options.\n\n#### Props\n\n| Prop               | Type                              | Default     | Required? | Description                                                                                                                                                                                                                                                               |\n| ------------------ | --------------------------------- | ----------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| defaultOpen        | `boolean`                         | `false`     | No        | This sets the default open state of the popover. By default the popover is closed.                                                                                                                                                                                        |\n| open               | `boolean`                         | `undefined` | No        | You can control the open/closed state of the popover with this prop. When it isn't undefined, this value will take precedence over any calls to `open()`, `close()`, or `toggle()`.                                                                                       |\n| onChange           | `(isOpen: boolean) =\u003e void`       | `undefined` | No        | This callback will be invoked each time the open state changes.                                                                                                                                                                                                           |\n| repositionOnResize | `boolean`                         | `false`     | No        | Setting this to `true` will update the position of the popover when the window's dimensions change and the popover is currently open.                                                                                                                                     |\n| repositionOnScroll | `boolean`                         | `false`     | No        | Setting this to `true` will update the position of the popover when the window's scroll position changes and the popover is currently open.                                                                                                                               |\n| containPolicy      | [`ContainPolicy`](#containpolicy) | `\"flip\"`    | No        | This tells the popover what to do when it overflows outside the dimensions of the window. By default it will flip its position on both the `x` and `y` axis to attempt to remain within the bounds of the window. See [`ContainPolicy`](#containpolicy) for more options. |\n| id                 | `string`                          | `undefined` | No        | By default this component creates a unique id for you, as it is required for certain aria attributes. Supplying an id here overrides the auto id feature.                                                                                                                 |\n\n#### `ContainPolicy`\n\n| Policy     | Description                                                                                                                                                                                                                                                                                                                                                                                      |\n| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| `\"flip\"`   | This will attempt to flip its position on both the `x` and `y` axis to attempt to remain within the bounds of the window.                                                                                                                                                                                                                                                                        |\n| `\"flipX\"`  | This will attempt to flip its position on only the `x` axis to attempt to remain within the bounds of the window.                                                                                                                                                                                                                                                                                |\n| `\"flipY\"`  | This will attempt to flip its position on only the `y` axis to attempt to remain within the bounds of the window.                                                                                                                                                                                                                                                                                |\n| `function` | You can decide what to do with the popover on your own by providing a callback with the signature \u003ccode\u003e(placement: string, triggerRect: ClientRect, popoverRect: ClientRect) =\u003e Placement \u0026#124; PlacementResult\u003c/code\u003e where [`Placement`](#placement) is a string returning an alternative placement and `PlacementResult` is an object shaped `{placement: Placement, style: CSSProperties}` |\n\n### `\u003cTarget\u003e`\n\nThis component wraps any React element and turns it into a popover target.\n\n#### Props\n\n| Prop          | Type                                | Default           | Required? | Description                                                                                                                                                                                                      |\n| ------------- | ----------------------------------- | ----------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| placement     | [`Placement`](#placement)           | `\"bottom\"`        | No        | This tells the target where it should render relative to its triggering element.                                                                                                                                 |\n| portal        | \u003ccode\u003eboolean \u0026#124; string \u003c/code\u003e | `false`           | No        | When `true` this will render the popover into a React portal with the id `#portals`. You can render it into any portal by providing its query selector here, e.g. `#foobar`, `[data-portal=true]`, or `.foobar`. |\n| closeOnEscape | `boolean`                           | `true`            | No        | By default the popover will close when the `Escape` key is pressed. You can turn this off by providing `false` here.                                                                                             |\n| closedClass   | `string`                            | `undefined`       | No        | This class name will be applied to the child element when the popover is `closed`.                                                                                                                               |\n| openClass     | `string`                            | `\"popover--open\"` | No        | This class name will be applied to the child element when the popover is `open`.                                                                                                                                 |\n| closedStyle   | `React.CSSProperties`               | `undefined`       | No        | These styles will be applied to the child element when the popover is `closed` in addition to the default styles that set the target's visibility.                                                               |\n| openStyle     | `React.CSSProperties`               | `undefined`       | No        | These styles name will be applied to the child element when the popover is `open` in addition to the default styles that set the target's visibility.                                                            |\n| children      | `React.ReactElement`                | `undefined`       | Yes       | The child is cloned by this component and has aria attributes injected into its props as well as the events defined above.                                                                                       |\n\n#### Placement\n\nThese are the default placements allowed by the popover relative to its triggering element\n\n| Placement        | Description                                      |\n| ---------------- | ------------------------------------------------ |\n| top              | ![top](assets/top.png)                           |\n| topLeft          | ![topLeft](assets/topLeft.png)                   |\n| topRight         | ![topRight](assets/topRight.png)                 |\n| right            | ![right](assets/right.png)                       |\n| rightTop         | ![rightTop](assets/rightTop.png)                 |\n| rightBottom      | ![rightBottom](assets/rightBottom.png)           |\n| bottom           | ![bottom](assets/bottom.png)                     |\n| bottomLeft       | ![bottomLeft](assets/bottomLeft.png)             |\n| bottomRight      | ![bottomRight](assets/bottomRight.png)           |\n| left             | ![left](assets/left.png)                         |\n| leftTop          | ![leftTop](assets/leftTop.png)                   |\n| leftBottom       | ![leftBottom](assets/leftBottom.png)             |\n| innerTop         | ![innerTop](assets/innerTop.png)                 |\n| innerTopLeft     | ![innerTopLeft](assets/innerTopLeft.png)         |\n| innerTopRight    | ![innerTopRight](assets/innerTopRight.png)       |\n| innerRight       | ![innerRight](assets/innerRight.png)             |\n| innerBottom      | ![innerBottom](assets/innerBottom.png)           |\n| innerBottomLeft  | ![innerBottomLeft](assets/innerBottomLeft.png)   |\n| innerBottomRight | ![innerBottomRight](assets/innerBottomRight.png) |\n| innerLeft        | ![innerLeft](assets/innerLeft.png)               |\n| center           | ![center](assets/center.png)                     |\n\n#### Example\n\n```jsx harmony\n\u003cTarget placement=\"innerTopLeft\"\u003e\n  \u003cdiv className=\"menu\"\u003eMenu\u003c/div\u003e\n\u003c/Target\u003e\n\n// \u003cdiv\n//   class=\"menu\"\n//   aria-hidden=\"true\"\n//   aria-modal=\"false\"\n//   id=\"popover--foobar\"\n//   role=\"dialog\"\n//   style=\"position: fixed; visibility: hidden; right: 1024px; top: 0px;\"\n// \u003e\n//   Menu\n// \u003c/div\u003e\n```\n\n### `\u003cTrigger\u003e`\n\nThis component wraps any React element and turns it into a popover trigger.\n\n#### Props\n\n| Prop        | Type                                                | Default     | Required? | Description                                                                                                                                                                                                                                                     |\n| ----------- | --------------------------------------------------- | ----------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| on          | \u003ccode\u003e\"hover\" \u0026#124; \"click\" \u0026#124; \"focus\" \u003c/code\u003e | `undefined` | Yes       | `\"hover\"` causes the popover to open on `mouseenter` and close on `mouseleave`. `\"click\"` causes the popover to toggle its visibility each `click` event. `\"focus\"` causes the popover to open when the child element is focused while nothing happens on blur. |\n| closedClass | `string`                                            | `undefined` | No        | This class name will be applied to the child element when the popover is `closed`.                                                                                                                                                                              |\n| openClass   | `string`                                            | `undefined` | No        | This class name will be applied to the child element when the popover is `open`.                                                                                                                                                                                |\n| closedStyle | `React.CSSProperties`                               | `undefined` | No        | These styles will be applied to the child element when the popover is `closed`.                                                                                                                                                                                 |\n| openStyle   | `React.CSSProperties`                               | `undefined` | No        | These styles name will be applied to the child element when the popover is `open`.                                                                                                                                                                              |\n| children    | `React.ReactElement`                                | `undefined` | Yes       | The child is cloned by this component and has aria attributes injected into its props as well as the events defined above.                                                                                                                                      |\n\n#### Example\n\n```jsx harmony\n\u003cTrigger on=\"click\"\u003e\n  \u003cbutton className=\"my-button\"\u003ePopover me!\u003c/button\u003e\n\u003c/Trigger\u003e\n\n// \u003cbutton\n//   class=\"my-button\"\n//   aria-controls=\"popover--12\"\n//   aria-haspopup=\"dialog\"\n//   aria-expanded=\"false\"\n// \u003e\n//   Popover me!\n// \u003c/button\u003e\n```\n\n### `\u003cClose\u003e`\n\nThis is a convenience component that wraps any React element and adds an onClick handler to close the popover.\n\n#### Props\n\n| Prop     | Type                 | Default     | Required? | Description                                                                                                                |\n| -------- | -------------------- | ----------- | --------- | -------------------------------------------------------------------------------------------------------------------------- |\n| children | `React.ReactElement` | `undefined` | Yes       | The child is cloned by this component and has aria attributes injected into its props as well as the events defined above. |\n\n```jsx harmony\n\u003cClose\u003e\n  \u003cbutton className=\"my-button\"\u003eClose me\u003c/button\u003e\n\u003c/Close\u003e\n\n// \u003cbutton\n//   class=\"my-button\"\n//   aria-controls=\"popover--12\"\n//   aria-haspopup=\"dialog\"\n//   aria-expanded=\"false\"\n// \u003e\n//   Close me\n// \u003c/button\u003e\n```\n\n### `usePopover()`\n\nThis hook provides the value of the popover's [PopoverContextValue object](#popovercontextvalue)\n\n#### Example\n\n```jsx harmony\nconst Component = () =\u003e {\n  const {open, close, toggle, isOpen} = usePopover()\n  return \u003cbutton onClick={toggle}\u003eToggle the popover\u003c/button\u003e\n}\n```\n\n### `PopoverContextValue`\n\n```typescript\ninterface PopoverContextValue {\n  // `true` when the popover is open and visible\n  // `false` when closed\n  isOpen: boolean\n  // opens the popover\n  open: () =\u003e void\n  // closes the popover\n  close: () =\u003e void\n  // toggles the popover between open/closed states\n  toggle: () =\u003e void\n  // calling this forces the popover to reposition\n  // itself to the specified placement\n  reposition: (nextPlacement: Placement) =\u003e void\n  // the ID of the popover target\n  id: string\n  // the style applied to the popover target\n  style: React.CSSProperties\n  // the rendered placement of the popover\n  placement: Placement\n  // sets the ref for the popover target\n  targetRef: React.MutableRefObject\u003cHTMLElement | null\u003e\n  // sets the ref for the triggering element\n  triggerRef: React.MutableRefObject\u003cHTMLElement | null\u003e\n  // this describes the events that cause the popover\n  // to open\n  triggeredBy: string | null\n  // sets the `triggeredBy` variable above\n  setTriggeredBy: (trigger: string) =\u003e void\n}\n```\n\n### `usePlacement()`\n\nThis hook provides access to the popover's rendered placement\n\n#### Example\n\n```jsx harmony\nconst Component = () =\u003e {\n  const placement = usePlacement()\n  return (\n    \u003cTarget placement=\"top\"\u003e\n      \u003cdiv className=\"my-popover\"\u003e\n        \u003cspan className={`arrow--${placement}`} /\u003e\n      \u003c/div\u003e\n    \u003c/Target\u003e\n  )\n}\n```\n\n### `useControls()`\n\nThis hook provides access to the popover's `open`, `close`, `toggle`, and `reposition` functions\n\n#### Example\n\n```jsx harmony\nconst Component = () =\u003e {\n  const {open, close, toggle} = useControls()\n  return (\n    \u003cTarget\u003e\n      \u003cdiv className=\"my-popover\"\u003e\n        \u003cbutton onClick={close}\u003eClose me\u003c/button\u003e\n      \u003c/div\u003e\n    \u003c/Target\u003e\n  )\n}\n```\n\n### `useIsOpen()`\n\nThis hook provides access to the popover's `isOpen` value\n\n#### Example\n\n```jsx harmony\nconst Component = () =\u003e {\n  const isOpen = useIsOpen()\n  return (\n    \u003cTarget\u003e\n      \u003cdiv className=\"my-popover\"\u003eAm I open? {isOpen ? 'Yes' : 'No'}\u003c/div\u003e\n    \u003c/Target\u003e\n  )\n}\n```\n\n## LICENSE\n\nMIT\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faccessible-ui%2Fpopover","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faccessible-ui%2Fpopover","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faccessible-ui%2Fpopover/lists"}