Installation
Requirements
- React 16.14 or newer — the automatic JSX runtime (
react/jsx-runtime) landed in 16.14 @emotion/react11.x@emotion/css11.x
Install
pnpm add emotion-variants @emotion/react @emotion/cssnpm install emotion-variants @emotion/react @emotion/cssyarn add emotion-variants @emotion/react @emotion/cssBoth Emotion packages are peer dependencies and must be installed alongside emotion-variants. @emotion/react serializes your styles for the css prop; @emotion/css backs className() and classNames. @emotion/css is imported unconditionally, so it is required even if you only ever use the css prop.
Enable the css prop
emotion-variants returns values you pass to Emotion's css prop. Make sure your project is set up to use it. The simplest setup points the automatic JSX runtime at Emotion:
// tsconfig.json
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "@emotion/react"
}
}Both options are required. jsxImportSource has no effect under "jsx": "react" — that is the classic transform, which calls React.createElement and never consults an import source.
Or per file, for a project that cannot switch globally:
/** @jsxImportSource @emotion/react */The pragma needs the automatic runtime too, so it must be the first thing in the file and the file must be compiled with react-jsx. On React older than 16.14, use Emotion's Babel plugin with the classic transform instead.
See Emotion's installation guide for other setups (Next.js, Vite, etc.).
Verify
Create a tiny component and render it. If TypeScript autocompletes size inside button({ ... }), you're good to go.
import { ev } from 'emotion-variants';
const button = ev({
base: {
padding: '8px 16px',
},
variants: {
size: {
sm: {
fontSize: 12,
},
lg: {
fontSize: 16,
},
},
},
});
type ButtonProps = NonNullable<Parameters<typeof button>[0]> & {
children: React.ReactNode;
};
export function Button({ size, children }: ButtonProps) {
return <button css={button({ size })}>{children}</button>;
}Next: Getting Started.