I'm currently using NextJS along with CSS Modules for styling purposes.
One of my goals is to adjust the appearance of a component in different scenarios:
- When it's rendered normally on a page, utilizing props to specify className modifiers.
- When it's rendered within a specific parent component.
- When it's rendered within a specific parent component as props.children.
I have solutions working for all these scenarios, but I'm wondering if any of these methods are considered bad practice or if there might be better alternatives to explore (especially for scenario 3).
For example, let's consider a simple Button component:
Scenario 1:
button.module.scss
.button {
color: 'black';
}
.red {
color: 'red';
}
.blue {
color: 'blue';
}
Button.jsx
import styles from './button.module.scss';
const Button = (props) => {
const classNames = [styles.button];
props.modifiers.map((modifier) => {
classNames.push(styles[modifier]);
});
return (
<button className={classNames.join(' ')}>{props.text}</button>
);
}
export default Button;
Page.jsx
<Button text={`Test`}/>
<Button text={`Test`} modifiers={[`red`]}/>
<Button text={`Test`} blue={[`red`]}//>
Scenario 2:
Now, imagine needing to change the styling of the Button component when it's placed inside ParentComponent (and potentially combined with the previous method).
parent-component.module.scss
.button {
background-color: 'green';
}
ParentComponent.jsx
import styles from './parent-component.module.scss';
import Button from 'components/button/Button.jsx';
const ParentComponent = (props) => {
return (
<>
<Button text={`Test`} modifiers={[styles.button}>
<Button text={`Test`} modifiers={[`red`, styles.button]}>
</>
);
}
Button.jsx needs updating to handle this new requirement:
props.modifiers.map((modifier) => {
classNames.push(styles[modifier] || modifier);
});
Scenario 3:
ParentComponent.jsx
import styles from './parent-component.module.scss';
const ParentComponent = (props) => {
return (
<div>{props.children}</div>
);
}
// Expose styles on the exported component so we can reference them in page.jsx
ParentComponent.styles = styles;
export default ParentComponent;
Page.jsx
<ParentComponent>
<Button text={`Test`} modifiers={[ParentComponent.styles.button]}>
</ParentComponent>
My background is in BEM, where I typically use a technique like the following to address similar challenges: Source
.component {
$self: &;
display: block;
max-width: 30rem;
min-height: 30rem;
&--reversed {
background: white;
border-color: lightgray;
#{ $self }__child-element {
background: rebeccapurple;
}
}
}
Any advice or suggestions would be greatly appreciated.