Skip to content
helia-ui
Gallery
HELIA HUB

Gallery

This page is for choosing. Every option the card parts and the motion system offer is on it, side by side, each one showing the exact source that produces it behind “Show code”. Nothing here is a new component: the variants are modifiers on Card and the transitions are classes in recipes.css.

The reference tables are on Cards for the parts and in docs/design-system.md for the motion tokens and the site theme.

Four tones, each of them a different answer to “what stands in for the edge”. outlined is the default and card is its older name; filled and muted are likewise the same tone. Padding and radius do not move between them, so a row can mix tones and still line up.

density moves the step the card parts pad to: 3 for compact, 4 by default, 5 for comfortable. A part that names its own step opts out and keeps it.

top is the stacked card. side puts the frame down the leading edge at 40% of the card and stacks again below 42rem, so a narrow viewport gets the top placement whatever is asked for. background fills the card with the frame, draws an overlay over it, and inverts the ink onto the fixed paper tone.

A figure, its label, and an optional change. The number is the child, so it can carry a unit or markup; the delta is a Badge and its tone is the caller’s, because the component has no idea whether up is good.

BigNumber is the figure with no card around it: the number at the display step, the unit beside it a step down, and the label above or below. Sparkline is the trend at control size, drawn by the same Plot-at-build path as Chart and shipped as inline SVG — no axes, no gridlines, one series in --helia-chart-1 unless the composition sets --accent.

The arrow and the ink are two props. direction says which way the number went; deltaTone says whether that reads well, and only the composition knows, because a figure that counts open findings goes up and that is not good news. Both parts set their figures in tabular numerals, so a row of them lines up on the digit.

Every number below is invented and describes this documentation site. Nothing here is a measurement of any part.

<CardContent variant="stats"> of three BigNumbers

Routes emitted

206up+18

Build time

41sdown-18%

Pages published

128up+9

Show code
<Card>
<CardContent variant="stats">
<BigNumber label="Routes emitted" delta="+18" direction="up">
<span>206</span>
<Sparkline
slot="sparkline"
values={[164, 171, 169, 178, 186, 191, 199, 206]}
ariaLabel="Routes emitted, rising across the quarter."
marker
/>
</BigNumber>
<BigNumber
label="Build time"
unit="s"
delta="-18%"
direction="down"
deltaTone="success"
>
<span>41</span>
<Sparkline
slot="sparkline"
kind="area"
values={[58, 56, 57, 51, 48, 47, 43, 41]}
ariaLabel="Build time, falling across the quarter."
marker
/>
</BigNumber>
<BigNumber label="Pages published" delta="+9" direction="up">
<span>128</span>
<Sparkline
slot="sparkline"
values={[96, 101, 104, 110, 113, 119, 124, 128]}
ariaLabel="Pages published, rising across the quarter."
marker
/>
</BigNumber>
</CardContent>
</Card>

The accent is a hint, not a field, and so is the ink. A page spends both a few times: the accent word in the hero, one inked tile in a mosaic, the layer of a stack the page is about, the leading bar in a comparison, and the link out to the hub. The parts below are what make those moments cheap to write. What a page may spend, and how often, is the accent budget in the design system.

tone="ink" puts one card of a set on the ground the contrast hero uses, pinned dark in both themes, with the inks and the accent re-derived against it. The title, which is the link, takes the accent. One of them in a set: two inked tiles is a dark row with a gap in it.

<LinkCard tone="ink">

Show code
<CardGrid columns={3} equalize class="not-content">
<LinkCard titleAs="h4" href="/helia-ui/cards/" eyebrow="Guide" title="The card parts">
What each part owns, and how a subset of them composes.
</LinkCard>
<LinkCard titleAs="h4" href="/helia-ui/layout/" eyebrow="Guide" title="Bands and grids">
Bands, grids and mosaics, and which one a section wants.
</LinkCard>
<LinkCard tone="ink" titleAs="h4" href="/helia-ui/foundations/" eyebrow="Reference" title="Tokens and scales">
The spacing, radius and type ladders every part is built from.
</LinkCard>
</CardGrid>

accent on a BigNumber colors the unit and nothing else. The glyph is the smallest thing on a figure that still reads across a section, so it is what the budget can afford here; the number stays ink.

Every number below is invented and measures nothing.

<BigNumber accent unit>

Vector over scalar

12×

Vector over DSP

8×

DSP over scalar

3×

Show code
<Card>
<CardContent variant="stats">
<BigNumber label="Vector over scalar" unit="×" accent>
<span>12</span>
</BigNumber>
<BigNumber label="Vector over DSP" unit="×" accent>
<span>8</span>
</BigNumber>
<BigNumber label="DSP over scalar" unit="×" accent>
<span>3</span>
</BigNumber>
</CardContent>
</Card>

Stack is the chain of layers a product page opens with: what sits above the thing, the thing, and what it runs on. One layer carries accent, and it is the page’s own. Below 62rem the chain folds to two columns, because four columns of wrapped pills on a phone is not a diagram.

