CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-vanilla-extract--sprinkles

Zero-runtime atomic CSS framework for vanilla-extract that generates static utility classes with type-safe composition

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

Vanilla Extract Sprinkles

Vanilla Extract Sprinkles is a zero-runtime atomic CSS framework that generates static utility classes for vanilla-extract. It enables developers to create type-safe, custom atomic CSS systems by defining properties, conditions (media queries, selectors), and shorthands through a declarative configuration API. All CSS is generated at build time with optional lightweight runtime composition for dynamic styling.

Package Information

  • Package Name: @vanilla-extract/sprinkles
  • Package Type: npm
  • Language: TypeScript
  • Installation:
    • npm: npm install @vanilla-extract/sprinkles
    • yarn: yarn add @vanilla-extract/sprinkles
    • pnpm: pnpm add @vanilla-extract/sprinkles

Core Imports

import { defineProperties, createSprinkles } from "@vanilla-extract/sprinkles";

For utilities:

import { createMapValueFn, createNormalizeValueFn } from "@vanilla-extract/sprinkles";

For runtime usage:

import { createSprinkles } from "@vanilla-extract/sprinkles/createRuntimeSprinkles";

For standalone utilities:

import { createMapValueFn, createNormalizeValueFn } from "@vanilla-extract/sprinkles/createUtils";

Basic Usage

import { defineProperties, createSprinkles } from "@vanilla-extract/sprinkles";

// Define properties with conditions and values
const responsiveProperties = defineProperties({
  conditions: {
    mobile: {},
    tablet: { '@media': 'screen and (min-width: 768px)' },
    desktop: { '@media': 'screen and (min-width: 1024px)' }
  },
  defaultCondition: 'mobile',
  properties: {
    display: ['none', 'flex', 'block', 'inline'],
    flexDirection: ['row', 'column'],
    paddingTop: {
      small: '4px',
      medium: '8px',
      large: '16px'
    }
  },
  shorthands: {
    padding: ['paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight'],
    paddingX: ['paddingLeft', 'paddingRight'],
    paddingY: ['paddingTop', 'paddingBottom']
  }
});

// Create sprinkles function
export const sprinkles = createSprinkles(responsiveProperties);

// Use in .css.ts files (build-time)
export const container = sprinkles({
  display: 'flex',
  paddingX: 'small',
  flexDirection: {
    mobile: 'column',
    desktop: 'row'
  }
});

// Use at runtime
const dynamicClass = sprinkles({
  display: 'flex',
  paddingTop: ['small', 'medium', 'large']
});

Architecture

Vanilla Extract Sprinkles is built around several key concepts:

  • Properties Definition: defineProperties creates atomic CSS class configurations with support for conditions, shorthands, and responsive arrays
  • Sprinkles Function: createSprinkles generates a type-safe function that composes utility classes
  • Build-time Generation: All CSS classes are generated during build via vanilla-extract's file scope
  • Runtime Composition: Optional runtime usage for dynamic class composition with minimal overhead
  • Type Safety: Full TypeScript support with conditional types and property validation
  • Conditions System: Support for media queries, selectors, @supports, and @container queries

Capabilities

Property Definition

Core functionality for defining atomic CSS properties with conditions, shorthands, and responsive configurations. This is the foundation for creating custom utility class systems.

function defineProperties<
  Properties extends AtomicProperties,
  Conditions extends BaseConditions,
  DefaultCondition extends keyof Conditions | Array<keyof Conditions> | false
>(
  options: ConditionalAtomicOptions<Properties, Conditions, DefaultCondition>
): ConditionalAtomicStyles<Properties, Conditions, DefaultCondition>;

Property Definition

Sprinkles Creation

Transform property definitions into type-safe utility functions that generate CSS class names. Supports both build-time and runtime usage patterns.

function createSprinkles<Args extends ReadonlyArray<SprinklesProperties>>(
  ...config: Args
): SprinklesFn<Args>;

type SprinklesFn<Args extends ReadonlyArray<SprinklesProperties>> = ((
  props: SprinkleProps<Args>
) => string) & { properties: Set<keyof SprinkleProps<Args>> };

Sprinkles Creation

Conditional Value Utilities

Helper functions for working with conditional values in responsive and theme-based styling scenarios.

function createMapValueFn<SprinklesProperties extends Conditions<string>>(
  properties: SprinklesProperties
): <OutputValue, Value>(
  value: Value,
  fn: (inputValue: ExtractValue<Value>, key: string) => OutputValue
) => OutputValue | Partial<Record<string, OutputValue>>;

function createNormalizeValueFn<SprinklesProperties extends Conditions<string>>(
  properties: SprinklesProperties
): <Value>(
  value: ConditionalValue<SprinklesProperties, Value>
) => Partial<Record<string, Value>>;

Conditional Value Utilities

Runtime Sprinkles

Lightweight runtime version of sprinkles creation for dynamic styling without build-time constraints.

function createSprinkles<Args extends ReadonlyArray<SprinklesProperties>>(
  ...args: Args
): SprinklesFn<Args>;

Runtime Sprinkles

Types

type ConditionalValue<
  SprinklesProperties extends Conditions<string>,
  Value extends string | number | boolean
> =
  | Value
  | Partial<Record<string, Value>>
  | ResponsiveArrayByMaxLength<number, Value>;

type RequiredConditionalValue<
  SprinklesProperties extends Conditions<string>,
  Value extends string | number | boolean
> = Value | RequiredConditionalObject<string, string, Value> | ResponsiveArray<number, Value>;

