rakitin
rakitin

Reputation: 2185

How to get CSS Modules to work with Reactstrap cssModule propType?

I noticed most form elements in the Reactstrap documentation have a PropType of a cssModule. I would assume that means I could override the default Reactstrap styles and do something like this:

Formtext.module.css

.formtext {
  background-color: blue;
  border: 2px solid black;
  margin: 10px;
}

SimpleForm.jsx

import styles from "./Formtext.module.css";
...

<FormText cssModule={styles.formtext}>
   This is some placeholder help text...
</FormText>

```

However, this doesn't seem to work. Checking my react dev tools the cssModule prop evaluates to undefined.

I'm using Using Reactstrap 5.0 and create-react-app 1.1.5

Is there something I'm unaware of that I need to do? Do I need to eject to be able to use css-modules? Can someone point me to an example of how to use the Reactstrap's cssModule prop correctly?


For reference here is the proptypes definition from Reactstrap docs

FormText.propTypes = {
  children: PropTypes.node,
  inline: PropTypes.bool,
  tag: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), // default: 'small'
  color: PropTypes.string, // default: 'muted'
  className: PropTypes.string,
  cssModule: PropTypes.object,
};

Upvotes: 3

Views: 4779

Answers (2)

Vočko
Vočko

Reputation: 2996

I did not really get the accepted answer, but I had the same problem recently and in my opinion, cssModule behaves exactly as one would expect. You just pass an imported module object and then specify classes they will be referenced towards the module.

Here is my example (from create-react-app) how I did fix Navbar to get it's bootstrap styles from my bootstrap module (as I don't import bootstrap globally):

import cx from 'classnames';
import bootstrap from 'bootstrap/dist/css/bootstrap.css';
import navbar from './navbar.css';

let styles = Object.assign({}, bootstrap, navbar);

public render() {
    return (<Navbar cssModule={styles} className={cx(styles.navbarExpandSm, styles.navbarToggleableSm, styles.borderBottom, styles.boxShadow, styles.mb3)} light>[your menu here]</Navbar>);
}

This simply says the control to take the styles module and reference all the class names passed in classNames towards it. If you take a look at the mapToCssModules method, it is exactly what it does. https://github.com/reactstrap/reactstrap/blob/d3cd4ea79dcaf478af5984f760ff1290406f62a5/src/utils.js#L53

In my case, it allows the control to pick up the original bootstrap styles and I can override what I need in my own module.

Upvotes: 3

Walker
Walker

Reputation: 130

On cssModule

It looks like cssModules doesn't behave quite like you would think; the prop doesn't take a single, overriding class - it takes a rejected class and a replacement class.

Reactstrap uses mapToCssModules to get this done. See its documentation here. Take note of the usage example:

<Example tag="div" cssModule={{ 'w-100': 'w-75' }} />

So your case would look something like this:

<FormText cssModule={{ 'form-text' : styles.formtext }} />

This will completely surpress the 'form-text' class though (which in your case, only contributes display: block. If you'd like to override more selectively, see below.


Try this instead

In the FormText source code, it looks like you may be able to do your overrides in a different way:

  • If you want to omit the form-text class altogether, include inline as a prop,
  • If you want to omit any color-related bootstrap classes, set 'color' to false (or something falsy),
  • set the className prop to your CSS Module object (styles.formtext).

<FormText className={styles.formText} color='' inline> Test formtext </FormText>

The most important part here is actually the className prop. You can also further override styling by including a tag prop (again, check the FormText docs).


Hope this was helpful! Happy holidays! 🦃🎅

Upvotes: 6

Related Questions