<Stack layers>

  1. Model toolingCompilerRuntime
  2. KernelsThis layer23 families
  3. Acceleration pathScalarDSPVector
  4. SiliconCortex-M4Cortex-M55
Show code
<Stack
ariaLabel="Where the kernel layer sits"
layers={[
{ label: 'Model tooling', chips: [{ label: 'Compiler' }, { label: 'Runtime' }] },
{
label: 'Kernels',
accent: true,
chips: [{ label: 'This layer', accent: true }, { label: '23 families' }],
},
{ label: 'Acceleration path', chips: [{ label: 'Scalar' }, { label: 'DSP' }, { label: 'Vector' }] },
{ label: 'Silicon', chips: [{ label: 'Cortex-M4' }, { label: 'Cortex-M55' }] },
]}
/>

Bars is the comparison a heading needs and a chart is too heavy for: labeled tracks against one scale, an axis under them, and one accented row. Every row is text as well as a bar, so the reading survives without the tracks. Past a handful of rows, or with a series that has a shape, reach for Chart.

The figures below are invented and measure nothing.

<Bars rows max ticks>

  1. Vector12.0×
  2. DSP3.3×
  3. Scalar1.0×

Invented figures, held here to show the scale.

Show code
<Bars
max={12}
ticks={['0×', '6×', '12×']}
caption="Invented figures, held here to show the scale."
rows={[
{ label: 'Vector', value: 12, display: '12.0×', accent: true },
{ label: 'DSP', value: 3.3, display: '3.3×' },
{ label: 'Scalar', value: 1, display: '1.0×' },
]}
/>

Title, one line, and a cue that moves when the card is under the pointer. The link lives on the title and the recipe stretches it over the card, so the whole card is the target and the cue is inside the same hit area.

A page that renders its cards from a record writes none of their words in its source. The parts state their own line for the page’s Markdown twin, so an agent reading the rendition gets the card the page shows rather than the props it was written with.

Six cards that need no image. Good artwork is the scarcest thing a card family depends on, so each of these carries itself on type, a mark or a figure instead. None of them is a new component: they are the CardHeader marks and scale, two parts (CardList, CardQuote) and one CardContent variant, so tone, density and the lift reach all of them unchanged.

The same six with density="compact". The mark, the list gap and the figure row all come off the density hook, so nothing here is restyled per size.

Five transitions, each built from the motion tokens and nothing else, so the per-site dial and the reduced-motion rule reach all of them at once. Point at the cards below; none of them does anything at rest.

The fifth transition. The rail reads the same dial the CSS does, so a site with motion switched off gets the jump rather than the slide.

The site theme is nine dials in one file. :root is where a site sets them; a section that wants its own treatment sets them on a wrapper that carries data-helia-theme, which is the hook semantic.css re-derives the composed tokens on. That is the mechanism every example below uses, and it is why they can sit next to each other on one page. A wrapper without the attribute moves only the dials themselves, not the radius steps and tinted surfaces built out of them.

The accent dial reaches a card through its artwork rather than its edge: no card part carries an accent rule or brim, so a subtree that names an accent shows it in the media, the badges and the type. The second accent is the one that pairs with it, and a link card spends it on the cue under the pointer.

Reveal fades and rises what it wraps the first time it reaches the viewport. Use it on a section, not on every card in one: a page where each element arrives separately reads as a page that is still loading. stagger is the one exception, and it is still one wrapper.

The hidden state is a class the script adds, so the content is visible without JavaScript, and the script returns before arming anything when the motion scale is 0.

Replay re-arms every reveal on this page, so the entry can be watched without scrolling away and back. It does nothing for a visitor who asked for reduced motion, because nothing armed.

<Reveal>

Show code
<Reveal>
<div className="gallery-grid not-content">
<Card tone="elevated">
<CardContent>One section, one reveal.</CardContent>
</Card>
<Card tone="elevated">
<CardContent>The cards inside it arrive together.</CardContent>
</Card>
<Card tone="elevated">
<CardContent>Which is the point of wrapping the section.</CardContent>
</Card>
</div>
</Reveal>

The cascade is on the direct children, so the grid is the Reveal rather than a div inside it: one wrapper with a grid class on it, and the cards are the children that arrive.

<Reveal stagger>

With stagger, the children arrive in order.

Each one waits a fast step longer than the last.

The wrapper itself does not move.
The cascade stops at the sixth child.
Show code
<Reveal stagger class="gallery-grid not-content">
<Card tone="elevated">
<CardContent>With stagger, the children arrive in order.</CardContent>
</Card>
<Card tone="elevated">
<CardContent>Each one waits a fast step longer than the last.</CardContent>
</Card>
<Card tone="elevated">
<CardContent>The wrapper itself does not move.</CardContent>
</Card>
<Card tone="elevated">
<CardContent>The cascade stops at the sixth child.</CardContent>
</Card>
</Reveal>

