Getting started

Truss UI is a Svelte 5 design system for SvelteKit apps. It borrows Material 3's tonal colour, surfaces and rounding and Blueprint's density, 32px controls and hairline structure, and implements them with its own tokens, components and icons. The core has no runtime dependencies besides Svelte.

Install

npm install @ruckc/truss-ui

Optional companions, each a separate package so you only pay for what you use:

npm install @ruckc/truss-chart   # SVG charts            (no dependencies)
npm install @ruckc/truss-graph   # node/edge editor      (no dependencies)
npm install @ruckc/truss-ol ol   # OpenLayers map        (peer: ol)

@ruckc/truss-graph and @ruckc/truss-ol use the core's buttons and tokens, so they list @ruckc/truss-ui as a peer dependency. All packages require Svelte 5.20 or newer.

Add the styles

Import the stylesheet once, in your root layout. It includes the design tokens, base styles and the bundled Inter and JetBrains Mono variable fonts (Latin subset). The font files are referenced by relative URL, so your app's own bundler hashes and serves them: nothing is fetched from a CDN.

<script lang="ts">
  import '@ruckc/truss-ui/styles.css';
  import { Toaster, DialogHost } from '@ruckc/truss-ui';
  let { children } = $props();
</script>

{@render children()}
<Toaster />
<DialogHost />

Prefer your own typeface? Import @ruckc/truss-ui/tokens.css and @ruckc/truss-ui/base.css instead of styles.css (tokens and element defaults, no fonts) and set --tr-font-sans. See Theming for the full split.

Use components

<script lang="ts">
  import { Button, Input, Select, DatePicker, toasts } from '@ruckc/truss-ui';
  let name = $state('');
  let when = $state<string>();
</script>

<Input label="Name" bind:value={name} />
<DatePicker label="Due" bind:value={when} />
<Button onclick={() => toasts.success(`Saved ${name}`)}>Save</Button>

Values are plain strings, numbers and arrays; dates travel as YYYY-MM-DD and date-times as YYYY-MM-DDTHH:MM (local, no timezone), so they sort and serialise without surprises. Most components take bind:value; callbacks are ordinary on… props.

Dark mode

The theme follows the operating system. Force one with data-theme on <html>:

document.documentElement.dataset.theme = 'dark';   // or 'light'; delete it to follow the OS

The Shell component manages this for you through bind:theme.

Snippets, not slots

Content props such as children, header, footer, actions and cell are Svelte 5 snippets:

<DataTable caption="Hosts" {columns} {rows} rowKey={(r) => r.id}>
  {#snippet cell(row, col)}
    {#if col.key === 'status'}<Badge intent="success">{row.status}</Badge>{:else}{row[col.key]}{/if}
  {/snippet}
</DataTable>

Next

/docs/getting-started Truss UI · MIT