@deepdish/stylesheet
v0.5.0
Published
CSS-in-TS style sheet
Keywords
Readme
@deepdish/stylesheet
A bare-bones CSS-in-TS solution that gives full control over the resultant CSS string. This package was developed in order to easily add CSS to shadow DOM elements.
API
Initializing a Stylesheet
A Stylesheet is a simple class that collects CSS rules. The makeStyleSheet function accepts a name, which is used to prefix generated CSS classes.
import { makeStyleSheet } from "@deepdish/stylesheet";
export const stylesheet = makeStyleSheet("amazing-stylesheet");Creating a style
// the stylesheet we created above
import { stylesheet } from "./stylesheet"
export const button = stylesheet.style({
color: 'red';
// ... other CSS styles (these properties are fully typed)
'pseudos': {
':hover': {
color: 'blue'
// ... pseudo CSS styles (these properties are fully typed as well)
}
}
})The button variable from the above example is a string representing a unique CSS class. The CSS rule generated from stylesheet.style is automatically collected in the Stylesheet's rules. The class selector can be applied like you'd expect:
// a collection of button styles co-located in a separate file
import { button } from "./button-styles";
export function Button({ children }: { children: React.ReactNode }) {
return <button className={button}>{children}</button>;
}Creating an element
You can quickly create a UI primitive using the .element method on a Stylesheet. The method supports Class Variance Authority, which makes it trivial to create UI variants.
import { cva } from "class-variance-authority";
// the stylesheet we created above
import { stylesheet } from "./stylesheet";
import * as styles from "./button-styles";
export const Button = stylesheet.element(
"button",
cva(styles.base, {
variants: {
intent: {
primary: styles.primary,
secondary: styles.secondary,
},
size: {
small: styles.small,
medium: styles.medium,
},
},
defaultVariants: {
intent: "primary",
size: "medium",
},
})
);The Button in the above example accepts all of the normal <button> props in addition to the variants intent and size, e.g.:
// the Button primitive we just created
import { Button } from "./button";
function Demo() {
return (
// these props are fully typed
<Button type="submit" size="medium" intent="secondary">
Secondary Button
</Button>
);
}Generate the CSS
You can generate the CSS by simply invoking the .render() method on a Stylesheet instance:
// the stylesheet we created above
import { stylesheet } from "./stylesheet";
const css = stylesheet.render();Advanced
Nested selectors
You can nest selectors by passing an object to the nested property.
// the stylesheet we created above
import { stylesheet } from "./stylesheet";
export const exampleWithNestedSelectors = stylesheet.style({
color: "red",
fontSize: "16px",
nested: {
".child": {
color: "green",
pseudos: {
":hover": {
color: "blue",
},
},
},
'&[data-test="foo"]': {
// these properties are fully typed
color: "blue",
},
},
});The resulting CSS will be:
.example-with-nested-selectors {
color: red;
font-size: 16px;
.child {
color: green;
&:hover {
color: blue;
}
}
&[data-test="foo"] {
color: blue;
}
}