<Reveal threshold={0.4}>

Show code
<Reveal threshold={0.4}>
<div className="gallery-grid not-content">
<Card tone="filled">
<CardContent>
A higher threshold waits until more of the section is in view.
</CardContent>
</Card>
<Card tone="filled">
<CardContent>
Lower it for a section too tall to ever cross the mark.
</CardContent>
</Card>
</div>
</Reveal>

Four parts that arrange a page rather than fill one. None of them knows what it is carrying: the ground, the cards and the artwork are all handed in, so the same four cover a product page, a release note and a landing.

Band takes a section to the edges of the reading frame and keeps its content on the readable measure. tone picks the ground and density the rhythm above and below it. None of the four grounds draws an edge or an elevation: a section that carried either would be a very wide card.

<Band tone="muted">

Show code
<Band tone="muted">
<div slot="header">
<Eyebrow>Ground</Eyebrow>
<h4>A section with a ground of its own</h4>
</div>
<p>
The paint runs to the edges of the frame and the words stay on the
measure. Nothing is drawn around it.
</p>
</Band>

CardGrid is the row of peers. A named count steps down at the two breakpoints; auto fits whatever min allows, which is the answer for a set whose length the page does not know. stagger makes the grid the reveal itself, so the cards cascade in rather than the block arriving as one.

<CardGrid columns={3} equalize stagger>

Columns

Two, three, four, or as many as the minimum allows.

Equalise

Every row takes the height of the tallest card on the grid.

Stagger

One wrapper, one arrival, told across the row.
Show code
<CardGrid columns={3} equalize stagger class="not-content">
<Card tone="filled">
<CardHeader titleAs="h4">
<span>Columns</span>
</CardHeader>
<CardContent>Two, three, four, or as many as the minimum allows.</CardContent>
</Card>
<Card tone="filled">
<CardHeader titleAs="h4">
<span>Equalise</span>
</CardHeader>
<CardContent>Every row takes the height of the tallest card on the grid.</CardContent>
</Card>
<Card tone="filled">
<CardHeader titleAs="h4">
<span>Stagger</span>
</CardHeader>
<CardContent>One wrapper, one arrival, told across the row.</CardContent>
</Card>
</CardGrid>

Masonry packs cards of unequal height into columns with no dead space under the short ones. It is CSS columns, so the packing is right in the first paint; the cost is a reading order that runs down each column before it moves across. Masonry packs by column with no JavaScript; use CardGrid when rows must align.

<Masonry columns={3}>

The profile told us where the cycles went on the first afternoon.

Dana MercerFirmware lead

Uneven by design

A short card next to a long one is what the layout is for. Forcing the two to one height is what makes a set of notes look padded.

Included

What the column keeps

  • Each card whole across a break
  • The gap on the spacing scale
  • One column below 42rem
Show code
<Masonry columns={3} class="not-content">
<Card tone="filled">
<CardQuote attribution="Dana Mercer" detail="Firmware lead" initials="DM">
The profile told us where the cycles went on the first afternoon.
</CardQuote>
</Card>
<Card tone="filled">
<CardHeader titleAs="h4">
<span>Uneven by design</span>
</CardHeader>
<CardContent>
A short card next to a long one is what the layout is for. Forcing the
two to one height is what makes a set of notes look padded.
</CardContent>
</Card>
<Card tone="filled">
<CardHeader titleAs="h4" eyebrow="Included">
<span>What the column keeps</span>
</CardHeader>
<CardList
items={[
'Each card whole across a break',
'The gap on the spacing scale',
'One column below 42rem',
]}
/>
</Card>
</Masonry>

Mosaic gives one card the room to carry artwork and fills the rest of the set around it. The feature is the first child rather than a prop, so the arrangement follows reading order. pattern moves it to the end of the set or across the top.

<Mosaic>

The feature

Two columns by two rows, with somewhere to put the artwork.

The rest fill the remaining cells.
In the order they were written.
Nothing here is placed by hand.
Show code
<Mosaic class="not-content">
<Card tone="elevated" media="background">
<CardMedia>
<Media treatment="color-field" style="--accent: var(--helia-accent-cyan)" />
</CardMedia>
<CardHeader titleAs="h4">
<span>The feature</span>
</CardHeader>
<CardContent>Two columns by two rows, with somewhere to put the artwork.</CardContent>
</Card>
<Card tone="filled">
<CardContent>The rest fill the remaining cells.</CardContent>
</Card>
<Card tone="filled">
<CardContent>In the order they were written.</CardContent>
</Card>
<Card tone="filled">
<CardContent>Nothing here is placed by hand.</CardContent>
</Card>
</Mosaic>

The rest of this section is not an example on a stage: the bands are on the page itself, which is the only way to see a ground actually run to the edges and a run of sections read as one rhythm. Scroll it as a page rather than as a set of parts.

Overview

One feature and the set around it

Featured

The one the section is about

Artwork needs room, and a grid of equals says nothing about which card is the point.

