Components

Popover

Popovers float over page content and hold supporting information or user controls.

Examples #

Import Syntax #

import Popover from 'mineral-ui/Popover';

Basic Usage #

Popovers wrap the triggering component. Placement is relative to the location of the trigger. Popovers will change position relative to the trigger automatically depending on viewport constraints.

<Popover content={<DemoContent />}>
  <Button>Open Popover</Button>
</Popover>

Title and Subtitle #

Formatted titles render above any other content if provided. Subtitles are only be rendered if the title attribute is present.

Title

Subtitle

Light years star stuff harvesting star light citizens of distant epochs encyclopaedia galactica.
<DemoLayout>
  <Popover
    content={<DemoContent />}
    placement="right"
    subtitle="Subtitle"
    title="Title"
    isOpen>
    <Button>Open Popover</Button>
  </Popover>
</DemoLayout>

Placement #

The placement prop determines the initial placement of the Popover content relative to the trigger. The Popover will still react to viewport edges and scrolling.

Light years star stuff harvesting star light citizens of distant epochs encyclopaedia galactica.
<DemoLayout>
  <Popover
    content={<DemoContent />}
    placement="bottom"
    isOpen>
    <Button>Open Popover</Button>
  </Popover>
</DemoLayout>

Overflow #

A Popover can extend beyond its bounding container (the blue area in this example) even if the container has an overflow: hidden style. See the portal example for even greater control.

Light years star stuff harvesting star light citizens of distant epochs encyclopaedia galactica.
<OverflowContainer>
  <Popover
    content={<DemoContent />}
    placement="right"
    isOpen>
    <Button>Open Popover</Button>
  </Popover>
</OverflowContainer>

Scrolling Container #

Popover will attempt to stay visible in an overflow: scroll container.

Light years star stuff harvesting star light citizens of distant epochs encyclopaedia galactica.
<ScrollParent>
  <Popover
    content={<DemoContent />}
    placement="left"
    isOpen>
    <Button>Open Popover</Button>
  </Popover>
</ScrollParent>

Portal #

Use a portal to render the Popover to the body of the page rather than as a sibling of the trigger. This can be useful to visually "break out" of a container with overflow or z-index styles. Note that you may have to adjust the modifiers to get the exact behavior that you want.

<ScrollParent>
  <Popover
    content={<DemoContent />}
    placement="bottom"
    usePortal
    isOpen
    modifiers={{
      preventOverflow: {
        escapeWithReference: true
      }
    }}>
    <Button>Open Popover</Button>
  </Popover>
</ScrollParent>

Disabled #

Disable the Popover and its trigger.

<Popover content={<DemoContent />} disabled>
  <Button>Open Popover</Button>
</Popover>

Controlled #

Popover controls its own state by default, and can optionally be managed by the application as a controlled component through the isOpen attribute. Callbacks for onOpen and onClose are also provided.

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      isOpen: false
    };

    this.onOpen = this.onOpen.bind(this);
    this.onClose = this.onClose.bind(this);
    this.togglePopover = this.togglePopover.bind(this);
  }

  onOpen(event) {
    this.setState({ isOpen: true });
  }

  onClose(event) {
    // Prevent extra call to togglePopover when clicking the controlling button.
    // Also avoid interactions with other popovers.
    const demoLayoutNode = this.demoLayout;
    if (
      !event.nativeEvent &&
      demoLayoutNode &&
      demoLayoutNode.contains(event.target)
    ) {
      event.stopImmediatePropagation();
    }

    this.setState({ isOpen: false });
  }

  togglePopover(event) {
    if (this.state.isOpen) {
      this.onClose(event);
    } else {
      this.onOpen(event);
    }
  }

  render() {
    const label = this.state.isOpen ? 'Close Popover' : 'Open Popover';
    return (
      <DemoLayout ref={node => { this.demoLayout = node }}>
        <Popover
          content={<DemoContent />}
          isOpen={this.state.isOpen}
          onOpen={this.onOpen}
          onClose={this.onClose}>
          <Button>{label}</Button>
        </Popover>
        <Button onClick={this.togglePopover}>{label}</Button>
      </DemoLayout>
    );
  }
}

Bidirectionality #

Popovers support right-to-left (RTL) languages. The placement of the content as well as the content itself will be reversed when the direction theme variable is set to rtl.

Light years star stuff harvesting star light citizens of distant epochs encyclopaedia galactica.
<DemoLayout dir="rtl">
  <ThemeProvider theme={{ direction: 'rtl' }}>
    <Popover content={<DemoContent />} isOpen placement="bottom-start">
      <Button>Open Popover</Button>
    </Popover>
  </ThemeProvider>
</DemoLayout>

Custom Content #

Use the content render prop to provide custom rendering control of the content. See our Render Props Guide for additional information, including important considerations and examples.

