@archetypeai/ds-ui-svelte-labs
v0.17.0
Published
Archetype AI Design System Labs Primitives (experimental 0.x tier composing @archetypeai/ds-ui-svelte-console)
Readme
@archetypeai/ds-ui-svelte-labs
Labs primitives of the Archetype AI design system - the experimental 0.x tier built on top of the frozen @archetypeai/ds-ui-svelte-console base. Svelte 5 primitives styled with Tailwind v4 and tailwind-variants, wired to the @archetypeai/ds-lib-tokens theme, composing console primitives (Button, Card, Badge) where they need stable building blocks. TypeScript source ships as .svelte files (no precompilation) so consumers get full type-checking and IDE go-to-definition.
Labs is versioned 0.x: breaking changes are in-contract between minor versions. Components that prove themselves graduate toward console; console itself never changes to accommodate labs.
Like console, the labs flavor ships two ways from the same source:
- npm package (this document's default) - how apps consume primitives: they stay in
node_modules, imported per-subpath, updated by version bump. The package is the source of truth. - shadcn-svelte registry - how primitives get modified or extended: pull a primitive's editable source into your app, change it, then port the change back into the package.
Install
npm i @archetypeai/ds-ui-svelte-labs @archetypeai/ds-ui-svelte-consoleThen install the peer dependencies shared by all subpaths:
npm i svelte tailwindcss bits-ui tailwind-variants tailwind-merge clsx @lucide/svelte @archetypeai/ds-lib-tokensPer-subpath peer dependencies
The chart-family subpaths additionally require heavy visualization peers that the other subpaths never load (they are declared as optional peers, so npm does not auto-install them):
| Subpath | Extra peers |
|---|---|
| primitives/chart | layerchart |
| primitives/scatter-chart | layerchart, d3-scale |
| primitives/sensor-chart | layerchart, d3-scale, d3-shape |
npm i [email protected] d3-scale d3-shapelayerchart is pinned to an exact 2.0 pre-release - prerelease versions break APIs between builds, so install the pinned version (labs is 0.x - churn here is in-contract).
Tailwind v4 setup (mandatory)
Tailwind v4 does not scan node_modules by default. Without the @source directives below, every class in this package is purged at consumer build time and components render unstyled.
In your consumer's app.css, in this order:
@import 'tailwindcss';
@import '@archetypeai/ds-lib-tokens/theme.css';
@source "../node_modules/@archetypeai/ds-ui-svelte-console/dist";
@source "../node_modules/@archetypeai/ds-ui-svelte-labs/dist";Order matters:
tailwindcssregisters the engine.@archetypeai/ds-lib-tokens/theme.cssdeclares the CSS variables that component classes consume.- The two
@sourcedirectives make Tailwind scan both packages - labs components compose console primitives, so both dists must be scanned.
Adjust the @source paths if your app.css lives elsewhere - they must resolve to each package's dist/ directory.
TypeScript setup
In your consumer's tsconfig.json (or jsconfig.json), set:
{
"compilerOptions": {
"moduleResolution": "bundler"
}
}"node16" and "nodenext" also work. Without one of these, the types condition in this package's exports map is bypassed, types fall back to the default JS file, and editor features degrade.
Usage
Each primitive lives at its own subpath. There is no barrel import { Logo } from '@archetypeai/ds-ui-svelte-labs' - subpaths keep layerchart and the d3 packages out of bundles for consumers who never touch the chart primitives.
<script lang="ts">
import Logo from '@archetypeai/ds-ui-svelte-labs/primitives/logo'
import Menubar from '@archetypeai/ds-ui-svelte-labs/primitives/menubar'
import Slider from '@archetypeai/ds-ui-svelte-labs/primitives/slider'
let volume = $state(50)
</script>
<Menubar />
<Logo size="lg" />
<Logo variant="compact" />
<Slider type="single" bind:value={volume} max={100} />Per-primitive subpaths
| Primitive | Import path |
|---|---|
| AspectRatio | @archetypeai/ds-ui-svelte-labs/primitives/aspect-ratio |
| Chart | @archetypeai/ds-ui-svelte-labs/primitives/chart |
| Kbd | @archetypeai/ds-ui-svelte-labs/primitives/kbd |
| Logo | @archetypeai/ds-ui-svelte-labs/primitives/logo |
| Menubar | @archetypeai/ds-ui-svelte-labs/primitives/menubar |
| ScatterChart | @archetypeai/ds-ui-svelte-labs/primitives/scatter-chart |
| SensorChart | @archetypeai/ds-ui-svelte-labs/primitives/sensor-chart |
| Slider | @archetypeai/ds-ui-svelte-labs/primitives/slider |
| Switch | @archetypeai/ds-ui-svelte-labs/primitives/switch |
| Toggle | @archetypeai/ds-ui-svelte-labs/primitives/toggle |
| VideoPlayer | @archetypeai/ds-ui-svelte-labs/primitives/video-player |
Class-merging and element-ref type helpers re-export from console at @archetypeai/ds-ui-svelte-labs/primitives/utils (a single cn/twMerge instance exists in the tree), alongside the labs domain helpers (healthTier, formatMMSS, clamp).
Logo (primitives/logo)
Two artwork forms behind one component. variant="default" is the horizontal wordmark (~5.4:1);
variant="compact" is the stacked social/avatar lockup (~1.6:1) - use it where a wordmark will
not fit, such as square tiles, avatars, narrow sidebars and splash marks.
Both forms honour the same size scale - sm | default | lg maps to h-4 | h-6 | h-8 -
and take their width from w-auto, so swapping variants changes the rendered width, never the
height. Because of that, compact reads small at sm; prefer default or lg, or override with
class.
<Logo /> <!-- wordmark, h-6 -->
<Logo variant="compact" size="lg" /> <!-- stacked lockup, h-8 -->
<Logo variant="compact" class="h-16 w-auto" />Both forms are single inline SVGs coloured by currentColor (text-foreground by default), so
they invert with the theme and accept any text-* override. The accessible name is
"Archetype AI" for both; pass aria-label / role to override when the mark sits next to a
text logotype and would otherwise double-announce.
VideoPlayer (primitives/video-player)
The seek track doubles as a timeline. markers are named windows in seconds (not fractions of
the duration), drawn as focusable dots; clicking one expands it into a range pill, seeks to its
start and starts playback. One is expanded at a time, bind:activeMarker is its index, and
scrubbing by hand or clicking the video surface collapses it. While one is expanded the others step
out of the way entirely, pointer events included.
<VideoPlayer
src={clip}
bind:time
bind:duration
bind:activeMarker
markers={[{ start: 12, end: 18, label: 'Approach' }]}
highlights={brushedWindows}
controlsVisibility="always"
onMarkerHover={(index) => (hovered = index)}
/>controlsVisibility="always" is required whenever markers must stay clickable during playback: the
default "auto" fades the control bar, and the markers with it, 2.5s in. For linked brushing,
highlights tints regions another view is pointing at, and onMarkerHover reports the marker under
the cursor or the keyboard focus.
Two traps when src changes, both invisible from the type signature:
- A new
srcremounts the player, and Svelte's media bindings write your bound values into the fresh element — so resettime = 0andpaused = trueyourself, or a stale position becomes the next clip's start. bind:durationholds the previous clip's value untilloadedmetadata. Reseed it from a known length if marker geometry has to be right on the first frame; whiledurationis 0 every marker collapses onto the left edge.
Marker seeking also needs an origin that serves HTTP Range requests — against one that doesn't, seeks silently do nothing. Serve the clip from a blob URL instead.
Extending console primitives
Labs adapts console primitives without ever changing console, using this escape-hatch ladder (in order):
classprop overrides on the console componentdata-slotattribute selectors in consumer CSStv({ extend })on console's exported variant clusters- (rare) a labs wrapper component
This document is the source for the package README (copied by prepack); the full design-system docs live in the repository's readme.
