$ yarn add jss-emotion
#OR
$ npm install --save jss-emotion
Usage
./MyComponent.tsx
import { createUseClassNames } from "./useClassNames";
const { useClassNames } = createUseClassNames<Props & { color: "red" | "blue" }>()({
(theme, { color })=> ({
"root": {
color,
"&:hover": {
"backgroundColor": "lightGrey"
}
}
})
});
function MyComponent(props: Props){
const [ color, setColor ]= useState<"red" | "blue">("red");
const { classNames }=useClassNames({...props, color });
return <span className={classNames.root}>hello world</span>;
}
./useClassNames.ts
import { createUseClassNamesFactory } from "jss-emotion";
const theme = {
"primaryColor": "blue";
};
function useTheme(){
return theme;
}
export const { createUseClassNames } = createUseClassNamesFactory({ useTheme });
Why this instead of JSS?
Consider this example use of JSS:
//JSS in bundled in @material-ui
import { makeStyles, createStyles } from "@material-ui/core/styles";
type Props = {
color: "red" | "blue";
};
const useStyles = makeStyles(
theme => createStyles<"root" | "label">, Props>({
"root": {
"backgroundColor": theme.palette.primary.main
},
"label": ({ color })=>({
color
})
})
);
function MyComponent(props: Props){
const classes = useStyles(props);
return (
<div className={classes.root}>
<span className={classes.label}>
Hello World
</span>
</div>
);
}
Many pain points:
- Because TypeScript doesn't support partial argument inference,
we have to explicitly enumerate the classes name as an union type
"root" | "label"
. - We shouldn't have to import
createStyles
to get correct typings. - Inconsistent naming conventions
makeStyles -> useStyles -> classes
Let's now compare with jss-emotion
import { createUseClassNames } from "./useClassNames";
type Props = {
color: "red" | "blue";
};
const { useClassNames } = createUseClassNames<Props>()(
(theme, { color })=> ({
"root": {
"backgroundColor": theme.palette.primary.main
},
"label": { color }
})
);
function MyComponent(props: Props){
const { classNames } = useClassNames(props);
return (
<div className={classNames.root}>
<span className={classNames.label}>
Hello World
</span>
</div>
);
}
Benefits:
- Less verbose, same type safety.
- Consistent naming convention
createUseClassNames -> useClassNames -> classNames
. - You don't need to remember how things are supposed to be named, just let intellisense guide you.
Besides, JSS
, at least the version bundled into material-ui
, have other problems:
Why not Styled component ?
See this issue
API Reference
This module exports:
createUseClassNamesFactory()
-
css
: Reexport ofimport { css } from "@emotion/css"
-
keyframes
:Reexport ofimport { keyframes } from "@emotion/css"
-
cx
: Reexport ofimport { cx } from "@emotion/css"
-
injectGlobal
: Reexport ofimport { injectGlobal } from "@emotion/injectGlobal"