npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@digitak/fashion

v0.9.10

Published

**Fashion** is an extension to the [vanilla-extract](https://vanilla-extract.style/) library that makes use of Typescript as a style preprocessor (eg. use Typescript instead of Sass, Less, Postcss, etc...).

Downloads

32

Readme

Fashion is an extension to the vanilla-extract library that makes use of Typescript as a style preprocessor (eg. use Typescript instead of Sass, Less, Postcss, etc...).

By using Typescript as a style preprocessor you gain the major benefit to share data between your Css and your Javascript application. Communicating values between Css and Javascript has always been complicated and hacky. Now you have only one source of truth.

It also has the advantage of bringing the power of Typescript as your preprocessor. Loops, objects, arrays, mappings, etc... everything becomes possible.

But while vanilla-extract had this brightest idea, its api lacked some crucial capacities. That is where Fashion comes to the rescue. Fashion comes with all the power of vanilla-extract, plus:

  • it makes possible to apply runtime style with the same syntax as static style (vanilla-extract has no mechanisms for runtime styling except by manipulating css variables),
  • simplify the api that was too low-level with too many differents paradigms (use variants like stitches as the default paradigm),
  • exposes utilities to easily and safely define your design system,
  • Fashion works with its own style object that differs from CSSType (used by vanilla-extract) by adding several features:
    • possibility to indicate default unit for sizes (px is default but can be rem),
    • possibility to indicate a default zoom level that will apply to every every space,
    • properties that start with the same name are grouped into an object. Ex: { fontSize, fontWeight, fontFamily } becomes { font: { size, weight, family }}. It's cleaner make it possible to work directly with Font or Background objects for example.

Setup

First, you have to install fashion as well as its peer dependencies:

npm install @digitak/fashion @vanilla-extract/css @vanilla-extract/recipes

And then the right vanilla-extract plugin that will preprocess your .css.ts files into standard .css files. The right plugin depends on your bundler (vite, esbuild, webpack, Next.js, etc...).

Follow the plugin installation instructions and you should be all set.

Static styling

Static styling has the best performances you can imagine. No css-in-js library could ever overperform static styling. Your .css.ts will be preprocessed at build time and transformed into plain css.

Basic usage

  1. Create a .css.ts file that will hold some style:
// styled.css.ts
import { style } from "@digitak/fashion"

export const styled = style({
  background: 'red',
  color: 'white',
})
  1. Import your style and apply it to a component:
import { styled } from "./styled.css"

export const Button = <button className={styled()}>
  I am a styled button
</button>

Variants

Heavily inspired by stitches, the variants system allows to define variations of a given style.

// styled.css.ts
import { style } from "@digitak/fashion"

export const styled = style({
  background: "transparent",
  color: "black",
  
  variants: {
    color: {
      blue: {
        background: "blue",
        color: "white",
      },
      red: {
        background: "red",
        color: "white",
      },
    },

    rounded: {
      true: {
        borderRadius: 99999
      }
    }
  }
})
import { styled } from "./styled.css"

export const Button = <button className={styled({ color: 'red', rounded: true })}>
  I am a styled red button
</button>

You can define as many variants as you want.

Flags variants

If you set a true and / or a false field as a variant value, its type will be converted into a boolean.

// styled.css.ts
import { style } from "@digitak/fashion"

export const styled = style({
  background: "transparent",
  color: "black",
  border: {
    width: 1,
  },
  
  variants: {
    rounded: {
      true: {
        borderRadius: 99999
      }
    }
  }
})

Default variants

You can specify default variants.

// styled.css.ts
import { style } from "@digitak/fashion"

export const styled = style({
  background: "transparent",
  color: "black",
  
  variants: {
    color: {
      blue: {
        background: "blue",
        color: "white",
      },
      red: {
        background: "red",
        color: "white",
      },
    },
  },

  defaultVariants: {
    color: "blue",
  }
})

Compound variants

You can also apply additional style when several variants are active together.

// styled.css.ts
import { style } from "@digitak/fashion"

export const styled = style({
  background: "transparent",
  color: "black",
  
  variants: {
    color: {
      blue: {
        background: "blue",
        color: "white",
      },
      red: {
        background: "red",
        color: "white",
      },
    },

    rounded: {
      true: {
        borderRadius: 99999
      }
    }
  },

  compoundVariants: [
    {
      variants: {
        color: "blue",
        rounded: true,
      },
      // apply a small blue shadow when the two variants below are active
      style: {
        boxShadow: {
          spread: 1,
          blur: 1,
          color: "blue",
        }
      },
    },
  ]
})

Global style

You can easily define global style:

// global.css.ts
import { globalStyle } from '@digitak/fashion';

globalStyle('html, body', {
  margin: 0,
})

Dynamic styling

Dynamic styling is great when you have a component with a visual state that can have any values.

import { styleToObject } from "@digitak/fashion/camel"

export const Button = <button style={styleToObject({
  background: "red",
  color: "white",
})}>
  I am a styled button
</button>

Fashion exports functions to transform a style object into:

  • a plain css string (kebab-case): import { styleToString } from "@digitak/fashion/kebab",
  • a plain css object (kebab-case): import { styleToObject } from "@digitak/fashion/kebab",
  • a plain css string (camel-case): import { styleToString } from "@digitak/fashion/camel",
  • a plain css object (camel-case): import { styleToObject } from "@digitak/fashion/camel".

⚠️ You cannot use variants, status (like :hover or :focus), selectors or media queries with dynamic styling.

Define a design system

Defining a strong design system will ensure your project follow strong design guidelines and will be easily configurable in the future.

Define variables and themes

Themes are a set of different objects that must assign values to the same variables.

For defining themes, one must first define which variables his themes rely on. Your Variables type should only contain values that change when you switch theme. We'll see later how to deal with constant values.

// theme.css.ts
import type { Color } from "@digitak/fashion"

// this type can contain any values, not just colors
export type Variables = {
  colors: {
    primary: Color;
    secondary: Color;
  };
};

// we inject our variables to get a function that will define our themes
const { defineThemes } = defineThemeVariables<Variables>();

Once the types of our variables is set, we can create our themes:

// theme.css.ts
// ... variable definitions

export const { themes, variables } = defineThemes({
  light: {
    colors: {
      primary: "#ff55gg",
      secondary: "#gg44dd",
    }
  },
  dark: {
    colors: {
      primary: "#00ee33",
      secondary: "#11dd44",
    }
  }
})

You will now be able to use your reactive theme this way:

// app.css.ts
import { style } from "@digitak/fashion"
import { variables } from "./theme.css"

export const appStyle = style({
  background: variables.colors.primary
})
// app.tsx
import { themes } from "./theme.css"
import { appStyle } from "./app.css"

export const App = ({ children }) => <div className={themes.light} >
  <div className={appStyle()}>
    {children}
  </div>
</div>

Define constant values

Fashion comes with some helper functions to safely define your design system.

An example of full design system would be:

// --- Variables & Themes --- //
export type Variables = {
  colors: {
    primary: Color;
    secondary: Color;
  };
};

const { defineThemes } = defineThemeVariables<Variables>();

export const { themes, variables } = defineThemes({
  light: {
    colors: {
      primary: "#ff55gg",
      secondary: "#gg44dd",
    }
  },
  dark: {
    colors: {
      primary: "#00ee33",
      secondary: "#11dd44",
    }
  }
});


// --- Design system --- //
export const colors = defineColors({
  ...variables.colors,
  // plus any other constant color
})

export const spaces = defineSizes({
  small: 4,
  medium: 8,
  large: 24,
  extraLarge: 48,
})

export const radiuses = defineSizes({
  squared: 0,
  small: 4,
  medium: 8,
  large: 24,
  rounded: 99999,
})

export const elevations = defineShadows({
  flat: {
    blur: 0,
    spread: 0,
  },
  low: {
    blur: 1,
    spread: 2,
    color: "rgba(0, 0, 0, 0.15)",
  },
  medium: {
    blur: 1,
    spread: 2,
    color: "rgba(0, 0, 0, 0.2)",
  },
  high: {
    blur: 2,
    spread: 5,
    color: "rgba(0, 0, 0, 0.25)",
  }
})

export const { biorhyme } = defineFontFamilies({
  biorhyme: [
    {
      src: "url('/BioRhyme-ExtraBold.ttf')",
      fontWeight: "bold",
    },
    {
      src: "url('/BioRhyme-Regular.ttf')",
    },
  ],
});

export const fonts = defineFonts({
  title: {
    family: biorhyme,
    weight: "bold",
  }
})

export const medias = defineMedias({
  mobile: "(width < 480px)",
  tablet: "(480px <= width < 1180px)",
  desktop: "(1180px <= width < 1980px)",
  huge: "(1980px <= width)",
})