Design system
Importing the neutron-design-system/styles.scss stylesheet makes your app look
like it belongs in the Neutron shell. Its rules are narrow on purpose: dozens
of independently authored apps should read as one system.
Setup
@use 'neutron-design-system/styles.scss';
@layer nt.tokens, nt.base, nt.layout, nt.components, nt.utilities, app;
@layer app {
.nt-app.my-app {
--nt-accent: #8adf9d;
}
}
<main class="nt-app nt-app--fill my-app">
<section class="nt-panel">
<h1 class="nt-title">My app</h1>
<button class="nt-button">Review in kernel</button>
</section>
</main>
Add a Sass plugin to your frontend build and link the generated CSS as a package-local asset from your HTML.
The package root separately exports optional TypeScript class helpers:
import {cx, nt, sizeClass, toneClass} from 'neutron-design-system';
They only compose class-name strings; importing them does not load the SCSS.
The rules
| Rule | |
|---|---|
| Dark only | There is no light theme |
| No gradients, no remote fonts | |
Radius capped at 5px | In the public tokens |
| Separate by tonal fill | Not by visible component borders |
| Structural separation = one-pixel inset hairlines | Not perimeter borders |
| Focus = a single visible hairline outline | |
| Spacing follows 4/8/12/16/20/24/32px |
And a compositional one that people miss:
Keep operational surfaces unframed on the page background. Do not turn every section into a card or panel.
Use nt-section headings, nt-detail-grid summaries, nt-settings-list rows,
and nt-disclosure for secondary detail.
Scope and overrides
Everything is scoped under .nt-app and organised into cascade layers. Put your
own rules in the app layer and use app-prefixed classes for local layout
and composition.
Do not rewrite nt-* component classes, and never style kernel workspace
classes from inside an app frame.
Recipes
App root — nt-app nt-app--fill plus an app-prefixed class.
A method call form — nt-form-grid nt-form-grid--two for compact field
pairs. Validate locally, show a request preview, then hand off with wording like
Review in kernel.
Compact status — nt-metric, nt-metric-label, nt-metric-value,
nt-metric-detail for non-interactive summaries.
Operational settings — nt-section with nt-detail-grid or
nt-settings-list; nt-disclosure for secondary content, with its native
button wired to aria-expanded and aria-controls.
Dense inspectors — nt-table-wrap, nt-copy-field, nt-json,
nt-pre nt-pre--wrap.
Tags — nt-tag-list and nt-tag for compact metadata. If a tag is
interactive, make it a button or checkbox.
Empty / loading / error — nt-state variants and nt-alert with visible
recovery controls.
Destructive flows — warning, danger, or critical severity with explicit consequence text. Kernel approval stays kernel-owned.
Accessibility
The package documents an accessibility matrix pairing each class with its element or role, name source, state attributes, and keyboard behaviour. Two points recur:
- Tooltip text is not an accessible name. Icon buttons need
aria-labelor hidden text. - Native elements do the work.
nt-buttonis a real<button>,nt-checkboxwraps a real input,nt-dialogis a native<dialog>or a named grouped panel witharia-labelledby.
role="alert" is for urgent inserted errors only, and aria-sort appears only
when a table actually sorts. App code owns Escape handling and focus restore for
its own dialogs.
The security rule
:::caution Do not imitate kernel dialogs App UI must not imitate the kernel's trusted approval, install, authorization, or signature dialogs.
An app frame cannot render into kernel chrome — whether it is an opaque tile or
tray, or a capability-bound dedicated background — but it can draw something
that looks like trusted UI. That is why the recommended wording for a
consented action is deferential (Review in kernel): the app should visibly
hand off, not appear to decide.
:::
Reference
Kitchen Sink is the living reference and the package's test surface: forms, typed calls, schema display, alerts, warning and danger states, dense inspectors, and resize-heavy text in narrow tiles.
Tiles can be small. Test your layout at a narrow width in a split workspace, not just full-screen.