HelixOverviewComponentsMapsGraphIntroductionInstallationDeriving a themeSandboxTheme builderVisual testingCortexDocsEngramBuildingTraceBuildingRecallDeclaredServicesInsightsGet in touchSource on GitHub
Getting started
Installationbun add @fusion.dev/helix@fusion.dev/helix-styles is a required dependency, on purpose. The components
use its semantic tokens and draw nothing without them. If the elements are
installed and the tokens are missing, your page shows unstyled boxes. There is
no fallback theme.Start a new projectIf you do not have a project yet, the scaffolder writes one with Helix
installed, the stylesheets imported, and every element registered:npm create @fusion.dev/helix-app@latest my-app ----template react-viteLeave out --template, and the command lists the templates and writes nothing.
Each template starts with the same three pages:a landing pagea sorted, paged data tablea form that a <form> reads with FormDataThe rest of this page adds Helix to a project you already have.Import the stylesheetsimport'@fusion.dev/helix-styles/helix.css'This one import loads four files in the order they must load:primitives.csstokens.cssbase.csselements.cssThe order matters, and a wrong order fails without an error. We set the order
once, inside the package, so you do not have to.The import resolves @fusion.dev/helix-styles through the dependency in
@fusion.dev/helix, so installing @fusion.dev/helix is enough. Only a bundler
resolves a bare specifier like this one. If you serve CSS through a <link>,
link helix.css by its path, as Without a bundler
shows.Import the files one at a timeEach file has its own export. If you bring your own reset or your own ramp,
import the two files you want and skip helix.css.primitives.css holds the raw ramp that the semantic layer is derived
from. The --helix-seed-* properties are read here. Your own code should
not name a primitive, and leaving the file out does not enforce that.
tokens.css refers to the primitives throughout, so without
primitives.css every semantic token resolves to nothing. We measured a page without it:
--helix-color-background computes to rgba(0, 0, 0, 0), and so does every
other color. Theming also depends on this file, because without
it, setting --helix-seed-brand changes nothing.tokens.css declares the semantic layer, the custom properties grouped
by category, plus color-scheme: light dark on :root. The files below read
from it, and it reads from primitives.css.base.css holds the element reset, the type scale on bare h1 through
h6, and the recipes for markup that Helix does not render. It reads tokens.elements.css hides each Helix element until its definition loads. It is
the file most often left out, because a page works without it until the page
is server-rendered. An element that has not upgraded has no shadow root and no
styles of its own, so without the file the markup flashes unstyled. With it,
the element stays hidden until it upgrades, and the layout settles when it
does.Import the files from a stylesheet you control, and keep them out of individual
components. The order then stays visible in one place.Register the elementsImport each family you use from its subpath:import'@fusion.dev/helix/button'import'@fusion.dev/helix/dialog'Each import has a side effect: it calls customElements.define for the
elements of that family, and for the families they render. You can run it more
than once. A second define for the same tag throws an error and stops the rest
of the module, so the helper behind the import checks the registry first.The package has side effects by design, so a bundler keeps everything you
import. import '@fusion.dev/helix' registers every element in the library,
which is the whole library in your bundle. Use it for a prototype, and use
subpaths in an app. Metrics lists the size of each family and of
the whole package.Check the installationRender one element and check whether it upgraded:awaitcustomElements.whenDefined('helix-button')console.log(document.querySelector('helix-button')?.shadowRootinstanceofShadowRoot)true means the definition loaded and the element built its shadow root.
false means the page has no helix-button to check. A promise that never
settles means the registration import did not run. Usually the import is outside
a 'use client' boundary, or you imported the subpath of a component you did
not end up using.If the element upgraded and the page still looks wrong, check the stylesheets
in the order above. The symptom tells you which layer is missing:No color at all means tokens.css is missing.Unstyled prose and bare headings mean base.css is missing.Components that look right once JavaScript runs, but flash unstyled before
it, mean elements.css is missing.To check the rest of your markup and styles against the Helix you installed,
start Diagnostics in development, and run helix scan on your
code. Each template starts diagnostics for you.Framework setupThe elements are custom elements, and every framework can render them.
Frameworks differ in three ways:How they pass a value that is not a string.How they bind an event.Whether they need configuration to accept an unknown tag.ReactShips a runtime bridge and jsx.d.tsVueShips vue.d.ts, needs compilerOptions.isCustomElementSvelteShips svelte.d.ts, and needs no configurationAngularNeeds CUSTOM_ELEMENTS_SCHEMAOther frameworksSolid, Qwik, Lit, and the three rules they all followWithout a bundlerThe stylesheets with no build stepA framework has its own page when Helix ships typings for it, or when it does
not compile Helix tags without configuration. Other frameworks work with no
setup.