The <Portal/> component renders its children into a new "subtree" outside of current component hierarchy. You can think of it as a declarative appendChild(), or jQuery's $.fn.appendTo(). The children of <Portal/> component will be appended to the container specified.

It looks like I will render here.
class PortalExample extends React.Component {
  constructor(...args) {
    super(...args);
    this.state = { show: false };

    this.show = () => this.setState({ show: true });
  }

  render() {
    let child = <span>But I actually render here!</span>;

    return (
      <div className="portal-example">
        <Button bsStyle="primary" onClick={this.show}>
          Render Child
        </Button>
        <div className="panel panel-default">
          <div className="panel-body">
            <span>It looks like I will render here.</span>

            <Portal container={() => this.container}>
              {this.state.show && child}
            </Portal>
          </div>
        </div>

        <div className="panel panel-default">
          <div
            ref={c => {
              this.container = c;
            }}
            className="panel-body"
          />
        </div>
      </div>
    );
  }
}
render(<PortalExample />);
NameTypeDefaultDescription
container
componentOrElement |
function

A Node, Component instance, or function that returns either. The container will have the Portal children appended to it.

onRendered
function

Love them or hate them, <Modal /> provides a solid foundation for creating dialogs, lightboxes, or whatever else. The Modal component renders its children node in front of a backdrop component.

The Modal offers a few helpful features over using just a <Portal/> component and some styles:

  • Manages dialog stacking when one-at-a-time just isn't enough.
  • Creates a backdrop, for disabling interaction below the modal.
  • It properly manages focus; moving to the modal content, and keeping it there until the modal is closed.
  • It disables scrolling of the page content while open.
  • Adds the appropriate ARIA roles are automatically.
  • Easily pluggable animations via a <Transition/> component.

Note that, in the same way the backdrop element prevents users from clicking or interacting with the page content underneath the Modal, Screen readers also need to be signaled to not to interact with page content while the Modal is open. To do this, we use a common technique of applying the aria-hidden='true' attribute to the non-Modal elements in the Modal container. This means that for a Modal to be truly modal, it should have a container that is outside your app's React hierarchy (such as the default: document.body).

let rand = () => Math.floor(Math.random() * 20) - 10;

const backdropStyle = {
  position: 'fixed',
  zIndex: 1040,
  top: 0,
  bottom: 0,
  left: 0,
  right: 0,
  backgroundColor: '#000',
  opacity: 0.5
};

const modalStyle = function() {
  // we use some psuedo random coords so nested modals
  // don't sit right on top of each other.
  let top = 50 + rand();
  let left = 50 + rand();

  return {
    position: 'fixed',
    width: 400,
    zIndex: 1040,
    top: top + '%',
    left: left + '%',
    border: '1px solid #e5e5e5',
    backgroundColor: 'white',
    boxShadow: '0 5px 15px rgba(0,0,0,.5)',
    padding: 20
  };
};

class ModalExample extends React.Component {
  constructor(...args) {
    super(...args);
    this.state = { showModal: false };

    this.close = () => {
      this.setState({ showModal: false });
    };

    this.open = () => {
      this.setState({ showModal: true });
    };
  }

  renderBackdrop(props) {
    return <div {...props} style={backdropStyle} />;
  }

  render() {
    return (
      <div className="modal-example">
        <Button onClick={this.open}>Open Modal</Button>
        <p>Click to get the full Modal experience!</p>

        <Modal
          onHide={this.close}
          style={modalStyle()}
          aria-labelledby="modal-label"
          show={this.state.showModal}
          renderBackdrop={this.renderBackdrop}
        >
          <div>
            <h4 id="modal-label">Text in a modal</h4>
            <p>
              Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
            </p>
            <ModalExample />
          </div>
        </Modal>
      </div>
    );
  }
}
render(<ModalExample />);
NameTypeDefaultDescription
show
boolean
false

Set the visibility of the Modal

container
componentOrElement |
function

A Node, Component instance, or function that returns either. The Modal is appended to it's container element.

For the sake of assistive technologies, the container should usually be the document body, so that the rest of the page content can be placed behind a virtual backdrop as well as a visual one.

onShow
function

A callback fired when the Modal is opening.

onHide
function
() => {}

A callback fired when either the backdrop is clicked, or the escape key is pressed.

The onHide callback only signals intent from the Modal, you must actually set the show prop to false for the Modal to close.

backdrop
boolean
| 'static'
true

Include a backdrop component.

renderDialog
function

