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
Overview
Eval results
Files

property-definition.mddocs/

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.

Capabilities

defineProperties

Defines a collection of utility classes with properties, conditions and shorthands. Supports multiple overloads for different configuration combinations.

/**
 * Define properties with conditions, shorthands, and responsive arrays
 */
function defineProperties<
  Properties extends AtomicProperties,
  ResponsiveLength extends number,
  Conditions extends BaseConditions,
  Shorthands extends { [shorthandName: string]: Array<keyof Properties> },
  DefaultCondition extends keyof Conditions | Array<keyof Conditions> | false
>(
  options: ConditionalAtomicOptions<Properties, Conditions, DefaultCondition> &
    ShorthandOptions<Properties, Shorthands> &
    ResponsiveArrayOptions<Conditions, ResponsiveLength>
): ConditionalWithResponsiveArrayAtomicStyles<
  Properties,
  Conditions,
  ResponsiveLength,
  DefaultCondition
> & ShorthandAtomicStyles<Shorthands>;

/**
 * Define properties with conditions and shorthands
 */
function defineProperties<
  Properties extends AtomicProperties,
  Conditions extends BaseConditions,
  Shorthands extends { [shorthandName: string]: Array<keyof Properties> },
  DefaultCondition extends keyof Conditions | Array<keyof Conditions> | false
>(
  options: ConditionalAtomicOptions<Properties, Conditions, DefaultCondition> &
    ShorthandOptions<Properties, Shorthands>
): ConditionalAtomicStyles<Properties, Conditions, DefaultCondition> &
  ShorthandAtomicStyles<Shorthands>;

/**
 * Define properties with conditions and responsive arrays
 */
function defineProperties<
  Properties extends AtomicProperties,
  Conditions extends BaseConditions,
  ResponsiveLength extends number,
  DefaultCondition extends keyof Conditions | Array<keyof Conditions> | false
>(
  options: ConditionalAtomicOptions<Properties, Conditions, DefaultCondition> &
    ResponsiveArrayOptions<Conditions, ResponsiveLength>
): ConditionalWithResponsiveArrayAtomicStyles<
  Properties,
  Conditions,
  ResponsiveLength,
  DefaultCondition
>;

/**
 * Define properties with conditions only
 */
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>;

/**
 * Define unconditional properties with shorthands
 */
function defineProperties<
  Properties extends AtomicProperties,
  Shorthands extends { [shorthandName: string]: Array<keyof Properties> }
>(
  options: UnconditionalAtomicOptions<Properties> &
    ShorthandOptions<Properties, Shorthands>
): UnconditionalAtomicStyles<Properties> & ShorthandAtomicStyles<Shorthands>;

/**
 * Define unconditional properties only
 */
function defineProperties<Properties extends AtomicProperties>(
  options: UnconditionalAtomicOptions<Properties>
): UnconditionalAtomicStyles<Properties>;

Configuration Options

The defineProperties function accepts various configuration options:

Properties

Define which CSS properties and values should be available. Properties can be defined as arrays for simple mappings or objects for semantic mappings.

// Array format for valid CSS values
properties: {
  display: ['none', 'block', 'flex'],
  flexDirection: ['row', 'column']
}

// Object format for semantic mappings
properties: {
  padding: {
    small: '4px',
    medium: '8px',
    large: '16px'
  },
  color: {
    primary: '#007bff',
    secondary: '#6c757d'
  }
}

// Style objects for complex scenarios
properties: {
  background: {
    red: {
      vars: { [alpha]: '1' },
      background: `rgba(255, 0, 0, ${alpha})`
    }
  }
}

Conditions

Define a set of media/feature queries, selectors, or other conditions for the provided properties.

conditions: {
  mobile: {},
  tablet: { '@media': 'screen and (min-width: 768px)' },
  desktop: { '@media': 'screen and (min-width: 1024px)' },
  darkMode: { '@media': '(prefers-color-scheme: dark)' },
  hover: { selector: '&:hover' },
  focus: { selector: '&:focus' },
  supportsGrid: { '@supports': 'display: grid' },
  largeContainer: { '@container': '(min-width: 800px)' }
}

Default Condition

Defines which condition(s) should be used when a non-conditional value is requested.

// Single default condition
defaultCondition: 'mobile'

