Code Monkey home page Code Monkey logo

popover's Introduction


<Popover>

Bundlephobia Types Code coverage Build status NPM Version MIT License

npm i @accessible/popover

An accessible, "batteries included", popover component for React.

Features

  • Several placement options You can render the popover anywhere! Top, top-left, bottom, center, inside, outside, literally anywhere!
  • Containment policies The popover is configured to contain itself inside the window using a containment policy. It's also optional, so you can turn it off.
  • Auto-repositioning Use the props repositionOnScroll or repositionOnResize to reposition the popover automatically when the scroll position or size of the window changes.
  • Style-agnostic You can use this component with the styling library of your choice. It works with CSS-in-JS, SASS, plain CSS, plain style objects, anything!
  • Portal-friendly The popover will render into React portals of your choice when configured to do so.
  • a11y/aria-compliant This component works with screen readers out of the box and manages focus for you.

Quick Start

Check out the example on CodeSandbox

import {Popover, Target, Trigger} from '@accessible/popover'

const Component = () => (
  <Popover repositionOnScroll repositionOnResize>
    <Target placement="bottomLeft">
      <div className="my-popover">Hello world</div>
    </Target>

    <Trigger on="hover">
      <a href="/profile/me">
        <img src="avatar.jpg" />
      </a>
    </Trigger>
  </Popover>
)

API

Components

Component Description
<Popover> This component creates the context for your popover target and trigger and contains some configuration options.
<Target> This component wraps any React element and turns it into a popover target.
<Trigger> This component wraps any React element and turns it into a popover trigger.
<Close> This is a convenience component that wraps any React element and adds an onClick handler to close the popover.

Hooks

Hook Description
usePopover() This hook provides the value of the popover's PopoverContextValue object.
useControls() This hook provides access to the popover's open, close, toggle, and reposition functions.
usePlacement() This hook provides access to the popover's rendered placement.
useIsOpen() This hook provides access to the popover's isOpen value.

<Popover>

This component creates the context for your popover target and trigger and contains some configuration options.

Props

Prop Type Default Required? Description
defaultOpen boolean false No This sets the default open state of the popover. By default the popover is closed.
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().
onChange (isOpen: boolean) => void undefined No This callback will be invoked each time the open state changes.
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.
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.
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 for more options.
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.

ContainPolicy

Policy Description
"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.
"flipX" This will attempt to flip its position on only the x axis to attempt to remain within the bounds of the window.
"flipY" This will attempt to flip its position on only the y axis to attempt to remain within the bounds of the window.
function You can decide what to do with the popover on your own by providing a callback with the signature (placement: string, triggerRect: ClientRect, popoverRect: ClientRect) => Placement | PlacementResult where Placement is a string returning an alternative placement and PlacementResult is an object shaped {placement: Placement, style: CSSProperties}

<Target>

This component wraps any React element and turns it into a popover target.

Props

Prop Type Default Required? Description
placement Placement "bottom" No This tells the target where it should render relative to its triggering element.
portal boolean | string 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.
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.
closedClass string undefined No This class name will be applied to the child element when the popover is closed.
openClass string "popover--open" No This class name will be applied to the child element when the popover is open.
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.
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.
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.

Placement

These are the default placements allowed by the popover relative to its triggering element

Placement Description
top top
topLeft topLeft
topRight topRight
right right
rightTop rightTop
rightBottom rightBottom
bottom bottom
bottomLeft bottomLeft
bottomRight bottomRight
left left
leftTop leftTop
leftBottom leftBottom
innerTop innerTop
innerTopLeft innerTopLeft
innerTopRight innerTopRight
innerRight innerRight
innerBottom innerBottom
innerBottomLeft innerBottomLeft
innerBottomRight innerBottomRight
innerLeft innerLeft
center center

Example

<Target placement="innerTopLeft">
  <div className="menu">Menu</div>
</Target>

// <div
//   class="menu"
//   aria-hidden="true"
//   aria-modal="false"
//   id="popover--foobar"
//   role="dialog"
//   style="position: fixed; visibility: hidden; right: 1024px; top: 0px;"
// >
//   Menu
// </div>

<Trigger>

This component wraps any React element and turns it into a popover trigger.