interface ResponsiveArray<Length extends number, Value> extends ReadonlyArray<Value> {
  0: Value;
  length: Length;
}

interface SprinklesProperties {
  styles: {
    [property: string]:
      | ConditionalWithResponsiveArrayProperty
      | ConditionalProperty
      | ShorthandProperty
      | UnconditionalProperty;
  };
}

interface ConditionalPropertyValue {
  defaultClass: string | undefined;
  conditions: {
    [conditionName: string]: string;
  };
}

interface ConditionalProperty {
  values: {
    [valueName: string]: ConditionalPropertyValue;
  };
}

interface UnconditionalProperty {
  values: {
    [valueName: string]: {
      defaultClass: string;
    };
  };
}

interface ShorthandProperty {
  mappings: Array<string>;
}

interface ConditionalWithResponsiveArrayProperty {
  responsiveArray: Array<string>;
  values: {
    [valueName: string]: ConditionalPropertyValue;
  };
}

type AtomicProperties = {
  [Property in keyof CSSProperties]?:
    | Record<string, CSSProperties[Property] | Omit<StyleRule, ConditionKey>>
    | ReadonlyArray<CSSProperties[Property]>;
} | Record<string, Record<string | number, Omit<StyleRule, ConditionKey>>>;

type BaseConditions = { [conditionName: string]: Partial<Record<ConditionKey, string>> };

type ConditionKey = '@media' | '@supports' | '@container' | 'selector';

type AtomicCSSProperties = {
  [Property in keyof CSSProperties]?:
    | Record<string, CSSProperties[Property] | Omit<StyleRule, ConditionKey>>
    | ReadonlyArray<CSSProperties[Property]>;
};

type AtomicCustomProperties = Record<
  string,
  Record<string | number, Omit<StyleRule, ConditionKey>>
>;

type ResponsiveArrayByMaxLength<MaxLength extends number, Value> = 
  MaxLength extends 1 ? ResponsiveArray<1, Value | null> :
  MaxLength extends 2 ? ResponsiveArray<1 | 2, Value | null> :
  MaxLength extends 3 ? ResponsiveArray<1 | 2 | 3, Value | null> :
  MaxLength extends 4 ? ResponsiveArray<1 | 2 | 3 | 4, Value | null> :
  MaxLength extends 5 ? ResponsiveArray<1 | 2 | 3 | 4 | 5, Value | null> :
  MaxLength extends 6 ? ResponsiveArray<1 | 2 | 3 | 4 | 5 | 6, Value | null> :
  MaxLength extends 7 ? ResponsiveArray<1 | 2 | 3 | 4 | 5 | 6 | 7, Value | null> :
  MaxLength extends 8 ? ResponsiveArray<1 | 2 | 3 | 4 | 5 | 6 | 7 | 8, Value | null> :
  never;

type ResponsiveArrayConfig<Value> = ResponsiveArray<2 | 3 | 4 | 5 | 6 | 7 | 8, Value>;

type ConditionalAtomicOptions<
  Properties extends AtomicProperties,
  Conditions extends BaseConditions,
  DefaultCondition extends keyof Conditions | Array<keyof Conditions> | false
> = {
  '@layer'?: string;
  properties: Properties;
  conditions: Conditions;
  defaultCondition: DefaultCondition;
};

type UnconditionalAtomicOptions<Properties extends AtomicProperties> = {
  '@layer'?: string;
  properties: Properties;
};

type ShorthandOptions<
  Properties extends AtomicProperties,
  Shorthands extends { [shorthandName: string]: Array<keyof Properties> }
> = {
  shorthands: Shorthands;
};

type ResponsiveArrayOptions<
  Conditions extends BaseConditions,
  ResponsiveLength extends number
> = {
  responsiveArray: ResponsiveArrayConfig<keyof Conditions> & {
    length: ResponsiveLength;
  };
};

Deprecated Exports

The following exports are deprecated but still available for backward compatibility:

Main Entry (@vanilla-extract/sprinkles)

/**
 * @deprecated Use `defineProperties` instead
 */
const createAtomicStyles = defineProperties;

/**
 * @deprecated Use `createSprinkles` instead  
 */
const createAtomsFn = createSprinkles;

Runtime Entry (@vanilla-extract/sprinkles/createRuntimeSprinkles)

/**
 * @deprecated Use `createSprinkles` instead  
 */
const createAtomsFn = createSprinkles;

Migration Guide

From createAtomicStyles to defineProperties:

// Old (deprecated)
import { createAtomicStyles } from "@vanilla-extract/sprinkles";
const styles = createAtomicStyles({ /* config */ });

// New (recommended)
import { defineProperties } from "@vanilla-extract/sprinkles";
const styles = defineProperties({ /* config */ });

From createAtomsFn to createSprinkles:

// Old (deprecated) - Build-time
import { createAtomsFn } from "@vanilla-extract/sprinkles";
const atoms = createAtomsFn(properties);

// New (recommended) - Build-time
import { createSprinkles } from "@vanilla-extract/sprinkles";
const sprinkles = createSprinkles(properties);

// Old (deprecated) - Runtime
import { createAtomsFn } from "@vanilla-extract/sprinkles/createRuntimeSprinkles";
const atoms = createAtomsFn(properties);

// New (recommended) - Runtime
import { createSprinkles } from "@vanilla-extract/sprinkles/createRuntimeSprinkles";
const sprinkles = createSprinkles(properties);
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@vanilla-extract/sprinkles@1.6.x
Publish Source
CLI
Badge
tessl/npm-vanilla-extract--sprinkles badge