Beside it

Peers, at the size a peer deserves.

Under it

Filled in document order.

And on

The set is as long as the page needs.

Capabilities

Three peers on a ground

The ground changes

The section above it has none, so this one reads as a step rather than as a box.

The measure does not

Paint to the edges, text on the same width as the prose above it.

Nothing is drawn

No edge, no brim, no shadow. The ground is the whole of the signal.

Notes

What came back from the field

We stopped arguing about section spacing the week the bands landed.

Priya RamanPlatform

Content first

Good artwork is the scarcest thing a card family depends on, so the options that carry a card without an image are the ones a long page leans on.

Covered

What a note can hold

  • A quote and who said it
  • A short list
  • A line of prose

Three columns, no measuring, no layout shift when the font lands.

Sam Okafor

The close

The inked ground is pinned dark in both themes, because ink that follows the theme over a ground that does not is a section that reads half the time. Code slotted into it holds the dark syntax theme on either page theme, for the same reason.

band.ts
import { Band } from '@ambiqai/helia-ui/astro';

Chart draws with Observable Plot at build and ships the result as inline SVG, so a page with five charts on it still ships no chart JavaScript. The palette is written as var(--helia-chart-*), which is what lets a figure that will never be redrawn follow the theme toggle.

The title and the subtitle are the part’s HTML rather than Plot’s type, and the subtitle says what is plotted against what — which is why no axis is titled. Gridlines run across the measure; only a scatter, which has a measure on both axes, gets the second set.

Every number below is invented and describes this documentation site. Nothing here is a measurement of any part.

kind="line" with two series

Weekly page views

Page views against week of the quarter, by section

  • Guides
  • Reference
5001,0001,5002,000123456789101112
Synthetic series.
Show code
<Chart
title="Weekly page views"
subtitle="Page views against week of the quarter, by section"
caption="Synthetic series."
kind="line"
data={trafficSeries}
x="week"
y="views"
series="section"
width={900}
height={280}
/>

kind="bar" grouped by series

Build time by stage

Wall-clock seconds against build stage, by cache profile

  • Cold
  • Warm
InstallGenerateBuildAssert020406080100
Show code
<Chart
title="Build time by stage"
subtitle="Wall-clock seconds against build stage, by cache profile"
kind="bar"
data={buildSeries}
x="stage"
y="seconds"
series="profile"
width={900}
height={280}
/>

kind="area", one series

Pages published

Pages on the site against week of the quarter

0102030405060123456789101112
Show code
<Chart
title="Pages published"
subtitle="Pages on the site against week of the quarter"
kind="area"
data={pagesSeries}
x="week"
y="pages"
width={900}
height={260}
/>

kind="scatter", gridlines on both axes

Weight against score

Performance score against transferred kilobytes, by template

  • Static
  • Island
80859095100100150200250300350400450500
Show code
<Chart
title="Weight against score"
subtitle="Performance score against transferred kilobytes, by template"
kind="scatter"
data={weightSeries}
x="transferKb"
y="score"
series="template"
width={900}
height={280}
/>

A chart with more categories than a row of bars can name, and a measure that spans more than a decade, needs four options the defaults do not give it. The set below is invented — the routines do not exist and neither do the ratios — but it is shaped like the one the options were written for: fourteen long names, three series, and speedups from under one to twelve.

orientation="horizontal" puts the categories on the vertical axis and takes the left margin from the longest label, so a name is never cut. The data contract does not move with the drawing: x still names the categories and y still names the measure.

orientation="horizontal"

Speedup by routine

Times faster than the reference path, by code path

  • vector path
  • scalar path
  • reference
packing_rescale_s8packing_rescale_s16window_fold_s8window_fold_s16stride_gather_s8stride_gather_s16accumulate_wide_s8accumulate_wide_s16saturate_narrow_s8saturate_narrow_s16transpose_block_s8transpose_block_s16reduce_rows_s8reduce_rows_s16024681012
Invented routines and invented ratios.
Show code
<Chart
title="Speedup by routine"
subtitle="Times faster than the reference path, by code path"
caption="Invented routines and invented ratios."
kind="bar"
data={routineSpeedups}
x="routine"
y="speedup"
series="path"
orientation="horizontal"
width={900}
height={620}
/>

scale moves the measure. A log axis ticks at 1, 2 and 5 through each decade it spans and rounds its own ends to that sequence unless min and max say otherwise, which is what stops a set with one twelve-times result in it from drawing every other bar as a stub. A log axis cannot draw a zero or a negative number: given one, the chart is drawn linear and the build log says why.

scale={{ type: "log", min: 0.5 }}

Speedup by routine, logarithmic

Times faster than the reference path, by code path

  • vector path
  • scalar path
  • reference