// Multiple default conditions for mutually exclusive scenarios
defaultCondition: ['lightMode', 'darkMode']

// Force explicit condition usage
defaultCondition: false

Shorthands

Maps custom shorthand properties to multiple underlying CSS properties.

shorthands: {
  padding: ['paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight'],
  paddingX: ['paddingLeft', 'paddingRight'],
  paddingY: ['paddingTop', 'paddingBottom'],
  placeItems: ['justifyContent', 'alignItems']
}

Responsive Arrays

Providing an array of condition names enables responsive array notation by defining the order of conditions.

responsiveArray: ['mobile', 'tablet', 'desktop']

CSS Layers

Optional CSS layer for generated styles. This wraps all generated CSS classes in the specified layer, useful for managing cascade order in complex stylesheets.

// Add all generated styles to the 'utilities' layer
'@layer': 'utilities'

// Example with CSS layer
const layeredProperties = defineProperties({
  '@layer': 'components',
  properties: {
    padding: {
      small: '8px',
      medium: '16px',
      large: '24px'
    },
    margin: {
      none: '0',
      auto: 'auto'
    }
  }
});

// Generated CSS will be wrapped in @layer components { ... }

CSS Output:

@layer components {
  .padding_small_mobile {
    padding: 8px;
  }
  
  .margin_auto_mobile {
    margin: auto;
  }
}

Usage Examples

Basic responsive properties:

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

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'],
    flexDirection: ['row', 'column'],
    paddingTop: {
      small: '10px',
      medium: '20px',
      large: '30px'
    }
  }
});

Color properties with theme conditions:

const colorProperties = defineProperties({
  conditions: {
    lightMode: {},
    darkMode: { '@media': '(prefers-color-scheme: dark)' }
  },
  defaultCondition: 'lightMode',
  properties: {
    color: {
      primary: '#007bff',
      secondary: '#6c757d'
    },
    background: {
      surface: '#ffffff',
      elevated: '#f8f9fa'
    }
  }
});

Properties with shorthands and responsive arrays:

const spacingProperties = defineProperties({
  conditions: {
    mobile: {},
    tablet: { '@media': 'screen and (min-width: 768px)' },
    desktop: { '@media': 'screen and (min-width: 1024px)' }
  },
  defaultCondition: 'mobile',
  responsiveArray: ['mobile', 'tablet', 'desktop'],
  properties: {
    paddingTop: { small: '4px', medium: '8px', large: '16px' },
    paddingBottom: { small: '4px', medium: '8px', large: '16px' },
    paddingLeft: { small: '4px', medium: '8px', large: '16px' },
    paddingRight: { small: '4px', medium: '8px', large: '16px' }
  },
  shorthands: {
    padding: ['paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight'],
    paddingX: ['paddingLeft', 'paddingRight'],
    paddingY: ['paddingTop', 'paddingBottom']
  }
});

Unconditional properties:

const unconditionalProperties = defineProperties({
  properties: {
    fontFamily: {
      heading: 'Georgia, serif',
      body: 'Arial, sans-serif',
      mono: 'Consolas, monospace'
    },
    borderRadius: {
      small: '2px',
      medium: '4px',
      large: '8px'
    }
  }
});

CSS layer integration:

const layeredUtilities = defineProperties({
  '@layer': 'utilities',
  conditions: {
    mobile: {},
    tablet: { '@media': 'screen and (min-width: 768px)' },
    desktop: { '@media': 'screen and (min-width: 1024px)' }
  },
  defaultCondition: 'mobile',
  properties: {
    display: ['none', 'block', 'flex'],
    position: ['static', 'relative', 'absolute', 'fixed'],
    zIndex: {
      hide: -1,
      base: 0,
      elevated: 10,
      modal: 100
    }
  },
  shorthands: {
    hide: ['display'],
    show: ['display']
  }
});

// Generated CSS will be organized in the utilities layer
// @layer utilities {
//   .display_none_mobile { display: none; }
//   .zIndex_modal_mobile { z-index: 100; }
//   /* etc... */
// }

Install with Tessl CLI

npx tessl i tessl/npm-vanilla-extract--sprinkles

docs

conditional-value-utilities.md

index.md

property-definition.md

runtime-sprinkles.md

sprinkles-creation.md

tile.json