Styling with @nexa/ui
Design tokens (with a real dark theme) + real CSS components (Button, Input, Card, Dialog, Drawer) + a small set of layout utilities, with real tree-shaking: the site only ships the CSS of what it actually uses. Deliberately small, not a full kit (see below for how to fill the gap fast if you need more).
Using a class
<button class="nx-btn nx-btn-primary">Buy</button>No declaration needed — nexa build already detects nx-* classes and generates the matching CSS.
Declaring it in nexa.toml
nexa add ui
# Installed @nexa/ui v0.1.0 (stable).
# Registered in nexa.toml and nexa.lock.nexa add ui registers the module — it doesn't download anything (it's already embedded in the binary), it just makes nexa.toml reflect reality and stops nexa build from warning.
Real tree-shaking
# dist/assets/nexa-ui.<hash>.css
# only ships tokens + .nx-btn — nothing from .nx-dialog if unusednexa-ui.css only carries the tokens plus the components the whole site actually uses — a fully static page in the same project doesn't link it at all.
How many components are there, and what if you need more?
<!-- Tailwind Play CDN: fast for prototyping; compile the CSS for production -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- ready-made components on top of Tailwind -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/daisyui@4/dist/full.min.css">
<!-- or, the classic choice -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">Today there's Button, Input, Card, Dialog and Drawer (plus color/spacing/radius tokens and a small set of layout utilities, see below) — the full list, with every modifier, lives in docs/REFERENCIA.md in Nexa's repo. To put together a complete design fast you've got three paths, and all three use the same mechanism (a plain <link>, from the previous step): (1) write your own CSS from scratch — this very tutorial does exactly that, a hand-written site.css linked from the layout; (2) use Tailwind (via CDN to prototype, or your own build for production) plus a ready-made component kit built on Tailwind like DaisyUI or Flowbite; or (3) use Bootstrap, PrimeVue/PrimeReact, or whatever you prefer. @nexa/ui and a third-party framework aren't competing — you can use nx-btn for the simple stuff and Tailwind/Bootstrap for the rest of the layout, on the same page.
Toast/snackbar for dashboards: ui.notify()
function saveOk() {
ui.notify({ message: "Saved successfully", variant: "success" });
}
function saveError() {
ui.notify({ message: "Couldn't save", variant: "danger", duration: 0 });
}Not to be confused with platform.notify() (a real OS-level notification, from the native packaging step) — ui.notify() is an ephemeral notification inside the page, like Quasar's $q.notify(). It stacks with others, auto-closes after 4s (duration: 0 disables that), is accessible (role="status"), and needs no declaration: ui is already builtin, same as for Dialog.
Stackable Dialog + ui.confirm()/ui.alert()
async function removeItem() {
if (await ui.confirm("Are you sure you want to delete this?")) {
// ...
}
}
<div class="nx-drawer" hidden>...</div>Opening a second Dialog while the first is open really stacks now (correct z-index by depth, aria-hidden on whichever gets covered) — the focus trap was already isolated per dialog from the start. ui.confirm()/ui.alert() cover the common case of confirming before deleting something, or announcing something got saved, without hand-writing the <div class="nx-dialog">: they return a real Promise that resolves on Accept/Cancel/Escape. Drawer (for sidebars and menus) has the same trapped focus as Dialog, with its own CSS.
Dark theme and layout utilities
<button data-nexa-strategy="load" onClick={() => platform.theme.set("dark")}>Dark</button>
<nav class="nx-flex nx-gap-3">...</nav>
<ul class="nx-grid nx-grid-cols-3">...</ul>
<main class="nx-stack">...</main>Without ever calling platform.theme.set(), the site already respects the OS's prefers-color-scheme — the helper (platform.theme.set("dark"|"light"|"system")) is only there so the user can pick explicitly and have that choice win over the system; it persists purely with platform.storage(), already covered. nx-flex/nx-grid/nx-stack are a small, deliberate set of layout utilities, tree-shaken just like the rest — not a full Tailwind-style utility system.