packing_rescale_s8packing_rescale_s16window_fold_s8window_fold_s16stride_gather_s8stride_gather_s16accumulate_wide_s8accumulate_wide_s16saturate_narrow_s8saturate_narrow_s16transpose_block_s8transpose_block_s16reduce_rows_s8reduce_rows_s160.5x1x2x5x10x20x
Show code
<Chart
title="Speedup by routine, logarithmic"
subtitle="Times faster than the reference path, by code path"
kind="bar"
data={routineSpeedups}
x="routine"
y="speedup"
series="path"
orientation="horizontal"
scale={{ type: 'log', min: 0.5 }}
valueFormat={(value) => `${value}x`}
width={900}
height={620}
/>

Inside a group the bars run in the order the rows first name the series, not in the order those names sort in, and the legend lists them in that same order. The series here are written fastest first — vector path, scalar path, reference — which is not alphabetical, so the two orders agreeing is the assertion rather than a coincidence.

Group order is series order

Speedup by routine, compact

Times faster than the reference path, by code path

  • vector path
  • scalar path
  • reference
packing_rescale_s8packing_rescale_s16window_fold_s8window_fold_s16stride_gather_s8stride_gather_s16accumulate_wide_s8accumulate_wide_s16saturate_narrow_s8saturate_narrow_s16transpose_block_s8transpose_block_s16reduce_rows_s8reduce_rows_s16024681012
Show code
<Chart
title="Speedup by routine, compact"
subtitle="Times faster than the reference path, by code path"
kind="bar"
data={routineSpeedups}
x="routine"
y="speedup"
series="path"
orientation="horizontal"
density="compact"
width={900}
height={520}
/>

axis titles an axis the subtitle cannot carry the unit for, valueLabels writes each bar’s value at its end, and referenceLines draws a rule across the measure. A constant baseline belongs on the rule rather than in a third series: it costs a palette color, a legend entry and a third of the bars to draw a line. Value labels are dropped as a set when the bands are too small to hold them, so a chart that shows them at one height stops showing them at another rather than overprinting.

axis, valueLabels and referenceLines

Speedup against the reference path

Two code paths, fourteen routines

  • vector path
  • scalar path
packing_rescale_s8packing_rescale_s16window_fold_s8window_fold_s16stride_gather_s8stride_gather_s16accumulate_wide_s8accumulate_wide_s16saturate_narrow_s8saturate_narrow_s16transpose_block_s8transpose_block_s16reduce_rows_s8reduce_rows_s16Routine0.5x1x2x5x10x20xTimes faster than reference11.8x1.6x4.2x0.9x9.4x2.1x3.1x1.2x6.7x1.8x2.4x0.8x12x2.4x5.3x1.1x8.1x1.9x2.9x1.3x7.4x2.2x3.6x0.95x10.2x1.7x4.8x1.4xreference
Show code
<Chart
title="Speedup against the reference path"
subtitle="Two code paths, fourteen routines"
kind="bar"
data={routinePaths}
x="routine"
y="speedup"
series="path"
orientation="horizontal"
scale={{ type: 'log', min: 0.5 }}
axis={{ valueLabel: 'Times faster than reference', categoryLabel: 'Routine' }}
valueLabels
valueFormat={(value) => `${value}x`}
referenceLines={[{ value: 1, label: 'reference' }]}
width={900}
height={480}
/>

ChartGroup gives the charts equal columns, so three drawn at the same width and height line up across the row and read as one figure. Draw them at a width near the column, not at the page width: the SVG scales into its column and takes its type with it.

<ChartGroup> of three

Page views

Views against week, by section

  • Guides
  • Reference
5001,0001,5002,000510

Build time

Seconds against stage, by cache profile

  • Cold
  • Warm
InstallGenerateBuildAssert020406080100

Pages published

Pages against week

0204060510
Show code
<ChartGroup>
<Chart
title="Page views"
subtitle="Views against week, by section"
kind="line"
data={trafficSeries}
x="week"
y="views"
series="section"
width={300}
height={200}
density="compact"
/>
<Chart
title="Build time"
subtitle="Seconds against stage, by cache profile"
kind="bar"
data={buildSeries}
x="stage"
y="seconds"
series="profile"
width={300}
height={200}
density="compact"
/>
<Chart
title="Pages published"
subtitle="Pages against week"
kind="area"
data={pagesSeries}
x="week"
y="pages"
width={300}
height={200}
density="compact"
/>
</ChartGroup>

Three parts for an index rather than a grid of cards: the tile that marks an entry, the row that is one entry, and the panel that sets a short piece of writing beside the code it describes.

The box comes off the control-height scale and the frame is one of three. --accent is per instance, so a list can give every entry a color of its own without the part learning what the list holds.

<IconTile size variant />

Show code
<div className="helia-display-row">
<IconTile name="microchip" size="sm" />
<IconTile name="microchip" />
<IconTile name="microchip" size="lg" />
<IconTile name="gauge-high" variant="outlined" />
<IconTile name="gauge-high" variant="filled" />
<IconTile
name="chart-line"
size="lg"
variant="filled"
style="--accent: var(--helia-accent-cyan)"
/>
</div>