A function that returns the dialog component. Useful for custom rendering. Note: the component should make sure to apply the provided ref.

 renderDialog={props => <MyDialog {...props} />}

renderBackdrop
function
props => <div {...props} />

A function that returns a backdrop component. Useful for custom backdrop rendering.

 renderBackdrop={props => <MyBackdrop {...props} />}

onEscapeKeyDown
function

A callback fired when the escape key, if specified in keyboard, is pressed.

onBackdropClick
function

A callback fired when the backdrop, if specified, is clicked.

containerClassName
string

A css class or set of classes applied to the modal container when the modal is open, and removed when it is closed.

keyboard
boolean
true

Close the modal when escape key is pressed

transition
elementType

A react-transition-group@2.0.0 <Transition/> component used to control animations for the dialog component.

backdropTransition
elementType

A react-transition-group@2.0.0 <Transition/> component used to control animations for the backdrop components.

autoFocus
boolean
true

When true The modal will automatically shift focus to itself when it opens, and replace it to the last focused element when it closes. This also works correctly with any Modal children that have the autoFocus prop.

Generally this should never be set to false as it makes the Modal less accessible to assistive technologies, like screen readers.

enforceFocus
boolean
true

When true The modal will prevent focus from leaving the Modal while open.

Generally this should never be set to false as it makes the Modal less accessible to assistive technologies, like screen readers.

restoreFocus
boolean
true

When true The modal will restore focus to previously focused element once modal is hidden

onEnter
function

Callback fired before the Modal transitions in

onEntering
function

Callback fired as the Modal begins to transition in

onEntered
function

Callback fired after the Modal finishes transitioning in

onExit
function

Callback fired right before the Modal transitions out

onExiting
function

Callback fired as the Modal begins to transition out

onExited
function

Callback fired after the Modal finishes transitioning out

manager
object
new ModalManager()

A ModalManager instance used to track and manage the state of open Modals. Useful when customizing how modals interact within a container

Built on top of <Position/> and <Portal/>, the overlay component is great for custom tooltip overlays.

Keep clicking to see the placement change.

// Styles mostly from Bootstrap.
const styles = {
  tooltip: {
    position: 'absolute',
    padding: '0 5px'
    // transition: 'all 0.2s ease-out 0.2s',
  },

  inner: {
    padding: '3px 8px',
    color: '#fff',
    textAlign: 'center',
    borderRadius: 3,
    backgroundColor: '#000',
    opacity: 0.75
  },

  arrow: {
    position: 'absolute',
    width: 0,
    height: 0,
    borderStyle: 'solid',
    opacity: 0.75
  }
};

const placementStyles = {
  left: {
    tooltip: {
      marginLeft: -3,
      padding: '0 5px'
    },

    arrow: {
      right: 0,
      borderWidth: '5px 0 5px 5px',
      borderColor: 'transparent transparent transparent #000'
    }
  },

  right: {
    tooltip: {
      marginLeft: 3,
      padding: '0 5px'
    },

    arrow: {
      left: 0,
      borderWidth: '5px 5px 5px 0',
      borderColor: 'transparent #232323 transparent transparent'
    }
  },

  top: {
    tooltip: {
      marginTop: -3,
      padding: '5px 0'
    },

    arrow: {
      bottom: 0,
      borderWidth: '5px 5px 0',
      borderColor: '#232323 transparent transparent transparent'
    }
  },

  bottom: {
    tooltip: {
      marginBottom: 3,
      padding: '5px 0'
    },

    arrow: {
      top: 0,
      borderWidth: '0 5px 5px',
      borderColor: 'transparent transparent #232323 transparent'
    }
  }
};

const PLACEMENTS = ['left', 'top', 'right', 'bottom'];

class OverlayExample extends React.Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      show: false,
      placement: null
    };

    this.onClick = () => {
      const { placement } = this.state;
      const nextPlacement = PLACEMENTS[PLACEMENTS.indexOf(placement) + 1];

      return this.setState({
        show: !!nextPlacement,
        placement: nextPlacement
      });
    };
  }

  render() {
    const { show, placement } = this.state;

    return (
      <div className="overlay-example">
        <Button
          bsStyle="primary"
          id="overlay-toggle"
          ref={c => {
            this.target = c && ReactDOM.findDOMNode(c);
          }}
          onClick={this.onClick}
        >
          I am an Overlay target
        </Button>
        <p>Keep clicking to see the placement change.</p>

        <Overlay
          show={show}
          onHide={() => this.setState({ show: false })}
          placement={placement}
          container={this}
          target={() => this.target}
        >
          {({ props, arrowProps, placement }) => {
            const placementStyle = placementStyles[placement];
            return (
              <div
                {...props}
                style={{
                  ...styles.tooltip,
                  ...placementStyle.tooltip,
                  ...props.style
                }}
              >
                <div
                  {...arrowProps}
                  style={{
                    ...styles.arrow,
                    ...placementStyle.arrow,
                    ...arrowProps.style
                  }}
                />
                <div style={{ ...styles.inner }}>
                  I&rsquo;m placed to the <strong>{placement}</strong>
                </div>
              </div>
            );
          }}
        </Overlay>
      </div>
    );
  }
}