Props

Prop Type Default Required? Description
on "hover" | "click" | "focus" 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.
closedClass string undefined No This class name will be applied to the child element when the popover is closed.
openClass string undefined No This class name will be applied to the child element when the popover is open.
closedStyle React.CSSProperties undefined No These styles will be applied to the child element when the popover is closed.
openStyle React.CSSProperties undefined No These styles name will be applied to the child element when the popover is open.
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.

Example

<Trigger on="click">
  <button className="my-button">Popover me!</button>
</Trigger>

// <button
//   class="my-button"
//   aria-controls="popover--12"
//   aria-haspopup="dialog"
//   aria-expanded="false"
// >
//   Popover me!
// </button>

<Close>

This is a convenience component that wraps any React element and adds an onClick handler to close the popover.

Props

Prop Type Default Required? Description
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.
<Close>
  <button className="my-button">Close me</button>
</Close>

// <button
//   class="my-button"
//   aria-controls="popover--12"
//   aria-haspopup="dialog"
//   aria-expanded="false"
// >
//   Close me
// </button>

usePopover()

This hook provides the value of the popover's PopoverContextValue object

Example

const Component = () => {
  const {open, close, toggle, isOpen} = usePopover()
  return <button onClick={toggle}>Toggle the popover</button>
}

PopoverContextValue

interface PopoverContextValue {
  // `true` when the popover is open and visible
  // `false` when closed
  isOpen: boolean
  // opens the popover
  open: () => void
  // closes the popover
  close: () => void
  // toggles the popover between open/closed states
  toggle: () => void
  // calling this forces the popover to reposition
  // itself to the specified placement
  reposition: (nextPlacement: Placement) => void
  // the ID of the popover target
  id: string
  // the style applied to the popover target
  style: React.CSSProperties
  // the rendered placement of the popover
  placement: Placement
  // sets the ref for the popover target
  targetRef: React.MutableRefObject<HTMLElement | null>
  // sets the ref for the triggering element
  triggerRef: React.MutableRefObject<HTMLElement | null>
  // this describes the events that cause the popover
  // to open
  triggeredBy: string | null
  // sets the `triggeredBy` variable above
  setTriggeredBy: (trigger: string) => void
}

usePlacement()

This hook provides access to the popover's rendered placement

Example

const Component = () => {
  const placement = usePlacement()
  return (
    <Target placement="top">
      <div className="my-popover">
        <span className={`arrow--${placement}`} />
      </div>
    </Target>
  )
}

useControls()

This hook provides access to the popover's open, close, toggle, and reposition functions

Example

const Component = () => {
  const {open, close, toggle} = useControls()
  return (
    <Target>
      <div className="my-popover">
        <button onClick={close}>Close me</button>
      </div>
    </Target>
  )
}

useIsOpen()

This hook provides access to the popover's isOpen value

Example

const Component = () => {
  const isOpen = useIsOpen()
  return (
    <Target>
      <div className="my-popover">Am I open? {isOpen ? 'Yes' : 'No'}</div>
    </Target>
  )
}

LICENSE

MIT

popover's People

Contributors

jaredlunde avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

popover's Issues

question: ie 11 compatibility

Hi mate, this component works amazing.

Could we create a version of the library with ie 11 compatibility out of the box?

I've tried to compile all this libraries with a babel.config.js with IE 11 on target, but crashes...

"react-portalize",
"@accessible/popover",
"@accessible/button",
"@accessible/tabbable",
"@accessible/use-conditional-focus",
"@accessible/use-id",
"@accessible/use-keycode",
"@react-hook/debounce",
"@react-hook/event",
"@react-hook/latest",
"@react-hook/merged-ref",
"@react-hook/passive-layout-effect",
"@react-hook/switch",
"@react-hook/throttle",
"@react-hook/window-scroll",
"@react-hook/window-size",

The error: TypeError: Assignment to read-only properties is not allowed in strict mode
in Target 

feat-request: disable autofocus to child as a prop

I've run on a issue where i got one popover, with two input type="text" inside that, when i try to write on the second one, the focus is lost.

I'll try to implement a codesandbox for replicate the issue asap.

So, I think if we can disable the autofocus option we'll be enough by the moment

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.