The anchor is the row itself, so the tile, the title and the line are one hit area and one accessible name. Hover tints the row where it sits; nothing lifts. Two to a desktop column and one to a phone is CardGrid columns={2}.

<IconRow href title icon />

Show code
<CardGrid columns={2}>
<IconRow href="/helia-ui/cards/" title="Cards" icon="layer-group">
Every part of the card family, and the modifiers that move them.
</IconRow>
<IconRow href="/helia-ui/code/" title="Code" icon="code">
Fences, language tabs and the terminal transcript.
</IconRow>
<IconRow href="/helia-ui/layout/" title="Layout" icon="table-columns">
Bands, grids and the two mosaics.
</IconRow>
<IconRow href="/helia-ui/foundations/" title="Foundations" icon="palette">
The tokens every recipe on this page is built from.
</IconRow>
</CardGrid>

The code slot is what the panel exists for: the block is the answer to the sentence beside it rather than a fence further down the page. ratio gives the two columns their share of the width, and below 62rem the text leads and the code follows.

<SplitPanel ratio="3:2">

Quickstart

Profile a model on the board

The command reads the model, runs it on the attached board and writes the layer timings beside it.

npm run profile -- model
Show code
<SplitPanel ratio="3:2" titleAs="h4">
<span slot="eyebrow">Quickstart</span>
<span slot="title">Profile a model on the board</span>
<div slot="body">
The command reads the model, runs it on the attached board and writes
the layer timings beside it.
</div>
<CodeTabs
slot="code"
ariaLabel="Profiler quickstart"
tabs={[
{
label: 'Shell',
language: 'bash',
code: 'npm run profile -- model',
},
{
label: 'Python',
language: 'python',
code: "profile('model')",
},
]}
/>
</SplitPanel>

The top of a landing page. The headline is the default slot rather than a prop, because the word that takes the product accent has to be marked in the markup: wrap it in <em> and the hero draws it in --helia-product-accent with the slant taken off. The side column renders only when aside or media has something in it, and below 62rem it stacks under the lede.

In MDX the headline goes in a <Fragment> on one line, with a blank line between it and every slotted child. Bare text on its own line is flow content, so MDX wraps it in a paragraph inside the heading and pulls the line after it into the same paragraph, which costs the first action its slot.

data-helia-accent is set on the example itself to show one product’s color on a page that carries none. A product site sets it once, through the Starlight plugin’s accent option, and writes no CSS.

The copy here is placeholder, not an approved product claim. The code frame in the side column holds the dark treatment on either page theme, the way one inside a contrast Band does, down to the frame’s title and buttons.

<Hero variant="contrast" eyebrow badge summary>

Kernel library

Kernel acceleration for the edge.

Preview

A kernel layer with tuned operators, package delivery, and integration paths for the toolchains a firmware build already uses.

Operators

200+

Op types

53

Models

40+

Paths

4

Install
npm install @example/kernels
Show code
<Hero
variant="contrast"
titleAs="h3"
data-helia-accent="helia-core"
eyebrow="Kernel library"
badge="Preview"
summary="A kernel layer with tuned operators, package delivery, and integration paths for the toolchains a firmware build already uses."
>
<Fragment>Kernel <em>acceleration</em> for the edge.</Fragment>
<Button slot="actions" href="/helia-ui/">Getting started</Button>
<Button slot="actions" href="/helia-ui/gallery/" variant="secondary">Why</Button>
<Button slot="actions" href="/helia-ui/reference/" variant="secondary">API</Button>
<CardGrid slot="aside" columns={2}>
<StatCard label="Operators">200+</StatCard>
<StatCard label="Op types">53</StatCard>
<StatCard label="Models">40+</StatCard>
<StatCard label="Paths">4</StatCard>
</CardGrid>
<CodeBlock
slot="media"
language="bash"
label="Install"
code={'npm install @example/kernels'}
/>
</Hero>

With no side column and no ground, the same part is the lede on its own measure: a section opener rather than a front door. The lede here is the summary slot rather than the prop, which is what a claim carrying bold or inline code needs; the slot wins wherever both are set.

<Hero eyebrow> with the summary slot

Design system

Parts, not pages.

Every part on this page is composed from the same tokens, so a site adopts the theme rather than a stylesheet: the recipes live in recipes.css and the site writes none of them.

Show code
<Hero titleAs="h3" eyebrow="Design system">
<Fragment>Parts, not <em>pages</em>.</Fragment>
<Fragment slot="summary">
Every part on this page is composed from the same tokens, so a site
adopts **the theme** rather than a stylesheet: the recipes live in
`recipes.css` and the site writes none of them.
</Fragment>
<Button slot="actions" href="/helia-ui/foundations/">Foundations</Button>
<Button slot="actions" href="/helia-ui/cards/" variant="secondary">Cards</Button>
</Hero>

