Skip to content
stldoPublic

About

Utility library handling the basic ingredients of styling, built to work alongside vanilla-extract

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

bakeware License Build status npm

  • Utility functions for vanilla-extract
  • TypeScript-ready, with built-in type definitions
  • 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 bakeware

spacing(...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

The MIT License

Copyright (C) 2026-present stldo

About

Utility library handling the basic ingredients of styling, built to work alongside vanilla-extract

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages