bakeware
v0.2.0
Published
Utility library handling the basic ingredients of styling, built to work alongside vanilla-extract
Maintainers
Readme
bakeware

- Utility functions for vanilla-extract
- TypeScript-ready, with built-in type definitions
- Simplifies working with @layer
- Supports type scale and vertical rhythm out of the box
- normalize helper suited for 2026 usage
- Access custom property values from themes
- Manage breakpoints with ease
Installation
npm install bakewarespacing(...values, options?)
Generates a space-separated string of values, following CSS conventions.
||Description|Default|
|---|---|---|
|values|A list of numbers or strings.|—|
|options.baseValue|Base value used to calculate the spacing units.|1rem|
|options.ratio|A ratio of the base value used as a spacing unit.|1/4|
|options.separator|Character used to separate the fragments—" " or ",".|" "|
import { spacing } from "bakeware";
spacing(1, 2);
// "0.25rem 0.5rem"
spacing(1, 2, { ratio: 2 });
// "0.5rem 1rem"
spacing(1, 2, { baseValue: "16px" });
// "4px 8px"
// Comma-separated declarations
`translate3d(${spacing(1, 2, 3, { separator: "," })})`;
// "translate3d(0.25rem,0.5rem,0.75rem)"verticalRhythm(signature, options?)
Creates a vertical rhythm system based on a given signature.
||Description|Default|
|---|---|---|
|signature|An object { lineHeight, spacingRatio } or a string in the format "${number}/${number}".|—|
|options.typeScale|typeScale configuration—when set, the returned object includes a fontSize method.|undefined|
|options.whitespaceRatio|Minimum whitespace between the line height and the actual text, expressed as a ratio between 0 and 1.|0|
import { verticalRhythm } from "bakeware";
const { spacing } = verticalRhythm({ lineHeight: 1.5, spacingRatio: 1/4 });
spacing(1, 2);
// "0.375rem 0.75rem"import { verticalRhythm } from "bakeware";
const { spacing } = verticalRhythm("4/6");
spacing(1, 2);
// "0.375rem 0.75rem"import { verticalRhythm } from "bakeware";
const { fontSize, spacing } = verticalRhythm("2/3", {
typeScale: "geometrical.goldenRatio",
whitespaceRatio: 0.2,
});
spacing(1, 2);
// "0.75rem 1.5rem"
fontSize(0);
// { fontSize: "1rem", lineHeight: "1.5rem" }
fontSize(1);
// { fontSize: "1.618033988749895rem", lineHeight: "3rem" }
fontSize(2);
// { fontSize: "2.618033988749895rem", lineHeight: "4.5rem" }typeScale(scale, unit?)
Generates a type scale based on mathematical or geometric formulas.
||Description|Default|
|---|---|---|
|scale|A string path (e.g., "natural.majorSecond") or a number representing the ratio.|—|
|unit|The CSS unit to use for the resulting font size.|"rem"|
import { typeScale } from "bakeware";
const { fontSize } = typeScale("natural.majorSecond");
fontSize(0);
// "1rem"
fontSize(1);
// "1.125rem"
fontSize(2);
// "1.265625rem"normalize(layer?)
CSS normalization based on Normalize.css and recent discussions across the web. It focuses on minimal impact, resetting only the styles strictly necessary while adding a few convenience styles from modern CSS specs.
||Description|Default|
|---|---|---|
|layer|Optional CSS layer name to wrap the normalization rules.|undefined|
import { layer } from "@vanilla-extract/css";
import { normalize } from "bakeware";
const layoutLayer = layer("layout");
normalize(layoutLayer);alpha(color, value)
Adjusts the opacity of a color, with support for var declarations generated by createTheme.
||Description|Default|
|---|---|---|
|color|The color string to modify.|—|
|value|A number between 0 and 1.|—|
transition(...properties, options?)
Makes implementing CSS transitions easy.
||Description|Default|
|---|---|---|
|properties|CSS property names.|—|
|options.behavior|—|"normal"|
|options.delay|—|undefined|
|options.duration|—|"0s"|
|options.timingFunction|—|"ease"|
import { style } from "@vanilla-extract/css";
import { transition } from "bakeware";
const example = style({
transition: transition("opacity", "transform", {
duration: 200,
}).toString(),
});
// .example {
// transition: opacity 200ms,transform 200ms;
// }transition(...).add(...properties, options?)
Adds declarations to the output using different options—see transition above for the available arguments.
import { transition } from "bakeware";
transition("opacity", { duration: "100ms" })
.add("height", { delay: 200, duration: "1s", timingFunction: "linear" })
.add("display", { behavior: "allow-discrete", duration: 500 })
.toString();
// "opacity 100ms,height 200ms linear 1s,display 500ms allow-discrete"transition(...).toString()
Returns the CSS transition string.
import { transition } from "bakeware";
transition("opacity").toString()
// "opacity 0s"createTransition(options?)
Generates a transition function with its own default options—see transition above for the available options.
import { createTransition, transition } from "bakeware";
const customTransition = createTransition({ duration: 200 });
transition("opacity").toString();
// "opacity 0s"
customTransition("opacity").toString();
// "opacity 200ms"animation(name, options?)
Makes implementing CSS animations easy.
||Description|Default|
|---|---|---|
|name|Animation name.|—|
|options.delay|—|undefined|
|options.direction|—|"normal"|
|options.duration|—|"0s"|
|options.fillMode|—|undefined|
|options.iterationCount|—|"1"|
|options.playState|—|"running"|
|options.timeline|—|"auto"|
|options.timingFunction|—|"ease"|
import { keyframes } from "@vanilla-extract/css";
import { style } from "@vanilla-extract/css";
import { animation } from "bakeware";
const fade = keyframes({
from: {
opacity: 0,
},
to: {
opacity: 1,
},
});
const example = style({
animation: animation(fade, {
duration: 200,
}).toString(),
});
// .example {
// animation: 200ms fade;
// }animation(...).add(...properties, options?)
Adds declarations to the output using different options—see animation above for the available arguments.
import { animation } from "bakeware";
animation("blur", { duration: "100ms" })
.add("slideOut", { delay: 200, duration: "1s", timingFunction: "linear" })
.add("blink", { duration: 500, playState: "paused" })
.toString();
// "100ms blur,200ms linear 1s slideOut,500ms paused blink"animation(...).toString()
Returns the CSS animation string.
import { animation } from "bakeware";
animation("blur").toString()
// "0s blur"createAnimation(options?)
Generates an animation function with its own default options—see animation above for the available options.
import { animation, createAnimation } from "bakeware";
const customAnimation = createAnimation({ duration: 200 });
animation("blur").toString();
// "0s blur"
customAnimation("blur").toString();
// "200ms blur"fontFace(rule, debugId?)
Extends vanilla-extract's fontFace, making the src definition cleaner. Fully compatible with the original function.
||Description|Default|
|---|---|---|
|rule|—|—|
|debugId|—|—|
import { fontFace } from "bakeware";
fontFace({
src: {
local: "Helvetica",
opentype: { tech: "variations", url: "./helvetica.otf" },
truetype: "./helvetica.ttf",
woff2: { url: "./helvetica.woff2" },
},
});
// local("Helvetica"),url("./helvetica.otf") format(opentype) tech("variations"),url("./helvetica.ttf") format(truetype),url("./helvetica.woff2") format(woff2)
// Can also be used with an array of strings
fontFace([
{
src: [
'local("Helvetica")',
'url("./helvetica.otf") format(opentype) tech("variations")',
'url("./helvetica.ttf") format(truetype)',
'url("./helvetica.woff2") format(woff2)',
],
},
]);
// Can also be used like vanilla-extract original function
fontFace([
{
src: 'local("Helvetica"), url("./helvetica.otf") format(opentype) tech("variations"), url("./helvetica.ttf") format(truetype), url("./helvetica.woff2") format(woff2)',
},
]);breakpoints(value)
||Description|Default|
|---|---|---|
|value|—|—|
Generates a set of media query strings for a given collection of breakpoints.
import { style } from "@vanilla-extract/css";
import { breakpoints } from "bakeware";
const breakpoint = breakpoints({
sm: "600px",
md: "900px",
lg: "1200px",
});
// {
// sm: "(min-width: 600px)",
// md: "(min-width: 900px)",
// lg: "(min-width: 1200px)",
// not: {
// sm: "not all and (min-width: 600px)",
// md: "not all and (min-width: 900px)",
// lg: "not all and (min-width: 1200px)",
// },
// }
style({
"@media": {
// >= 900px
[breakpoint.md]: {
display: "flex",
},
// < 900px
[breakpoint.not.md]: {
padding: "1rem",
},
},
});
// @media (min-width: 900px) {
// display: flex;
// }
//
// @media not all and (min-width: 900px) {
// padding: 1rem;
// }
// It accepts min, max and mediaType
breakpoints({
mobile: { min: "240px", max: "479px" },
tablet: { min: "480px", max: "1023px" },
desktop: { min: "1024px" },
print: { mediaType: "print" },
});
// {
// mobile: "(min-width: 240px) and (max-width: 479px)",
// tablet: "(min-width: 480px) and (max-width: 1023px)",
// desktop: "(min-width: 1024px)",
// print: "print",
// not: {
// mobile: "not all and (min-width: 240px) and (max-width: 479px)",
// tablet: "not all and (min-width: 480px) and (max-width: 1023px)",
// desktop: "not all and (min-width: 1024px)",
// print: "not print"
// }
// }createTheme(themeContract?, tokens, debugId?)
Extends vanilla-extract's createTheme, exposing the vars values. Fully compatible with the original implementation.
||Description|Default|
|---|---|---|
|themeContract|—|—|
|tokens|—|—|
|debugId|—|—|
createTheme.var(declaration)
Used to access the value of a custom property generated by createTheme.
||Description|Default|
|---|---|---|
|declaration|The value returned by createTheme.|—|
import { createTheme } from "bakeware";
const [_, vars] = createTheme({
example: "#000",
});
// {
// example: "var(--example_xxxxxxx)",
// }
createTheme.var(vars.example);
// "#000"globalStyles(rules)
Sets global styles for multiple selectors. The rules object accepts the same selector-based global styles as vanilla-extract, with optional top-level named layers.
||Description|Default|
|---|---|---|
|rules|Object containing selectors and optional named layers.|—|
import { globalStyles } from "bakeware";
globalStyles({
"*": {
boxSizing: "border-box",
},
svg: {
display: "inline-block",
},
});Top-level @layer groups selectors under named CSS layers:
globalStyles({
"@layer": {
reset: {
"*": {
boxSizing: "border-box",
},
html: {
blockSize: "100%",
},
},
components: {
button: {
cursor: "pointer",
},
},
},
});
// @layer reset {
// * { box-sizing: border-box; }
// html { block-size: 100%; }
// }
//
// @layer components {
// button { cursor: pointer; }
// }Selector-level @layer rules continue to use vanilla-extract's existing syntax:
globalStyles({
body: {
"@layer": {
base: {
margin: 0,
},
},
},
});License
Copyright (C) 2026-present stldo
