Security News
CISA Brings KEV Data to GitHub
CISA's KEV data is now on GitHub, offering easier access, API integration, commit history tracking, and automated updates for security teams and researchers.
styled-components-modifiers
Advanced tools
A library that enables BEM flavored modifiers to styled components
Styled Components are incredibly useful when building an application, but the community lacks guidelines and best practices for how to structure, organize, and modify a component library. Fortunately, the CSS ecosystem has several solutions for this, including the very well-thought-out Block, Element, Modifier (BEM) conventions.
This library enhances styled-components
by allowing you to use BEM-flavored conventions when building your components.
Our method for structuring Blocks and Elements doesn’t actually require any special tooling. It’s just a simple convention we use for namespacing the components, add the Elements as properties of a Block component:
// Define your Button styled component (the Block)
const Button = styled.button``;
// Define your Icon styled component (the Element)
const Icon = styled(IconComponent)``;
// Add the Icon as a property of the Button
Button.Icon = Icon;
// To render these components...
render() {
return (
<Button>
<Button.Icon />
</Button>
)
}
This gives us a nice namespacing that's easy to visualize in a Blocks and Elements structure.
But what about modifiers?
This tool allows you to implement modifiers and apply them to
styled-components
like this:
<Button modifiers={['success', 'large']}>...</Button>
or as a single string like this:
<Button modifiers="success">...</Button>
The modifiers are passed in as an array of flags or a single flag. Each flag changes the appearance of the Block or Element component. When passing in an array, the values are filtered and only strings are used, which means that it is safe to do the following:
<Button modifiers={['large', isLoading && 'loading']}>...</Button>
which, if isLoading
is false
, resolves to:
<Button modifiers={['large', false]}>...</Button>
In this case only large
will be used.
This package is
available on npm as styled-components-modifiers
.
To install the latest stable version with npm
:
$ npm install styled-components-modifiers --save
...or with yarn
:
$ yarn add styled-components-modifiers
The core of styled-components-modifiers
is a modifier configuration object.
The keys in this object become the available flags that can be passed to the
component's modifiers
prop. Each value defines a function that returns a CSS
style string.
For our demo, let's first set up a modifier configuration object:
const MODIFIER_CONFIG = {
// The functions receive the props of the component as the only argument.
// Here, we destructure the theme from the argument for use within the modifier styling.
disabled: ({ theme }) => `
// These styles are applied any time this modifier is used.
background-color: ${theme.colors.chrome_400};
color: ${theme.colors.chrome_100};
`,
// Alternatively, you can return an object with your styles under the key `styles`.
success: ({ theme }) => ({
styles: `
background-color: ${theme.colors.success};
`,
}),
warning: ({ theme }) => `
background-color: ${theme.colors.warning};
`,
large: () => `
height: 3em;
width: 6em;
`,
};
Then, we need to apply the modifier configuration object (MODIFIER_CONFIG
) to
the styled component we want to modify:
import styled from 'styled-components';
import { applyStyleModifiers } from 'styled-components-modifiers';
const Button = styled.button`
// Any styles that won't change or may be overruled can go above where you
// apply the style modifiers. In BEM, these would be the styles you apply in
// either the Block or Element class's primary definition.
font-size: 24px;
padding: 16px;
// Then apply the modifier configuration.
${applyStyleModifiers(MODIFIER_CONFIG)};
`;
export default Button;
The end result is a block (Button
) with four available modifiers (disabled
,
success
, warning
, and large
).
Because the modifiers are an arbitrary array of flags, it is very easy to pass a
value as a modifier that is not found in the component's modifier configuration
object. Fortunately, we have a tool to help with that: you can validate the
modifiers
prop with styleModifierPropTypes
:
// In the Button component's file
import { styleModifierPropTypes } from 'styled-components-modifiers';
// ...the Button definition, as seen above, goes here...
Button.propTypes = {
modifiers: styleModifierPropTypes(MODIFIER_CONFIG),
};
This will validate that only keys found within our MODIFIER_CONFIG
are
supplied to the styled component. It will also throw a PropTypes
error if an
invalid modifier is used.
Applying modifiers when rendering the component is as simple as providing a
modifiers
prop. The prop should be an array of strings that correspond to keys
in the modifier configuration object applied to the component.
function Form() {
return (
<div>
{/* ...the rest of form goes here... */}
{/* Render a button, and give it a `modifiers` prop with the desired modifiers. */}
<Button modifiers="success" />
</div>
);
}
In the example above, our button will have the styles
from the success
modifier applied.
When designing components that are intended to be responsive, you may find it
useful to apply different styles based on a size
prop as shown below.
import styled from 'styled-components';
import {
applyResponsiveStyleModifiers,
applyStyleModifiers,
responsiveStyleModifierPropTypes,
styleModifierPropTypes,
} from 'styled-components-modifiers';
// Define the MODIFIER_CONFIG in exactly the same way as above. You would use the same
// modifier configuration for responsive and non-responsive modifiers.
const Button = styled.button`
// ...define your base styles here...
// Apply the modifier configuration:
${applyStyleModifiers(MODIFIER_CONFIG)}
// Then apply the responsive modifiers.
// This must happen AFTER the normal modifiers have been applied.
${applyResponsiveStyleModifiers(MODIFIER_CONFIG)}
`;
Button.propTypes = {
// Setup validation of the "normal" modifier flags:
modifiers: styleModifierPropTypes(MODIFIER_CONFIG),
// You can also validate the responsive modifier flags:
responsiveModifiers: responsiveStyleModifierPropTypes(MODIFIER_CONFIG),
};
export default Button;
Using responsive modifiers is a little bit different, though, but just as simple:
<Button
responsiveModifiers={{
small: 'disabled',
medium: ['success', 'large'],
}}
size={getTheSizeFromSomewhere()}
/>
It works by matching the size
prop provided to the component with the keys of
the responsiveModifiers
prop, and then applying the appropriate modifier(s)
based on the corresponding value in responsiveModifiers
.
So, for example, when Button
receives a prop size
with a value equal to
medium
, the modifiers success
and large
will be applied to the Button
.
If size
does not match any key in the responsiveModifiers
, no additional
modifiers will be applied. Your normal modifiers
array will still work exactly
the same.
Tada! Responsive styling!
Finally, let’s say you want to apply multiple modifier arrays, or perhaps you
just really don't like naming the prop modifiers
. You can name the prop
something else when you apply the props to your component:
const Button = styled.button`
// the prop used for passing modifiers to this button will be
// named `altPropName` instead of the default `modifiers`:
${applyStyleModifiers(MODIFIER_CONFIG, 'altPropName')}
`;
The same can be done when you applyResponsiveStyleModifiers
.
Here's your chance to showcase work you are proud of! Feel free to add a link to any projects using Styled Components Modifiers:
Websites/ Apps:
Component Libraries:
We are thankful for any contributions made by the community. By contributing you agree to abide by the Code of Conduct in our Contributing Guidelines.
FAQs
A library that enables BEM flavored modifiers to styled components
The npm package styled-components-modifiers receives a total of 1,645 weekly downloads. As such, styled-components-modifiers popularity was classified as popular.
We found that styled-components-modifiers demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
CISA's KEV data is now on GitHub, offering easier access, API integration, commit history tracking, and automated updates for security teams and researchers.
Security News
Opengrep forks Semgrep to preserve open source SAST in response to controversial licensing changes.
Security News
Critics call the Node.js EOL CVE a misuse of the system, sparking debate over CVE standards and the growing noise in vulnerability databases.