React-modal: Can you use this package with styled components?

Created on 14 Mar 2018  路  8Comments  路  Source: reactjs/react-modal

Can you use this package with styled components?

Most helpful comment

Seems to work fine using the following:

export function ReactModalAdapter({ className, modalClassName, ...props }) {
  return (
    <ReactModal
      className={modalClassName}
      portalClassName={className}
      bodyOpenClassName="portalOpen"
      {...props}
    />
  );
}

export const StyledReactModal = styled(ReactModalAdapter).attrs({
  overlayClassName: 'Overlay',
  modalClassName: 'Modal',
})`
  & .Overlay {...}
  & .Modal {...}
  &[class*='--after-open'] {...}
  &[class*='--before-close'] {...}
}`

All 8 comments

Yes, you can (I don't know if this solution is the idiomatic way), check it out:

Component
```import React from 'react';
import PropTypes from 'prop-types';
import noop from 'lodash/noop';

import ModalClose from './Close';

import { StyledModal, Container } from './style';

const propTypes = {
isOpen: PropTypes.bool.isRequired,
contentLabel: PropTypes.string.isRequired,
children: PropTypes.node.isRequired,
onClose: PropTypes.func,
className: PropTypes.string,
tall: PropTypes.bool,
noCloseLabel: PropTypes.bool,
};

const defaultProps = {
className: '',
onClose: noop,
tall: false,
noCloseLabel: false,
};

const ModalBox = ({
isOpen,
contentLabel,
children,
onClose,
className,
tall,
noCloseLabel,
...props
}) => (
isOpen={isOpen}
contentLabel={contentLabel}
onRequestClose={onClose}
className={className}
tall={tall}
{...props}
>
{noCloseLabel || }
{children}


);

ModalBox.propTypes = propTypes;
ModalBox.defaultProps = defaultProps;

export default ModalBox;

**Style (where I am importing react-modal)**

import styled from 'styled-components';
import ReactModal from 'react-modal';

export const StyledModal = styled(ReactModal) position: fixed; top: 0; right: 0; bottom: 0; left: 0; display: flex; align-items: ${({ tall }) => (tall ? 'flex-start' : 'center')}; justify-content: center; background-color: rgba(29, 49, 65, 0.8); overflow-x: hidden; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 1.2rem; z-index: 1031; ;
StyledModal.displayName = 'StyledModal';

export const Container = styled.div background-color: ${({ theme }) => theme.color.white}; max-width: 700px; padding: 3em 2em; position: relative; ;
Container.displayName = 'Container';
```

Cannot do with styled components. For some reason the above does not work

Yes, you can (I don't know if this solution is the idiomatic way), check it out:

Component

import PropTypes from 'prop-types';
import noop from 'lodash/noop';

import ModalClose from './Close';

import { StyledModal, Container } from './style';

const propTypes = {
  isOpen: PropTypes.bool.isRequired,
  contentLabel: PropTypes.string.isRequired,
  children: PropTypes.node.isRequired,
  onClose: PropTypes.func,
  className: PropTypes.string,
  tall: PropTypes.bool,
  noCloseLabel: PropTypes.bool,
};

const defaultProps = {
  className: '',
  onClose: noop,
  tall: false,
  noCloseLabel: false,
};

const ModalBox = ({ 
  isOpen, 
  contentLabel, 
  children, 
  onClose, 
  className, 
  tall, 
  noCloseLabel,
  ...props
   }) => (
    <StyledModal
      isOpen={isOpen}
      contentLabel={contentLabel}
      onRequestClose={onClose}
      className={className}
      tall={tall}
      {...props}
   >
      <Container className={className}>
        {noCloseLabel || <ModalClose onClick={onClose} />}
        {children}
      </Container>
   </StyledModal>
);

ModalBox.propTypes = propTypes;
ModalBox.defaultProps = defaultProps;

export default ModalBox;

Style (where I am importing react-modal)

import styled from 'styled-components';
import ReactModal from 'react-modal';

export const StyledModal = styled(ReactModal)`
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  display: flex;
  align-items: ${({ tall }) => (tall ? 'flex-start' : 'center')};
  justify-content: center;
  background-color: rgba(29, 49, 65, 0.8);
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 1.2rem;
  z-index: 1031;
`;
StyledModal.displayName = 'StyledModal';

export const Container = styled.div`
  background-color: ${({ theme }) => theme.color.white};
  max-width: 700px;
  padding: 3em 2em;
  position: relative;
`;
Container.displayName = 'Container';

how can we style overlay?

So... does it work with styled components or not?

Seems to work fine using the following:

export function ReactModalAdapter({ className, modalClassName, ...props }) {
  return (
    <ReactModal
      className={modalClassName}
      portalClassName={className}
      bodyOpenClassName="portalOpen"
      {...props}
    />
  );
}

export const StyledReactModal = styled(ReactModalAdapter).attrs({
  overlayClassName: 'Overlay',
  modalClassName: 'Modal',
})`
  & .Overlay {...}
  & .Modal {...}
  &[class*='--after-open'] {...}
  &[class*='--before-close'] {...}
}`

@lcvbeek You can even drop the overlayClassName, you can target it with .ReactModal__Overlay in the styled-components' CSS. Also, I would suggest not overriding the bodyOpenClassName - I think it's best to override as little as possible.

@thexpand actually you have to specify the overlay class name, if you want to style it.

This is because if no overlay class name is specified, react-modal adds some inline styles which will take precedence over any styles you might supply in a .ReactModal__Overlay class you provide (for example, if you have .ReactModal__Overlay { background: pink; }, you will see that the default style will be set inline on the element (rgba(255,255,255, 0.75).

refer:
http://reactcommunity.org/react-modal/styles/
http://reactcommunity.org/react-modal/styles/classes/

If you specify className, the default content styles will not be applied. Likewise, if you specify overlayClassName, the default overlay styles will not be applied.

You can still use overlayClassName: 'ReactModal__Overlay' if you want, but in any case it must be specified.

I found another way to do this, by using the element props (see docs):

import ReactModal from "react-modal";
import styled from "styled-components";

const ModalStyle = styled.div`
  ...
`;

const OverlayStyle = styled.div`
  ...
`;

function Modal() {
  return (
    // Note that the className properties are required to prevent react-modal
    // from overriding the styles defined in contentElement and overlayElement
    <ReactModal
      className="_"
      overlayClassName="_"
      contentElement={(props, children) => <ModalStyle {...props}>{children}</ModalStyle>}
      overlayElement={(props, contentElement) => <OverlayStyle {...props}>{contentElement}</OverlayStyle>}
    >
      ...
    </ReactModal>
  );
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

tairy-potter picture tairy-potter  路  3Comments

CXJoyce picture CXJoyce  路  4Comments

phaedryx picture phaedryx  路  4Comments

kinucris picture kinucris  路  3Comments

gavmck picture gavmck  路  3Comments