react-modal-portal
TypeScript icon, indicating that this package has built-in type declarations

0.0.4 • Public • Published

react-modal-portal

NPM version Release XO code style

Components

The modal components are layout components which render their children into a modal container, either at a specific place in the DOM (portals) or in-place.

By default, modals are rendered to the end of the document's body.

Modal

The naked component (with no styles applied) is exported as Modal. The markup produced does apply some CSS classnames, and should render some markup similar to the following sample.

<div class="modal">
    <div class="backdrop"></div>
    <div class="window">
        <div class="title">
            <label for="x">
                <!-- title -->
            </label>
            <span tabIndex="9999" class="icon" role="button">
                &times;
            </span>
        </div>
        <div id="x" class="content">
            <!-- child content -->
        </div>
    </div>
</div>

StyledModal

This is the naked modal wrapped with styled-components and a default theme.

Some basic examples showing the default styles and bundled triggers are available at https://dominicbirch.github.io/react-modal-portal.

There are many ways to customize the appearance of the modal some suggestions which immediately sprint to mind are as follows.

Style it from scratch

To do this, just work with the naked Modal component and override using the class names it renders.

.modal {
    .backdrop {
        background-color: hotpink;
    }
}

The main advantage to doing this will be that there is minimal overhead, no need for styled-components, themes, or any of the default styles in your bundle.

This approach also gives you immediate control over how to chunk and serve your styles, whether that's in CSS or JS.

Provide a theme

If you are already using a styled-components theme, you will notice that the library adds a modal property to the default theme's abstraction; you can use this to adjust the basic settings of the default theme.

Even if you aren't using styled-components, you can pass it a theme object; either by adding a styled-components theme context to your app, or by passing one in to the modal's props.

You might decide to make some small changes like removing the whitespace to create a minimal layout container, then let the child content handle appearance for exmaple.

import React from "react";
import StyledModal, { defaultTheme } from "react-modal-portal";

export default () => 
    <StyledModal theme={{modal: { ...defaultTheme.modal, whitespace: 0 }}}>
        {/* your child content here */}
    </StyledModal>;

Higher-Order Components

The following may be used to augment the modal components as you see fit; they are intentionally kept separate rather than exporting lots of variations to offer more control with a smaller output.

Layouts

The library exports a Higher-Order Component factory, withLayout, which may be used to apply a given layout component to other components without repeatedly adding them to TSX/JSX with every usage. The HOC may be used with any component which accepts children.

The withLayout Higher-Order Component can be applied to class components as a decorator, as shown in the following example.

import React from "react";
import StyledModal from "react-modal-portal";

type Props = {
    onClose?: () => void;
    onChange?: (value: any) => void;
};

@withLayout(StyledModal, ({onClose}) => ({
    onClose,
    title: "Have you considered giving us more money?",
}))
export class Upsell extends React.Component<Props> {
    // ...
}

The named class export is replaced with a React.ComponentType<Props> where the defaultProps of Upsell are preserved, and the displayName is set as withStyledModal(Upsell).

Alternatively, it may also be applied without the decorator syntax above as follows.

export function Confirmation() {
    // ...
}

export const ConfirmationModal = withLayout(StyledModal, () => ({
    title: "Are you sure?",
}))(Confirmation);

Toggles

These functions can be used to reduce repetition of showing/hiding modals in response to clicking buttons, links.

toggled(componentType)

This is a simple Higher-Order Component or component decorator; use this when you want to augment a ModalLike component to include a toggle control, adding props to control the toggle used.

import { toggled, StyledModal } from "react-modal-portal";

export const ModalWithToggle = toggled(StyledModal);

withToggle(toggleOptions)(componentType)

This is a Higher-Order Component factory which can be used to create a decorator which creates a specific toggle for a ModalLike component, preserving the original ModalLike component's props.

Apply it as a decorator as follows:

import { withToggle, ModalProps } from "react-modal-portal";

@withToggle({
    kind: "button",
    label: "Show me the modal!",
})
export default class MyFancyModal extends React.Component<ModalProps> {
    // ...
}

Or alternatively,

import { withToggle, StyledModal } from "react-modal-portal";

export const ModalWithToggleButton = withToggle({ 
    kind: "button",
    label: "show",
    hideLabel: "hide",
})(StyledModal);

Hooks

All of the logical aspects of the modal components are exported as hooks; this should help if there's a need to create a different modal component with the same props/behavior.

  • useToggle - Returns a ToggleState for the given props.
  • useModalContainer - Returns a DOM reference for use as a portal target.
  • useBodyScrollLock - Used to control scrolling of background content.

Package Sidebar

Install

npm i react-modal-portal

Weekly Downloads

1

Version

0.0.4

License

MIT

Unpacked Size

25 kB

Total Files

6

Last publish

Collaborators

  • dominicbirch