reactjs / react-modal

Accessible modal dialog component for React
http://reactcommunity.org/react-modal
MIT License
7.37k stars 809 forks source link

When I try to apply css variables from css modules in React, nothing is passed #1021

Closed uuzelac closed 1 year ago

uuzelac commented 1 year ago

Summary:

This is my styles.module.css that I imported into my Modal.tsx:

.modalOverlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(13, 13, 13, 0.52);
}

.modalContent {
  position: absolute;
  top: 50%;
  left: 50%;
  right: auto;
  bottom: auto;
  margin-right: -50%;
  transform: translate(-50%, -50%);
  padding: 40px;
  background-color: var(--gray);
  border-radius: 20px;
  outline: none;
  box-shadow: 2px 3px 24px rgba(203, 190, 163, 0.27);
}
import Modal from 'react-modal';
import styles from './styles.module.css';

<Modal
      isOpen={modalIsOpened}
      className={styles.modalContent}
      overlayClassName={styles.modalOverlay}>

   ...
   <CustomForm ... />
   <CustomButton ... />
</Modal>

The problem is that this var(--gray) doesn't work. Also if I import any custom button or form that is also using styles.module.css that contains var(--some-color) that var returns nothing. I am using theme provider around my <App /> component that holds all the values for the colors values. I need this for the theme switching.

RajivRnjan commented 1 year ago

I am interested to work on this issue under Quine. So please assign me this issue to me.

Zaid1681 commented 1 year ago

Hey , assign this issue to me i am interested to work on this issue under quine

hklohani commented 1 year ago

style={{ '--gray': 'your color', }}

Hey, do like this and let me know if it works

diasbruno commented 1 year ago

@uuzelac @RajivRnjan @Zaid1681 Thanks for the interest on working on this, but first things first...

diasbruno commented 1 year ago

Second and the funny one....what is quine? Can you guys point me to this project? Hope this is not refering to quine

uuzelac commented 1 year ago

Sorry guys for the late response, I was busy recently. I find the way around for this problem by providing theme inside the ReactModalPortal this way:

import ReactModal from 'react-modal';
import { useTheme } from '../../theme/useTheme';

interface ModalInterface {
  isOpen: boolean;
  children: React.ReactNode;
}

const Modal = ({ isOpen, children }: ModalInterface): JSX.Element => {
  const { theme } = useTheme();

  return (
    <ReactModal
      isOpen={isOpen}
      className={styles.modalContent}
      overlayClassName={styles.modalOverlay}>
      <div style={{ ...(theme as CSSProperties) }}>{children}</div>
    </ReactModal>
  );
};

By this way all my children components inside ReactModal can now receive var(--someValue) from css modules.

But this was not the complete solution because ReactModal itself cannot see var properties from styles.modalContent, so I passed additional styles directly to ReactModal using style prop. So the final solution looks like this:

import ReactModal from 'react-modal';
import { useTheme } from '../../theme/useTheme';

interface ModalInterface {
  isOpen: boolean;
  children: React.ReactNode;
}

const Modal = ({ isOpen, children }: ModalInterface): JSX.Element => {
  const { theme, themeType } = useTheme();
  const additionalStyles =
    themeType === THEME_LIGHT
      ? { overlay: {}, content: { backgroundColor: Color.WHITE } }
      : { overlay: {}, content: { backgroundColor: Color.BLACK} };
  return (
    <ReactModal
      isOpen={isOpen}
      className={styles.modalContent}
      overlayClassName={styles.modalOverlay}
      style={additionalStyles}>
      <div style={{ ...(theme as CSSProperties) }}>{children}</div>
    </ReactModal>
  );
};

This solution is bit more like a hack, but this way all my css modules inside ReactModal could now access var properties and I could pass inline style to ReactModal itself.

I really hope this solution could help someone save a lot of hours.

Cheers :)

diasbruno commented 1 year ago

@uuzelac Great that you've found a solution, but this seems to be too much work for a something that looks really simple.

Can, any of you guys, make a reproducible example so we can see where the problem is?

uuzelac commented 1 year ago

So imagine that you have just two colors that you pass as an object to your <Root /> component like this:

theme = {
    '--black': '#000000',
    '--white': '#FFFFFFF',
}
const App = () => {
  return (
    <div style={{ ...theme }}>
      <Root />
    </div>
  );
};

This way all css modules for example styles.module.css in your Root can access these values like this:

.button {
  background-color: var(--black);
}

except ReactModal because it is created outside of the App component. As I saw in the documentation ReactModal is a React Portal and it is rendered on the top of everything which is ok but that makes a bit difficult to use themes, providers or something that is a wrapper around Root component. I didn't find any other elegant solution for this case scenario. Maybe there is something in the documentation which I overlooked, so please point me in the right direction if I made some mistake.

Thanks

diasbruno commented 1 year ago

Thanks. Is there anything else in the middle that handles the theme's object to be properly scoped? A library, a compiler transformer (loader or whatever)?