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.
npm create vite@latest my-app -- --template vanilla
cd my-app
npm install -D sass @wovenui/coreSet up
Write the configuration once
A partial that forwards
@wovenui/core/mixinswith 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);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";Import it in the entry
Imported once in
main.js, it applies to every page the app builds. In a TypeScript project the file ismain.tsand the line is the same.src/main.jsimport './styles/global.scss'
With utility classes
Classes go straight into 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.
@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));
}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.
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.
<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.