@astryxdesign/lab
Experimental Astryx components — published to npm only under the @canary dist-tag for early testing; never released as a stable (latest) version.Experimental Astryx components. This package is a staging area for components being developed before graduating to
@astryxdesign/core. It ships to npm only under the @canary dist-tag — there is never a stable (latest) release.Purpose
Components in lab:
- Are importable in storybook and sandbox for testing
- Are publishable for early external testing via the
@canarytag only - Can be iterated on freely without worrying about breaking stable consumers
- Compose with
@astryxdesign/corecomponents (use the theme, follow naming conventions) - Graduate to
@astryxdesign/coreafter thorough engineering review
See the Component Lifecycle wiki for how a component moves from lab → core (and the promotion gates), and the Component Hardening Protocol for the bar a component must clear to graduate.
What's here vs what's in core
Lab: Works, has basic props, maybe has stories. API might change. Not accessibility-hardened, not vibe-tested, not fully themed. Canary-only — no stability promise.
Core: Full keyboard/a11y, hover guards, theming story, status states, spec compliance, vibe tested. Shipped to consumers on
latest.Promotion gate: accessibility
The Accessibility Checklist is a hard requirement for graduating to core — every item, verified in the promotion PR, alongside the hardening bar linked above.
Lab components get the same scan coverage as core (the
pr-a11y axe audit and the weekly full scan run against lab too), but a11y findings on a lab component do not block lab merges — they block promotion. Iterate freely in lab; clear the checklist to graduate.Usage
Inside the monorepo (storybook/sandbox), imports resolve via pnpm workspaces:
tsximport {CodeEditor} from '@astryxdesign/lab';
Trying lab components in your own project (canary)
Lab is published only under the
@canary dist-tag, so you must request that tag explicitly. There is no latest version to install.bashnpm install @astryxdesign/lab@canary @astryxdesign/core@canary
tsximport {CodeEditor} from '@astryxdesign/lab';import '@astryxdesign/core/astryx.css';import '@astryxdesign/lab/lab.css';
Canary builds track the latest commit onmain(0.x.y-canary.<sha>). They can break between any two versions — pin an exact version if you need stability.
Documenting a Lab component (canary docsite)
Lab appears only on the canary docsite — the production site documents the published stable release and never loads this package (see the target gates in
apps/docsite/scripts/ and the exclusion tests in apps/docsite/src/__tests__/integration-targets.test.ts).Authoring is the same two-artifact flow a Core author uses; the only difference is where the runnable demos live (Core keeps its blocks centrally in
packages/cli/assets/templates/blocks/, Lab owns its own blocks/ directory here):- Component doc —
src/<Name>/<Name>.doc.mjsexportingdocs(props, usage, playground config,examples). Picked up automatically on canary; no registration anywhere. - Runnable demos — same-stem pairs in
blocks/:<BlockName>.tsx+<BlockName>.doc.mjs(aTemplateDocstampedtype: 'block'). Discovered automatically once this package declares the directory — nothing per-component. The docsite renders the pair as the component page's showcase/examples and the playground can import anything the package exports.
This package declares that directory once:
templates: './blocks' in astryx.integration.mjs, and "blocks" in the files list in package.json. A new demo is just its block pair.How a demo reaches a component page:
exampleFor: '<Component>' (or alsoExampleFor) is what attaches a block — the page renders every block attributed to it, whatever the block is named. The block's name is the demo's display name; component-doc example labels are CLI-snippet headings. The two are independent mechanisms.Use these conventions for new demos:
- Give the block descriptor the same
nameas the component doc's examplelabel, so the snippet and its runnable demo read as one documented set (this naming convention is what theexample-coveragereport keys on — it is not how the docsite attaches demos). - Exactly one attributed block sets
isShowcase: true(the hero demo — conventionally the first example). displayNameanddescriptionare required by the docsite build; setcomponentsUsedandaspectRatiofor the gallery.
A doc example with no corresponding block exists only as a CLI/code snippet — the docsite page's demos come solely from blocks. Note the converse does not follow from names alone: an example label with no same-named block does not by itself mean the demo is missing, because the component may render demos under other names (several Core components do). The
example-coverage docsite test output reports both sides of that pairing; it is a report, not a gate — Core has the same non-guarantee, and whether pairing should gate CI is an open repo-wide decision.Note:astryx integration add templatescaffolds a./templatesroot for a package that declares none. Declaretemplates: './blocks'explicitly instead, matching charts and richtext; unifying the two conventions is a pending repo decision.
Why no stable release?
package.json keeps "private": true plus an "astryx": { "canaryOnly": true } marker. The release workflow's stable (latest) job skips both private and canaryOnly packages, while the canary job strips private in its ephemeral CI checkout only (never in git) to publish the @canary tag. The committed private: true is npm's hard guarantee that no stable publish can ever happen — do not remove it.