View on GitHub

React Popover

Smart popover component for React. Click anywhere to dismiss it

Overview

The popover appears as some sort of tooltip when you click on a triggering element. I am always trying to make my components behave as natural / native-like as possible. This popover component can be positioned left/right/above/below the triggering element and it disappears the moment you interact with anything else on the page. If you try to open another popover or simply click away (anywhere on the page), the popover will close. It will also close if you click its trigger again.

You can use the popover to display contextual information or even for menus…maybe a “more links” sort of menu.

The stying for the popover is minimal but you can bring your own styles.

Installation

npm i @terebentina/react-popover -S

Usage

import React from 'react';
import Popover from '@terebentina/react-popover';

import '@terebentina/react-popover/lib/styles.css';

class MyComponent extends React.Component {
  render() {
    return (
      <div>
        If you want to see a nice popover 
        <Popover position="bottom" className="awesome" trigger="click me">
          here I am in all my glory!
        </Popover>
      </div>
    );
  }
}

Importing the default styles is optional. You can either import them from here or from your sass files and overwrite or not import them at all and implement them yourself. The html structure is very simple and clear.

Demo

You can see a demo in the box below but there's a catch...because this very page was built statically without React, clicking to dismiss the popover works just inside the box, the rest of the page is not set up to handle that. Just imagine that the box below is the whole page :)

Html Structure

The popover is rendered with the following html:

<div class="popover popover--bottom popover--active">
  <a href="#" class="popover_trigger">your trigger here</a>
  <div class="popover_content">
    your content here
  </div>
</div>
  • .popover--active is added when the popover is shown (and removed when hidden).
  • .popover--top, .popover--bottom, .popover--left, .popover--right the position of the content relative to the trigger.
  • any class you add to the popover component is also added on div.popover (<Popover className="foo" ...). See below.

Properties

  • position one of bottom, top, left, right to specify where the content should appear relative to the trigger element. Defaults to top if not specified. Adds the popover--<position> class to the main div (e.g. position--left).
  • className classes that you want added to the main div. These can help you style the trigger and content any way you like.
  • trigger a simple string or a react node (e.g. <Popover trigger="click me" /> or <Popover trigger={<span>or <strong>me</strong></span>} />). Whatever you use here is going to be wrapped into an <a> element and be used as the trigger for the popover. So don’t use an <a> here! With the examples above, this will become <a href="#">click me</a> and <a href="#"><span>or <strong>me</strong></span></a>.

Dismiss on click

A good UX shouldn’t have multiple bits of information/context menus open all over the interface in the form of popovers. So, ideally, only 1 popover should be open at any one time. As a well behaving popover, this popover closes when you click anywhere on the page, including when you open another popover. To achieve this it needs a bit of help from you: you need to add a catch-all component in your most top level component so that clicks are caught and a close event is dispatched to all popovers. Don’t worry, this is very simple. Suppose you have the following structure:

// App.jsx
import SubComponent from './SubComponent.jsx';

class App extends React.Component {
  render() {
    return (
      <div className="myAwesomeApp">
        <SubComponent />
      </div>
    );
  }
}


// SubComponent.jsx
import Popover from '@terebentina/react-popover';

class SubComponent extends React.Component {
  render() {
    return (
      <div>
        <Popover trigger="click me">popover content</Popover>
      </div>
    );
  }
}

With the above structure the popover would be shown when clicking on click me and hidden when clicking it again but it won’t disappear if you’d click anywhere else on the page. If that’s all you ever wanted from a popover then you’re good. But if not, see below:

// App.jsx
import SubComponent from './SubComponent.jsx';
import { PopoverWrapper } from '@terebentina/react-popover';

class App extends React.Component {
  render() {
    return (
      <PopoverWrapper className="myAwesomeApp">
        <SubComponent />
      </PopoverWrapper>
    );
  }
}


// SubComponent.jsx same as above

The PopoverWrapper component returns a <div> with an onClick event attached. When the click on the trigger bubbles up through the DOM up to PopoverWrapper, it is caught there and a notification is then sent to all popovers to close.

Obviously, you could have kept the original structure and wrapped everything in PopoverWrapper:

render() {
  return (
    <PopoverWrapper>
      <div className="myAwesomeApp">
        <SubComponent />
      </div>
    </PopoverWrapper>
  );
}
chevron-right twitter github hamburger