An API reference is generated, not written, and it is generated for four languages. The extractors differ, the model they produce does not, and these parts render the model: the same header, the same table, the same columns for a Python function, a C function and a TypeScript function. Everything below comes from one hand-written model in src/lib/reference-gallery-model.ts.

RefSymbol, Python

functionSince 0.8

Run a model on a connected target and return a typed collection of measurements.

src/helia/profiler.py:48

profile_model(
model: str | Path,
*,
board: str,
timeout_s: float = 30.0,
) -> ProfileResult
Parameters of profile_model
NameTypeDefaultDescription
modelstr | PathRequiredPath to the model artifact to profile.
boardstrRequiredTarget board identifier used by the active probe.
timeout_sfloat30.0Maximum time to wait for the target to complete.
Show code
<RefSymbol {...symbolProps(REFERENCE_EXAMPLES.python)} level={3}>
<RefSection title="Parameters">
<RefParams
caption="Parameters of profile_model"
density="compact"
rows={paramRows(REFERENCE_EXAMPLES.python)}
/>
</RefSection>
</RefSymbol>

RefSymbol, C

functionSince 0.8

Run the same operation with caller-owned configuration and result structures.

include/profile.h:112

profile_status_t profile_model(
const profile_config_t *config,
profile_result_t *result
);
Parameters of profile_model
NameTypeDefaultDescription
configconst profile_config_t *Required · inProfiling configuration. The caller retains ownership.
resultprofile_result_t *Required · outReceives measurements and execution metadata.
Show code
<RefSymbol {...symbolProps(REFERENCE_EXAMPLES.c)} level={3}>
<RefSection title="Parameters">
<RefParams
caption="Parameters of profile_model"
density="compact"
rows={paramRows(REFERENCE_EXAMPLES.c)}
/>
</RefSection>
</RefSymbol>

RefSymbol, TypeScript

function

profileModel

TypeScript

Run the same operation from the browser client against a gateway.

src/client/profile.ts:31

function profileModel(
model: string | URL,
options: ProfileOptions,
): Promise<ProfileResult>
Parameters of profileModel
NameTypeDefaultDescription
modelstring | URLRequiredWhere the model artifact can be fetched from.
optionsProfileOptions{}Board, measurements, and the gateway to dispatch to.
Show code
<RefSymbol {...symbolProps(REFERENCE_EXAMPLES.typescript)} level={3}>
<RefSection title="Parameters">
<RefParams
caption="Parameters of profileModel"
density="compact"
rows={paramRows(REFERENCE_EXAMPLES.typescript)}
/>
</RefSection>
</RefSymbol>

A generated module page carries more symbols than a table of contents will show, so it indexes itself; a site that builds its own sidebar takes the same tree as nested links.

The rest of the Astro parts, one example each. They are documented in depth on their own pages; they are here so that one page answers what the package can draw.

<CodeTabs tabs={[...]} />

const average = total / samples.length;
Show code
<CodeTabs
ariaLabel="Average latency implementation"
tabs={[
{
label: 'TypeScript',
language: 'typescript',
code: 'const average = total / samples.length;',
},
{
label: 'Python',
language: 'python',
code: 'average = total / len(samples)',
},
]}
/>

<AsciiTerminal lines={[...]} />

Expected output
$ npm run build Resolving configuration… ENTRY src/index.ts TARGET es2022 ! no accent color set x missing tsconfig path alias ✓ Build complete
Show code
<AsciiTerminal
title="Expected output"
lines={[
{ kind: 'command', text: 'npm run build' },
{ kind: 'muted', text: 'Resolving configuration…' },
{ kind: 'output', text: ' ENTRY src/index.ts' },
{ kind: 'output', text: ' TARGET es2022' },
{ kind: 'warning', text: ' ! no accent color set' },
{ kind: 'error', text: ' x missing tsconfig path alias' },
{ kind: 'success', text: '✓ Build complete' },
]}
/>

<AsciiTerminal lines={imported} />

From a module
$ npm run docs:build Reading what the parts stated ROUTES 26 renditions written
Show code
<AsciiTerminal title="From a module" lines={modelTranscript} />

<Callout title tone>

Show code
<div className="helia-callout-stack">
<Callout title="Keep the calibration set">
The converter writes it beside the artifact, so the next run starts from
the same numbers.
</Callout>
<Callout tone="warning" title="Density is inherited">
A part that names its own step opts out of the hook and keeps it.
</Callout>
</div>

<Timeline groups={[...]} />

What's new

  1. Week two

    The gallery shows its own source

    Every example carries the MDX that renders it.

  2. Week one

    Content-first cards landed

Show code
<Timeline
heading="What's new"
groups={[
{
label: 'Week two',
items: [
{
title: 'The gallery shows its own source',
description:
'Every example carries the MDX that renders it.',
},
],
},
{
label: 'Week one',
items: [{ title: 'Content-first cards landed' }],
},
]}
/>

<AccordionGroup items={[...]} />

When does a variant earn a place here?

When it is a modifier on a part rather than a part of its own.

Where are the reference tables?