render(<OverlayExample />);
NameTypeDefaultDescription
show
boolean

Set the visibility of the Overlay

placement
placements

Specify where the overlay element is positioned in relation to the target element

flip
boolean

Enables the Popper.js flip modifier, allowing the Overlay to automatically adjust it's placement in case of overlap with the viewport or toggle. Refer to the flip docs for more info

children required
Function ({ show: boolean, placement: Placement, outOfBoundaries: ?boolean, scheduleUpdate: () => void, props: { ref: (?HTMLElement) => void, style: { [string]: string | number }, aria-labelledby: ?string }, arrowProps: { ref: (?HTMLElement) => void, style: { [string]: string | number }, }, }) => React.Element

A render prop that returns an element to overlay and position. See the react-popper documentation for more info.

popperConfig
object

A set of popper options and props passed directly to react-popper's Popper component.

rootClose
boolean

Specify whether the overlay should trigger onHide when the user clicks outside the overlay

rootCloseEvent
RootCloseWrapper.propTypes.event

Specify event for toggling overlay

onHide
function

A Callback fired by the Overlay when it wishes to be hidden.

required when rootClose is true.

transition
elementType

A react-transition-group@2.0.0 <Transition/> component used to animate the overlay as it changes visibility.

onEnter
function

Callback fired before the Overlay transitions in

onEntering
function

Callback fired as the Overlay begins to transition in

onEntered
function

Callback fired after the Overlay finishes transitioning in

onExit
function

Callback fired right before the Overlay transitions out

onExiting
function

Callback fired as the Overlay begins to transition out

onExited
function

Callback fired after the Overlay finishes transitioning out

Dropdown is set of structural components for building, accessible dropdown menus with close-on-click, keyboard navigation, and correct focus handling. As with all the react-overlay's components its BYOS (bring your own styles). Dropdown is primarily built from three base components, you should compose to build your Dropdowns.

  • Dropdown, which wraps the menu and toggle, and handles keyboard navigation
  • Dropdown.Toggle generally a button that triggers the menu opening
  • Dropdown.Menu The overlaid, menu, positioned to the toggle with PopperJs

const Menu = ({ role }) => (
  <Dropdown.Menu flip>
    {({ show, onClose, props }) => {
      return (
        <div
          {...props}
          role={role}
          className={css`
            display: ${show ? 'flex' : 'none'};
            min-width: 150px;
            position: absolute;
            flex-direction: column;
            border: 1px solid #e5e5e5;
            background-color: white;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
            padding: 20px;
          `}
        >
          <button onClick={onClose} style={{ textAlign: 'left' }}>
            Item 1
          </button>
          <button onClick={onClose} style={{ textAlign: 'left' }}>
            Item 2
          </button>
        </div>
      );
    }}
  </Dropdown.Menu>
);

const Toggle = ({ id, children }) => (
  <Dropdown.Toggle>
    {({ toggle, show, props }) => (
      <Button id={id} {...props} onClick={toggle}>
        {children}
      </Button>
    )}
  </Dropdown.Toggle>
);

const DropdownButton = ({ show, onToggle, drop, alignEnd, title, role }) => (
  <Dropdown
    show={show}
    onToggle={onToggle}
    drop={drop}
    alignEnd={alignEnd}
    itemSelector="button:not(:disabled)"
  >
    {({ props }) => (
      <div
        {...props}
        className={css`
          position: relative;
          display: inline-block;
        `}
      >
        <Toggle id="example-toggle">{title}</Toggle>
        <Menu role={role} />
      </div>
    )}
  </Dropdown>
);

class DropdownExample extends React.Component {
  constructor(...args) {
    super(...args);
    this.state = { show: false };
  }

  render() {
    const { show } = this.state;
    return (
      <div className="dropdown-example">
        <DropdownButton
          show={show}
          onToggle={show => this.setState({ show })}
          title={`${show ? 'Close' : 'Open'} Dropdown`}
        />
        <DropdownButton alignEnd title="Align right" />

        <DropdownButton drop="up" title="Drop up" />
        <DropdownButton role="menu" title="Role 'menu'" />
      </div>
    );
  }
}

