HelixOverviewComponentsMapsGraphIntroductionInstallationDeriving a themeSandboxTheme builderVisual testingCortexDocsEngramBuildingTraceBuildingRecallDeclaredServicesInsightsGet in touchSource on GitHub
Foundations
Recipes@fusion.dev/helix-styles includes recipes for markup that the components do
not render, such as:your own anchorsyour own buttonsa card you built yourselfprose from a CMSRecipes are data- attributes. They need no JavaScript, and they use the same
tokens as the components. With recipes, your page can look like Helix without
any custom elements.Buttons<buttondata-button="solid"data-button-tone="primary">Save</button><adata-button="ghost"href="/settings">Settings</a>A button recipe has two axes:data-button sets the button's emphasis: solid, outlined, ghost, or
subtle.data-button-tone sets what the button means: primary, accent,
neutral, or danger.data-button-width takes auto, standard, or full.Use the button recipe only on elements that Helix does not render, such as
an <a> styled as a button. For a button, use helix-button. The recipe has no
loading state, no pressed state, and no type="submit" handling.Links<adata-linkhref="/pricing">Pricing</a><adata-linkdata-link-underline="quiet"href="/docs">Docs</a>data-link-size and data-link-underline are the modifiers. quiet is for
navigation, where an underline on every row would distract. If a link opens a
new tab or window, say so in the link text, so it does not surprise your users.Navigation items<helix-navigationlabel="Sections"><aaria-current="page"href="/guide">Guide</a><ahref="/api">API</a></helix-navigation><buttondata-navigation-item>Menu</button>A link inside helix-navigation is styled by the page's stylesheet, because the
page's styles reach a slotted link before the component's do.
data-navigation-item gives the same look to an element outside a navigation
bar. Two custom properties set the text color:--navigation-item-color colors every destination except the current one.--navigation-item-current-color colors the destination marked
aria-current="page".Set them on helix-navigation or on any element that contains it.Surfaces and layout<divdata-card>…</div><lidata-list-item>…</li><divdata-dock="bottom-end">…</div>data-dock pins an element to a corner of the window. data-dock-within pins it
to a corner of the nearest positioned ancestor.Surface axesTwo of the visual axes describe a surface. Use these attributes
to apply them to a plain element:<sectiondata-material="glass">…</section><divdata-separation="elevated">…</div>data-material takes glass, frosted, and transparent. data-separation
takes elevated, filled, outlined, and plain. The values are the same as
the axes' values, so each word means the same thing here as on a component. A
<section> that is glass and a component with material="glass" get the same
treatment. See Elevation and material.Blur costs the most to render.glass and frosted both use a
backdrop-filter. The compositor re-reads what is behind the element on every
frame in which the element moves. A full-width band that stays on screen while
you scroll pays that cost the whole time. To show depth, use data-separation,
which costs less.Prose<articledata-prose><h2>From a CMS</h2><p>Styled without being rewritten.</p></article>In prose:Headings use the type scale.Paragraphs use the measure and leading.Lists, links, and inline code follow the same styles.See Typography.Three Markdown constructs need components, because HTML alone cannot hold what
they need:Fenced code becomes helix-code-block, with the fence's language as its
label and its language. A <pre> has no label or copy button.Alerts such as > [!WARNING] become helix-callout. A <blockquote> has no
tone. NOTE becomes tone="info", TIP becomes success, WARNING becomes
warning, and CAUTION becomes danger. IMPORTANT has no tone. Each
callout is headed by its kind, as GitHub shows it.Tables become helix-table. A <table> squeezes its columns to fit, so
a narrow screen breaks a value such as eu-central-1 across lines. The
header row becomes the table's columns, each aligned as the Markdown aligned
it. A column of short values stays whole, a column of sentences wraps, and a
table wider than the screen scrolls in its own box.The rehype plugin from @fusion.dev/helix/rehype makes all three changes in the
tree your Markdown library has already built. It parses nothing, so your
library, its dialect, and your sanitizing stay yours. Add it to any pipeline
that reaches rehype, such as remark with remark-rehype, react-markdown, or
MDX.Tables are GitHub Flavored Markdown, so your pipeline needs remark-gfm to
parse them. Without it, a table stays a paragraph of pipes. For a remark
pipeline, install:bun add unified remark-parse remark-gfm remark-rehype rehype-stringifyThen add the plugin after remark-rehype:importrehypeHelixfrom'@fusion.dev/helix/rehype'importrehypeStringifyfrom'rehype-stringify'importremarkGfmfrom'remark-gfm'importremarkParsefrom'remark-parse'importremarkRehypefrom'remark-rehype'import{unified}from'unified'consthtml=awaitunified().use(remarkParse).use(remarkGfm).use(remarkRehype).use(rehypeHelix).use(rehypeStringify).process(markdown)Code that a highlighter colored before the plugin ran keeps its colors. Pass
fences: false if your page draws its own code blocks, alerts: false to keep
alerts as quotes, tables: false to keep tables as HTML, and headings to
name each kind in your page's language. A table with a caption, a cell that
spans more than one column or row, or a heading cell outside its header row
stays HTML, because the grid cannot draw it as written.NoteThe plugin changes only these three constructs. If the Markdown comes from your
users, sanitize it in your pipeline before the plugin runs.Prose spaces each component the same as the element it replaces.Region axesThese two attributes are API. Import the base layer for them, even in an app
that uses only components:<divdata-density="sm">…</div><divdata-color-mode="dark">…</div>data-density sets the size of the controls in a region. It works through
custom properties, so it crosses every shadow boundary. data-color-mode sets
the color mode for a subtree. See Size and
density and Color modes.Utilities<spandata-hidden-visually>Sorting by</span>data-hidden-visually clips the element, so it stays in the accessibility tree.
display: none would remove it. See Accessibility.When to use a componentA recipe sets appearance and has no behavior. A recipe cannot:manage statetake part in a formtrap focushandle the keyboardIf you need to add a script to a recipe, use the component.