On the page for the part, not on this one.

Show code
<AccordionGroup
items={[
{
title: 'When does a variant earn a place here?',
content:
'When it is a modifier on a part rather than a part of its own.',
},
{
title: 'Where are the reference tables?',
content: 'On the page for the part, not on this one.',
},
]}
/>

<EditorialBand tone="paper">

Chapter

A band, not a card

No border, no radius, no shadow: a chapter-level section.

Show code
<EditorialBand tone="paper">
<SectionHeader
eyebrow="Chapter"
title="A band, not a card"
description="No border, no radius, no shadow: a chapter-level section."
/>
</EditorialBand>

<SectionHeader eyebrow title description href>

Parts

Everything the package draws

One row above a section, with the link that leaves it.

All contracts
Show code
<SectionHeader
eyebrow="Parts"
title="Everything the package draws"
description="One row above a section, with the link that leaves it."
href="/helia-ui/reference/astro-parts/"
linkLabel="All contracts"
/>

<DataTable caption columns rows />

Card tones
ToneWhat stands in for the edge
elevatedA shadow
outlinedA hairline border
filledA muted fill
ghostNothing, until the pointer arrives
Show code
<DataTable
caption="Card tones"
columns={['Tone', 'What stands in for the edge']}
rows={[
['elevated', 'A shadow'],
['outlined', 'A hairline border'],
['filled', 'A muted fill'],
['ghost', 'Nothing, until the pointer arrives'],
]}
/>

<MediaEmbed title videoId />

1:24
The player is not requested until the visitor presses play.Watch on YouTube ↗
Show code
<MediaEmbed
title="YouTube embed sample"
videoId="M7lc1UVf-VE"
caption="The player is not requested until the visitor presses play."
duration="1:24"
/>

<Eyebrow>

Section label

Inline label
Show code
<Eyebrow>Section label</Eyebrow>
<Eyebrow as="span">Inline label</Eyebrow>

<Chip tone size href>

NeutralAccentStaticLinkedMedium

Medium static

Show code
<div className="helia-badge-row">
<Chip>Neutral</Chip>
<Chip tone="accent">Accent</Chip>
<Chip tone="static">Static</Chip>
<Chip href="/helia-ui/gallery/#other-parts">Linked</Chip>
<Chip size="md">Medium</Chip>
<Chip size="md" tone="static">
Medium static
</Chip>
</div>

<Button variant size>

Show code
<div className="helia-display-row">
<Button href="/helia-ui/gallery/#other-parts">Primary</Button>
<Button href="/helia-ui/gallery/#other-parts" variant="secondary">
Secondary
</Button>
<Button href="/helia-ui/gallery/#other-parts" variant="ghost">
Ghost
</Button>
<Button href="/helia-ui/gallery/#other-parts" size="sm">
Primary, small
</Button>
<Button
href="/helia-ui/gallery/#other-parts"
variant="secondary"
size="sm"
>
Secondary, small
</Button>
<Button href="/helia-ui/gallery/#other-parts" variant="ghost" size="sm">
Ghost, small
</Button>
</div>

<Badge tone size dot>

NeutralInfoSuccessWarningDangerAccentNeutral, medium

Info, medium

With a dot

Show code
<div className="helia-badge-row">
<Badge>Neutral</Badge>
<Badge tone="info">Info</Badge>
<Badge tone="success">Success</Badge>
<Badge tone="warning">Warning</Badge>
<Badge tone="danger">Danger</Badge>
<Badge tone="accent">Accent</Badge>
<Badge size="md">Neutral, medium</Badge>
<Badge size="md" tone="info">
Info, medium
</Badge>
<Badge size="md" tone="success" dot>
With a dot
</Badge>
</div>

<Icon name text size />

Show code
<div className="gallery-stack">
<div className="helia-display-row">
<Icon name="gauge-high" text="gauge-high" size="sm" />
<Icon name="memory" text="memory" size="sm" />
<Icon name="microchip" text="microchip" size="sm" />
</div>
<div className="helia-display-row">
<Icon name="gauge-high" text="gauge-high" size="md" />
<Icon name="memory" text="memory" size="md" />
<Icon name="microchip" text="microchip" size="md" />
</div>
<div className="helia-display-row">
<Icon name="gauge-high" text="gauge-high" size="lg" />
<Icon name="memory" text="memory" size="lg" />
<Icon name="microchip" text="microchip" size="lg" />
</div>
<div className="helia-display-row">
<Icon name="gauge-high" />
<Icon name="memory" />
<Icon name="microchip" />
<Icon name="chart-line" />
<Icon name="circle-info" />
<Icon name="arrow-right" />
</div>
</div>

Standalone plots keep the same separation as other prose blocks. A chart group owns the spacing between its plots.

BuildSize
Example24

Size by build

Illustrative size units

05101520Example

First grouped plot

05101520Example

Second grouped plot

051015Example

Planned before deployment

A feature row can explain a capability without linking its whole surface.