render(<DropdownExample />);
NameTypeDefaultDescription
children required
Function ({ props: { onKeyDown: (SyntheticEvent) => void, }, }) => React.Element

A render prop that returns the root dropdown element. The props argument should spread through to an element containing both the menu and toggle in order to handle keyboard events for focus management.

drop
'up' | 'left' | 'right' | 'down'

Determines the direction and location of the Menu in relation to it's Toggle.

itemSelector
string
'* > *'

A css slector string that will return focusable menu items. Selectors should be relative to the menu component: e.g. > li:not('.disabled')

alignEnd
boolean

Align the menu to the 'end' side of the placement side of the Dropdown toggle. The default placement is top-start or bottom-start.

show
boolean
 controlled by: onToggle, initial prop: defaultShow

Whether or not the Dropdown is visible.

onToggle
function
 controls show

A callback fired when the Dropdown wishes to change visibility. Called with the requested show value, the DOM event, and the source that fired it: 'click','keydown','rootClose', or 'select'.

function(
  isOpen: boolean,
  event: SyntheticEvent,
): void

NameTypeDefaultDescription
children required
Function ({ show: boolean, alignEnd: boolean, close: (?SyntheticEvent) => void, placement: Placement, outOfBoundaries: ?boolean, scheduleUpdate: () => void, props: { ref: (?HTMLElement) => void, style: { [string]: string | number }, aria-labelledby: ?string }, arrowProps: { ref: (?HTMLElement) => void, style: { [string]: string | number }, }, }) => React.Element

A render prop that returns a Menu element. The props argument should spread through to a component that can accept a ref.

show
boolean

Controls the visible state of the menu, generally this is provided by the parent Dropdown component, but may also be specified as a prop directly.

alignEnd
boolean

Aligns the dropdown menu to the 'end' of it's placement position. Generally this is provided by the parent Dropdown component, but may also be specified as a prop directly.

flip
boolean

Enables the Popper.js flip modifier, allowing the Dropdown to automatically adjust it's placement in case of overlap with the viewport or toggle. Refer to the flip docs for more info

usePopper
true | false
true

popperConfig
object

A set of popper options and props passed directly to react-popper's Popper component.

rootCloseEvent
string

Override the default event used by RootCloseWrapper.

NameTypeDefaultDescription
children required
Function ({ show: boolean, toggle: (show: boolean) => void, props: { ref: (?HTMLElement) => void, aria-haspopup: true aria-expanded: boolean }, }) => React.Element

A render prop that returns a Toggle element. The props argument should spread through to a component that can accept a ref. Use the onToggle argument to toggle the menu open or closed

The <Affix/> component toggles position: fixed; on and off, emulating the effect found with position: sticky;.

The <AutoAffix/> component wraps <Affix/> to automatically calculate offsets in many common cases.

I am an affixed element
class AffixExample extends React.Component {
  render() {
    return (
      <div className="affix-example">
        <AutoAffix viewportOffsetTop={15} container={this}>
          <div className="panel panel-default">
            <div className="panel-body">I am an affixed element</div>
          </div>
        </AutoAffix>
      </div>
    );
  }
}

render(AffixExample);
NameTypeDefaultDescription
offsetTop
number
0

Pixels to offset from top of screen when calculating position

viewportOffsetTop
number
null

When affixed, pixels to offset from top of viewport

offsetBottom
number
0

Pixels to offset from bottom of screen when calculating position

topClassName
string

CSS class or classes to apply when at top

topStyle
object

Style to apply when at top

affixClassName
string

CSS class or classes to apply when affixed

affixStyle
object

Style to apply when affixed

bottomClassName
string

CSS class or classes to apply when at bottom

bottomStyle
object

Style to apply when at bottom

onAffix
function

Callback fired right before the affixStyle and affixClassName props are rendered

onAffixed
function

Callback fired after the component affixStyle and affixClassName props have been rendered

onAffixTop
function

Callback fired right before the topStyle and topClassName props are rendered

onAffixedTop
function

Callback fired after the component topStyle and topClassName props have been rendered

onAffixBottom
function

Callback fired right before the bottomStyle and bottomClassName props are rendered

onAffixedBottom
function

Callback fired after the component bottomStyle and bottomClassName props have been rendered

NameTypeDefaultDescription
container
componentOrElement |
function