Light years star stuff harvesting star light citizens of distant epochs encyclopaedia galactica.
() => {
  const content = ({ props }) => {
    // Your root element must be a Popper component.
    // import { Popper } from 'react-popper';

    const Content = styled('div')(({ theme }) => ({
      ...componentStyleReset(theme),

      backgroundColor: theme.backgroundColor_dangerPrimary,
      color: theme.color_white,
      margin: theme.space_inset_sm,
      padding: theme.space_inset_lg,
      zIndex: theme.zIndex_100
    }));

    return (
      <Popper placement={props.placement}>
        {(popperProps) => {
          const contentProps = {
            ...props,
            ...popperProps
          };

          return (
            <Content {...contentProps} >
              <DemoContent />
            </Content>
          );
        }}
      </Popper>
    );
  };

  return (
    <DemoLayout>
      <Popover content={content} isOpen placement="bottom-start">
        <Button>Open Popover</Button>
      </Popover>
    </DemoLayout>
  );
}

Custom Trigger #

Use the children render prop to provide custom rendering control of the trigger. See our Render Props Guide for additional information, including important considerations and examples.

() => {
  // Your render function must return a Popper Reference component.
  // import { Reference } from 'react-popper';
  const CustomTrigger = styled('button')();      

  return (
    <Popover content={<DemoContent />}>
      {
        ({ props, state }) => {
          return (
            <Reference>
              {({ ref: popperRef }) => {
                const triggerProps = {
                  ...props,
                  ref: (node) => {
                    popperRef(node);
                    props.ref(node);
                  },
                  role: undefined
                }

                return (
                  <CustomTrigger {...triggerProps}>
                    Popover <span role="img" aria-hidden="true">{state.isOpen ? '▲' : '▼'}</span>
                  </CustomTrigger>
                );
              }}
            </Reference>
          );
        }
      }
    </Popover>
  );
}

API & Theme #

Popover Props #

The Popover component takes the following React props.

NameTypeDefaultDescription
childrenReact$Node | RenderFnrequired

Trigger for the Popover. Optionally provides custom rendering control. See the custom trigger example and our render props guide.

contentReact$Node | RenderFnrequired

Content of the Popover. Optionally provides custom rendering control. See the custom content example and our render props guide.

defaultIsOpenboolean

Open the Popover upon initialization. Primarily for use with uncontrolled components.

disabledboolean

Disables the Popover

focusTriggerOnClosebooleantrue

Determines whether focus will be set to the trigger when the Popover is closed.

hasArrowbooleantrue

Include an arrow on the Popover content pointing to the trigger

idstring

Id of the Popover

isOpenboolean

Determines whether the Popover is open. For use with controlled components.

modifiersObject

Plugins that are used to alter behavior. See PopperJS docs for options.

onClose

Called when Popover is closed

onOpen

Called when Popover is opened

placement'bottom'

Placement of the Popover

positionFixedboolean

Apply fixed positioning to the content

subtitleReact$Node

Subtitle displayed under the title

titleReact$Node

Title of the Popover

usePortalboolean

Use a Portal to render the Popover to the body rather than as a sibling to the trigger

Undocumented properties, including as and css, will be applied to the root element.

Popover Theme Variables #

These variables can be used as hooks to override this component's style at either a local or global level. The theme referenced below is whatever theme is available from props to the instance of this component.

VariableValue
PopoverArrow_backgroundColortheme.panel_backgroundColor
PopoverArrow_borderColortheme.panel_borderColor
PopoverContent_backgroundColortheme.panel_backgroundColor
PopoverContent_borderColortheme.panel_borderColor
PopoverContent_borderRadiustheme.borderRadius_1
PopoverContent_boxShadowtheme.boxShadow_2
PopoverContent_colortheme.color
PopoverContent_paddingVerticaltheme.space_inset_sm
PopoverContent_maxWidthnone
PopoverContent_zIndextheme.zIndex_100
PopoverContentBlock_marginVerticaltheme.space_stack_sm
PopoverContentBlock_paddingHorizontaltheme.space_inset_md

Usage #

When/How to Use #

Popovers contain content providing clarification for other interface elements. Since popovers are usually triggered with deliberate user actions, they can contain more complex information than a tooltip which appears upon hovering/focusing an element.

  • Keep content short. Don't put so much content that the tooltip requires a scrollbar.
  • Popovers can be used to implement other custom behaviors or widgets such as color pickers, or other task-specific custom inputs.
  • Popovers could be chained together in application logic to create walkthroughs for onboarding.

Best Practices #

Use Popover to provide extra context for selected interface elements.

Don't place long or extra-wide content in a Popover. If more context is needed, provide a link to another resource with more detail. If you must display wide content, add a max-width value to constrain the layout.

Light years star stuff harvesting star light citizens of distant epochs encyclopaedia galactica.