Skip to content
WovenUI LogoWovenUI

Setup

Vite

Fits any project that builds with Vite. Configure WovenUI once, load the global stylesheet in main.js, and style your markup with utility classes and apply().

Install

The vanilla template has no UI framework. Vite compiles .scss files once sass is installed, and @use "@wovenui/core" resolves through the package exports with no Vite configuration.

Terminal
npm create vite@latest my-app -- --template vanilla
cd my-app
npm install -D sass @wovenui/core

Set up

  1. Write the configuration once

    A partial that forwards @wovenui/core/mixins with your settings. The mixins entry has the same API as @wovenui/core (apply(), every mixin, token(), with()) and outputs no CSS.

    src/styles/_woven.scss
    @forward "@wovenui/core/mixins" with ($brand: #4361ee, $generate-utility-classes: true);
  2. Create the global stylesheet

    It emits the tokens, the reset, the base styles and the utility classes with your configuration. @use "woven" comes first, so core loads with the configured brand. Nothing else in the app loads @wovenui/core.

    src/styles/global.scss
    @use "woven";
    @use "@wovenui/core";
  3. Import it in the entry

    Imported once in main.js, it applies to every page the app builds. In a TypeScript project the file is main.ts and the line is the same.

    src/main.js
    import './styles/global.scss'

With utility classes

Classes go straight into index.html.

index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My app</title>
  </head>
  <body>
    <main class="grid gap-4 p-6">
      <div class="flex between x-center gap-3 p-4 bg-surface border rounded-md">
        <span class="font-semibold">Invoices</span>
        <span class="bg-success-subtle text-success text-xs rounded-full px-2 py-1">Paid</span>
      </div>
      <article class="card">
        <h2 class="title">Quarterly report</h2>
        <p class="text">Revenue and churn for July to September.</p>
      </article>
    </main>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

With apply()

Each component loads the partial and writes only its own rules. Numbers are configuration keys (p(4) is var(--wu-space-4)), and modifiers come after the utility: state and breakpoint in either order. Import the stylesheet from the entry, next to the global one.

src/card.scss
@use "../styles/woven" as *;

.card {
    @include apply(p(4), bg(surface), rounded(md), shadow(md) hover, p(6) md);
}

.title {
    @include apply(m(0), font-size(lg), font(semibold));
}

.text {
    @include apply(mt(2), mb(0), text-color(muted));
}
src/main.js
import './styles/global.scss'
import './card.scss'

Prebuilt CSS

To use the default configuration with no Sass step, import the prebuilt stylesheet in place of global.scss. apply() and your own configuration need the Sass route above.

src/main.js
import '@wovenui/core/min.css'

Dark mode

With no data-theme on <html>, the tokens follow the operating system setting. Set data-theme="dark" or data-theme="light" to choose one, and change it from a script to switch at runtime: document.documentElement.dataset.theme = "dark". Any element can carry data-theme to theme only its own subtree. Every class and every apply() rule reads the tokens, so nothing else changes.

index.html
<html lang="en" data-theme="dark">

What gets emitted

The global stylesheet holds the tokens, the light and dark themes, the reset, the base styles, the tooltips, the @property registrations and, with $generate-utility-classes: true, every utility class. Without the classes it is 5.8 KB gzipped. Load it on every page, because the tokens live there.

card.scss compiles to five rules and nothing else: .card, its hover, its md padding, the title and the text. The tokens are not repeated per stylesheet, and it cannot reset the configured brand.