
Research
/Security News
Weaponizing Discord for Command and Control Across npm, PyPI, and RubyGems.org
Socket researchers uncover how threat actors weaponize Discord across the npm, PyPI, and RubyGems ecosystems to exfiltrate sensitive data.
babel-plugin-style-props-emotion
Advanced tools
The adapter to utilize style-props with the Emotion CSS-in-JS library.
Use theme aware style props on any JSX element using emotion
.
<h1 mt={0} mb={4} color="primary" textDecoration="underline">
Hello
</h1>
<ThemeProvider>
, or just use plain CSS units and
properties.# yarn
yarn add -D babel-plugin-style-props babel-plugin-style-props-emotion
# npm
npm i -D babel-plugin-style-props babel-plugin-style-props-emotion
Add the appropriate plugins to your Babel config file in the order as shown
below. Be sure that the emotion preset is included in your list of presets
.
// babel.config.js
module.exports = {
presets: [
'@babel/preset-env',
'@babel/preset-react',
'@emotion/babel-preset-css-prop',
],
plugins: ['babel-plugin-style-props', 'babel-plugin-style-props-emotion'],
}
<ThemeProvider>
Place your <ThemeProvider>
component around your React app as you normally
would, and pass your theme
object.
import { ThemeProvider } from 'emotion-theming'
import { theme } from './theme'
const YourApp = () => (
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
)
For a barebones theme to start working with, see this example.
For a TailwindCSS copycat theme to get started with, see this example.
Your theme
should follow the styled-system
specification that you can find
detailed here.
babel-plugin-style-props-emotion
converts style props to values in a css
prop. This allows emotion
to parse the styles into CSS.
// Your JSX
<div color='red' px={5} />
// Output JSX (simplified)
<div
css={theme => ({
color: theme.colors.red,
paddingLeft: theme.space[5],
paddingRight: theme.space[5],
})}
/>
If you've used styled-system
or other similar styling solutions, this plugin's
usage should be familiar.
When colors, fonts, font sizes, a spacing scale, or other values are definied in
a <ThemeProvider>
, the values can be referenced by key in the props.
// example theme
const theme = {
// ...
colors: {
primary: '#07c',
muted: '#f6f6f9',
},
}
<div color="primary" bg="muted" />
Function calls, expressions, and variables are dropped into the css
prop as
computed properties. Consider the following example:
const Box = () => {
const myColor = 'primary'
const myFunction = () => 'muted'
const boolean = true
const size = 'small'
return <div color={myColor} bg={myFunction()} mt={boolean ? 'large' : size} />
}
// transpiles to something like:
const Box = () => {
const myColor = 'primary'
const myFunction = () => 'muted'
const boolean = true
const size = 'small'
return (
<div
css={theme => ({
color: theme.colors[myColor], // theme.colors.primary
backgroundColor: theme.colors[myFunction()], // theme.colors.muted
marginTop: theme.space[boolean ? 'large' : size], // theme.space.large || theme.space.small
})}
/>
)
}
You can use arrays to specify responsive styles.
<div width={['100%', '50%', '25%']} />
Opt out of setting a value for a breakpoint by using null
.
<div width={[null, '50%', null, '25%']} />
Responsive arrays will generate styles according to the breakpoints defined in
the mediaQueries
key in your theme
.
If you are using a variable in a style prop's responsive array, it cannot be an array.
const myValue = '1rem'
const myArray = ['1rem', '2rem', '3rem']
// This works:
<div m={[myValue, '2rem', '3rem']} />
// This does not:
<div m={myArray} />
If you need to dynamically style a responsive array, please see Use styleScale props.
When a style prop has keys that are defined in a <ThemeProvider>
, you can
negate them by prefixing them with a '-' (hyphen).
const theme = {
// ...
space: [
0,
'5rem'
]
}
// theme alias
theme.space.large = theme.space[1]
<div mt="-large" mr={-1} />
// transpiles to something like:
<div
css={theme => ({
marginTop: '-' + theme.space.large,
marginRight: '-' + theme.space[1]
})}
/>
// resulting in:
<div css={theme => ({ marginTop: '-5rem', marginRight: '-5rem' })} />
Due to the nature of static compilation, using a negative theme key in a variable or a return value of a function will not result in the negation of a theme value.
// This will NOT work.
const Box = ({ isNegative }) => {
const mySpace = isNegative ? '-large' : 'large'
return <div mx={mySpace}>
}
Every style prop has a Hover
, Focus
, and Active
modifier that is
available. For example, if you want to apply a style to opacity
when an
element is being hovered, use the opacityHover
prop.
// I will be 50% opacity on mouse hover!
<div opacity={1} opacityHover={0.5} />
Custom variants and style props can be defined in the base babel plugin options
under variants
. See below for an example config
// babel.config.js
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-react'],
plugins: [
[
'babel-plugin-style-props',
{
variants: {
boxStyle: 'boxStyles',
},
},
],
'babel-plugin-style-props-emotion',
],
}
The above config will tell the base babel-plugin-style-props
to transpile the
boxStyle
prop on any JSX element to properties in the css
prop.
const theme = {
// ...
boxStyles: {
primary: {
color: 'white',
backgroundColor: '#f0f'
}
}
}
// `boxStyle` on an element:
<div boxStyle="primary" />
// will transpile to something like:
<div css={theme => ({ ...theme.boxStyles.primary })} />
// which results in:
<div css={theme => ({ color: 'white', backgroundColor: '#f0f' })} />
Use scale
variants for any themeable style prop. scale
style props allow you
to specify a set of responsive values for a style prop in a single key, or a via
an array of keys and/or values.
This is useful for styles that usually change at every breakpoint such as font sizes or space values, or when you need to dynamically assign breakpoint values since normal style props cannot accept dynamic arrays.
See below for an example:
<div mScale="xl" />
// transpiles to something like
<div
css={theme => ({
margin: theme.spaceScales.xl[0],
"@media (min-width: 40em)": {
margin: theme.spaceScales.xl[1]
},
"@media (min-width: 52em)": {
margin: theme.spaceScales.xl[2]
},
"@media (min-width: 64em)": {
margin: theme.spaceScales.xl[3]
}
})}
/>
Like with normal style props, scale
props can be overridden per breakpoint
using an array, be negated with a -
, and can use null
to skip over
breakpoints.
<div mScale={['xl', null, '-l']} />
// transpiles to something like
<div
css={theme => ({
margin: theme.spaceScales.xl[0],
"@media (min-width: 40em)": {
margin: theme.spaceScales.xl[1]
},
"@media (min-width: 52em)": {
margin: theme.spaceScales.xl[2]
},
"@media (min-width: 64em)": {
margin: "-" + theme.spaceScales.l[3]
}
})}
/>
Note how the xl
scale still persists through the second and third breakpoint.
Using scales, we can persist a scale for as long as we need it, then override it
when necessary!
Any variable passed to a styleScale
prop must be an array (or function
returning an array). This array also currently cannot contain null
to skip
over breakpoints. If you need to skip a breakpoint, just pass the same key again
in the responsive array.
Consider this example:
// This works:
const myScale = ['xl', 'l', 'l', 'xl']
<div mScale={myScale} />
// This does not work:
const myBadScale = ['xl', 'l', null, 'xl']
<div mScale={myBadScale} />
Any dynamic array passed to a styleScale
prop has access to the non-scaled
theme
equivalent. This means that if you are passing a dynamic array to the
colorScale
prop, it will first check if that colorScales
property exists,
fallback and check normal colors
, then finally use the raw value if neither
would work.
Consider this example:
const theme = {
// ...
colors: {
primary: 'red'
}
colorScales: {
secondary: ['blue', 'green', 'black', 'white']
}
}
const colors = ['primary', 'secondary', 'secondary', '#fff']
<div colorScale={colors} />
// results in something like
<div
css={theme => ({
color: theme.colors.primary,
"@media (min-width: 40em)": {
color: theme.colorsScales.secondary[1]
},
"@media (min-width: 52em)": {
color: theme.colorsScales.secondary[2]
},
"@media (min-width: 64em)": {
color: '#fff'
}
})}
/>
Scales follow the same theme specification as detailed above, except each theme
key has Scales
appended to it. For example, to define the scales for font
sizes, it would exist in your theme as fontSizesScales
. The associated prop
would be fontSizeScale
.
const theme = {
fontSizesScales: {
l: ['1rem', '1.15rem', '1.35rem', '1.5rem']
}
}
<p fontSizeScale="l" />
If you would like this babel plugin to strip all style-props from your resulting
JSX and HTML, specify shouldStrip
in your plugin options.
// babel.config.js
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-react'],
plugins: [
[
'babel-plugin-style-props',
{
shouldStrip: true,
},
],
[
'babel-plugin-style-props-emotion',
{
shouldStrip: true,
},
],
],
}
To achieve a similar API to styled-system
/theme-ui
without the performance
cost, this plugin makes some opinionated decisions as to how you can structure
your theme.
Currently, this plugin only supports up to 5 breakpoints from your theme
.
The ability to specify the amount of breakpoints and mediaqueries will come in a
future release.
This plugin only supports two levels of nesting in a theme
object.
Consider the following example.
// theme.js
const theme = {
colors: {
primary: '#fff',
red: {
light: '#f0f',
dark: '#0f0',
},
},
lineHeights: {
copy: 1.5,
},
}
<div color="red.light" bg="primary" />
The above example will not work because we are accessing a third level of
nesting for our color
style prop. This is largely how this plugin eliminates
the styled-system
/theme-ui
runtime cost.
If you want to have namespaced-like behavior, consider flatly namespacing your keys as a workaround.
const theme = {
colors: {
primary: '#fff',
'red.light': '#f0f',
'red.dark': '#0f0',
},
lineHeights: {
copy: 1.5,
},
}
defaultProps
This plugin does not support specifying React's defaultProps
for style props.
defaultProps
get injected into components at runtime, and therefore cannot be
transpiled at buildtime.
If you are composing reusable components with defaults using this plugin, it's recommended to just set your defaults directly in conjunction with prop spreading.
// Grid.js
const Grid = ({ children, ...props }) => {
return (
<div display="grid" {...props}>
{children}
</div>
)
}
const Example = () => {
return (
<Grid gridTemplateColumns="1fr 1fr" gridColumnGap="1rem">
<div justifySelf="end">Default</div>
<div alignSelf="start">Props!</div>
</Grid>
)
}
-
(hypen)This plugin relies on the hyphen preceeding a theme key to determine the negation of a scale.
css
props.This plugin is currently incompatible with existing css
props on components.
In a future release, it will handle statically merging your prop-based styles
with the one's defined in the css
prop.
MIT.
FAQs
The adapter to utilize style-props with the Emotion CSS-in-JS library.
The npm package babel-plugin-style-props-emotion receives a total of 0 weekly downloads. As such, babel-plugin-style-props-emotion popularity was classified as not popular.
We found that babel-plugin-style-props-emotion demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer 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.
Research
/Security News
Socket researchers uncover how threat actors weaponize Discord across the npm, PyPI, and RubyGems ecosystems to exfiltrate sensitive data.
Security News
Socket now integrates with Bun 1.3’s Security Scanner API to block risky packages at install time and enforce your organization’s policies in local dev and CI.
Research
The Socket Threat Research Team is tracking weekly intrusions into the npm registry that follow a repeatable adversarial playbook used by North Korean state-sponsored actors.