AZMARA PLATFORM
Guide

Install in Vite

Add @azmr/ui to a Vite React app with Tailwind CSS v4's Vite plugin, a first component and dark mode.

View as Markdown for coding assistants, or see llms.txt.

This guide adds @azmr/ui to a React app built with Vite. It takes about five minutes. If you do not have an app yet, create one with npm create vite@latest my-app -- --template react-ts; everything below is what you add or change.

1. Install

pnpm add @azmr/ui @azmr/core
# or
npm install @azmr/ui @azmr/core

react and react-dom are already in your app. @azmr/core is a peer dependency, so install it yourself: see Installation.

2. Set up Tailwind CSS v4

Tailwind v4 has a Vite plugin. Install it (pnpm add -D tailwindcss @tailwindcss/vite) and add it to your Vite config:

vite.config.ts
import tailwindcss from "@tailwindcss/vite";
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";

export default defineConfig({
  plugins: [react(), tailwindcss()],
});

3. Import the stylesheet

In your global CSS, import Tailwind and then the package's stylesheet:

src/index.css
@import "tailwindcss";
@import "@azmr/ui/styles.css";

Load it once, where your app starts. The entry file below also sets up dark mode, explained in step 5:

src/main.tsx
import { ThemeProvider } from "@azmr/ui/react";
import {
  DENSITY_COOKIE,
  parseDensity,
  parseThemePreference,
  readCookie,
  THEME_COOKIE,
} from "@azmr/ui/theme";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
import "./index.css";

// Read the choice saved by an earlier visit, so a reload keeps it.
const theme = parseThemePreference(readCookie(document.cookie, THEME_COOKIE));
const density = parseDensity(readCookie(document.cookie, DENSITY_COOKIE));

createRoot(document.getElementById("root") as HTMLElement).render(
  <StrictMode>
    <ThemeProvider defaultTheme={theme} defaultDensity={density}>
      <App />
    </ThemeProvider>
  </StrictMode>,
);

4. Use a component

src/App.tsx
import { Button } from "@azmr/ui/button";
import { Input } from "@azmr/ui/input";
import { ThemeToggle } from "./theme-toggle";

export default function App() {
  return (
    <main className="mx-auto flex max-w-sm flex-col gap-3 p-6">
      <h1 className="text-2xl font-semibold">Hello</h1>
      <label htmlFor="name" className="text-sm font-medium">
        Your name
      </label>
      <Input id="name" placeholder="Aroha" />
      <Button>Say hello</Button>
      <ThemeToggle />
    </main>
  );
}

Run pnpm dev and open the page. You should see a heading, a labelled field and a button, styled with the design tokens.

5. Add dark mode

With no setup at all the page already follows the operating system. To let people choose, the entry file above wraps the app in ThemeProvider, which remembers a choice in a cookie. The entry file reads that cookie when the page starts, so a reload keeps the choice. A component changes it with useTheme():

src/theme-toggle.tsx
import { Button } from "@azmr/ui/button";
import { useTheme } from "@azmr/ui/react";

export function ThemeToggle() {
  const { resolvedTheme, setTheme } = useTheme();
  const next = resolvedTheme === "dark" ? "light" : "dark";
  return (
    <Button variant="outline" onClick={() => setTheme(next)}>
      Switch to {next} mode
    </Button>
  );
}

Density works the same way: useTheme() also returns density and setDensity, with the values compact, comfortable and spacious.

A page that is built in the browser can only apply the saved choice once its JavaScript has run, so someone who chose dark while their system is light may see a brief flash of the light theme first. If that matters, inline the themeInitScript() described in Theming.

What was tested

The files above are the files of an app that CI builds. On every change it packs @azmr/ui into a tarball, installs it into that app, type-checks and builds it, and checks that:

  • Tailwind found the package's classes inside node_modules, with nothing added to the config;
  • the colour tokens are in the built stylesheet;
  • the built bundle contains the app and the Button, and reads the saved theme cookie.

Next steps

On this page