The logical container node or component for determining offset from bottom of viewport, or a function that returns it

autoWidth
boolean
true

Automatically set width when affixed

The <RootCloseWrapper/> component registers your callback on the document when rendered. Powers the <Overlay/> component. This is used achieve modal style behavior where your callback is triggered when the user tries to interact with the rest of the document or hits the esc key.

class RootCloseWrapperExample extends React.Component {
  constructor(...args) {
    super(...args);

    this.state = { show: false };

    this.show = () => this.setState({ show: true });
    this.hide = () => this.setState({ show: false });
  }

  render() {
    return (
      <div className="root-close-wrapper-example">
        <Button bsStyle="primary" onClick={this.show}>
          Render RootCloseWrapper
        </Button>

        {this.state.show && (
          <RootCloseWrapper onRootClose={this.hide}>
            <div className="panel panel-default">
              <div className="panel-body">
                <span>Click anywhere to dismiss me!</span>
              </div>
            </div>
          </RootCloseWrapper>
        )}
      </div>
    );
  }
}
render(<RootCloseWrapperExample />);
NameTypeDefaultDescription
onRootClose
function

Callback fired after click or mousedown. Also triggers when user hits esc.

children
element

Children to render.

disabled
boolean

Disable the the RootCloseWrapper, preventing it from triggering onRootClose.

event
'click' | 'mousedown'
'click'

Choose which document mouse event to bind to.

Animation of components is handled by transition props. If a component accepts a transition prop you can provide a react-transition-group@2.0.0 compatibleTransition component and it will work.

Feel free to use CSSTransition specifically, or roll your own like the below example.

ReferenceError: document is not defined
const FADE_DURATION = 200;

injectCss(`
  .fade {
    opacity: 0;
    transition: opacity ${FADE_DURATION}ms linear;
  }

  .in {
    opacity: 1;
  }

  .transition-example-modal {
    position: fixed;
    z-index: 1040;
    top: 0; bottom: 0; left: 0; right: 0;
  }

  .transition-example-backdrop {
    position: fixed;
    top: 0; bottom: 0; left: 0; right: 0;
    background-color: #000;
  }

  .transition-example-backdrop.fade.in {
    opacity: 0.5;
  }

  .transition-example-dialog {
    position: absolute;
    width: 400;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    border: 1px solid #e5e5e5;
    background-color: white;
    box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
    padding: 20px;
  }
`);

const fadeStyles = {
  entering: 'in',
  entered: 'in'
};

const Fade = ({ children, ...props }) => {
  return (
    <Transition {...props} timeout={FADE_DURATION}>
      {(status, innerProps) =>
        React.cloneElement(children, {
          ...innerProps,
          className: `fade ${fadeStyles[status]} ${children.props.className}`
        })
      }
    </Transition>
  );
};

class TransitionExample extends React.Component {
  constructor(...args) {
    super(...args);

    this.state = { showModal: false };
    this.toggleModal = () => {
      this.setState({ showModal: !this.state.showModal });
    };

    this.toggleTooltip = () => {
      this.setState({ showTooltip: !this.state.showTooltip });
    };

    this.tooltipRef = React.createRef();
  }

  render() {
    return (
      <div className="transition-example">
        <Button bsStyle="primary" onClick={this.toggleModal}>
          Show Animated Modal
        </Button>

        <Button
          bsStyle="primary"
          onClick={this.toggleTooltip}
          ref={this.tooltipRef}
        >
          Show Tooltip
        </Button>

        <Overlay
          placement="top"
          transition={Fade}
          show={this.state.showTooltip}
          modifiers={{ offset: { enabled: true, offset: '0 5px' } }}
          target={() => this.tooltipRef.current}
        >
          {({ ref, style }) => (
            <div ref={ref} className="tooltip tooltip-inner" style={style}>
              Hello there
            </div>
          )}
        </Overlay>

        <Modal
          transition={Fade}
          backdropTransition={Fade}
          className="transition-example-modal"
          backdropClassName="transition-example-backdrop"
          show={this.state.showModal}
          onHide={this.toggleModal}
        >
          <div className="transition-example-dialog">
            <h4 id="modal-label">{"I'm fading in!"}</h4>
            <p>
              Anim pariatur cliche reprehenderit, enim eiusmod high life
              accusamus terry richardson ad squid. Nihil anim keffiyeh
              helvetica, craft beer labore wes anderson cred nesciunt sapiente
              ea proident.
            </p>
          </div>
        </Modal>
      </div>
    );
  }
}

render(<TransitionExample />);