sveltelean
Versionv0.2.0 GitHub

What Svelte Lean is

Two products and the infrastructure they share. Svelte Lean Primitives (@svelte-lean/primitives) covers the interaction patterns of an application: buttons, dialogs, popovers, disclosures, form controls, tabs, menus, listboxes and comboboxes. Svelte Lean Table (@svelte-lean/table) is a data table that renders a native <table> and grows into a data grid through separate entry points.

The starting question for every primitive is the same: what does the browser already know how to do? A <dialog> opened by an invoker command owns its top layer, page inertness, Escape and focus return, so the package owns nothing for it beyond styles, a contract and development validation. Tabs have no platform interaction, so one small behavior is registered once per page and driven by attributes in the markup.

The runtime therefore grows with the interaction, not with the number of components. A page that uses only native primitives ships 0 B of Svelte Lean behavior JavaScript in the production fixture that proves it; a page with tabs ships the tabs registration and the shared kernel, 1521 B brotli.

What it is not

  • Not a Tailwind component collection: the packages carry no CSS framework dependency.
  • Not a Radix port or a Headless UI clone: behavior is not modelled as a component instance with its own listeners and state.
  • Not a Web Components library: the markup is plain HTML that Svelte renders and hydrates.
  • Not a replacement for Svelte, and not a claim that Svelte's event model is slow. The advantage is the absence of unnecessary abstraction, not a faster framework.
  • Not anti-JavaScript. A correct combobox needs meaningful behavior code; the goal is the minimum necessary runtime, not zero runtime at any cost.

Who it is for

Teams that write markup and want the page to work before hydration and with client JavaScript disabled where the platform allows it. Applications on Svelte 5 and SvelteKit that render on the server, because every relationship in the markup uses authored ids and no state is generated at hydration. Projects that want to own their CSS and depend only on a maintained behavior engine.

It is a poorer fit for teams that prefer a component API for every interaction, or that need a primitive the platform does not yet cover well in their browser target. The trade-offs and the comparison pages say so in detail.

Two products

ProductPackageDescription
Svelte Lean Primitives@svelte-lean/primitivesNative-first primitives driven by a DOM protocol: 40 Tier 0 primitives with no runtime, 15 Tier 1 behaviors with one shared listener per event type and 5 Tier 2 behaviors with a lazy per-root controller.
Svelte Lean Table@svelte-lean/tableA data table for Svelte 5 that renders a native <table>, keeps its state in one plain object and adds capabilities through separate entry points.

The two products share code only where it is genuinely reusable, through @svelte-lean/core; the table is not built on the primitives' runtime and does not register behaviors (ADR 0006).

How behavior is shipped

Mode A, native only. Plain platform markup: a <dialog>, a popover, a <details>, native inputs. No package is required. The data-slean attributes on these elements are hooks for the optional stylesheet and for development validation; the browser owns the behavior.

Mode B, package-managed behavior. For tabs, menus, listboxes and comboboxes the markup carries a static marker such as data-slean="tabs". @svelte-lean/vite discovers the marker at build time and injects the matching registration module, so the production bundle contains the behaviors the markup uses and nothing else. A manual import '@svelte-lean/primitives/tabs/register' is the documented escape hatch and ships the same modules.

Mode C, owned styles. The stylesheet of a primitive is a plain CSS file that can be copied into the application and edited there; the behavior engine stays in the package so an accessibility fix reaches every project through npm. The slean add command that would automate the copy does not exist yet.

The three modes render the same behavior contract. The whole model, with the shipping invariants and how each one is tested, is on Distribution.

What exists today

Every package is at version 0.2.0: a preview, not published to npm. The repository is at release stage 0 with most of stage 1 in place, as recorded in docs/release.md on 2026-09-27. This section lists what exists; the release document lists what each stage requires, and nothing beyond it is promised.

PackageRoleDocumentation
@svelte-lean/primitivesContracts and types for all 60 primitives; 15 Tier 1 and 5 Tier 2 behaviors as side-effect register modules/primitives
@svelte-lean/table<DataTable />, createTable(), optional modules/table
@svelte-lean/stylesOptional CSS: tokens, base, one file per primitive/styling
@svelte-lean/viteBuild-time behavior discovery, manifest, build report/docs/architecture/build-time-discovery
@svelte-lean/coreBehavior registry, shared event router, DOM and keyboard helpers, diagnostics/docs/architecture/dom-protocol

Primitives: 40 native (Tier 0) primitives with no runtime, button, dialog, popover, disclosure, checkbox, switch, radio-group, date-field, input, field, segmented, rating, slider, otp-field, file-field, color-field, autocomplete, alert-dialog, drawer, accordion, card, separator, avatar, badge, tag, kbd, carousel, alert, progress, meter, spinner, skeleton, breadcrumb, pagination, steps, button-group, scroll-area, descriptions, timeline, empty; 15 delegated behaviors (Tier 1), each measured including the shared kernel, tabs (1521 B brotli), menu (1932 B brotli), listbox (1838 B brotli), calendar (3925 B brotli), toggle (888 B brotli), toggle-group (1569 B brotli), toolbar (1494 B brotli), range-slider (1291 B brotli), number-field (1082 B brotli), tree (1919 B brotli), tooltip (1297 B brotli), context-menu (1409 B brotli), file-drop (1107 B brotli), hover-card (1353 B brotli), menubar (1457 B brotli); 5 lazy scoped controller (Tier 2), combobox (2564 B brotli), date-picker (4912 B brotli), select (3362 B brotli), toast (1396 B brotli), splitter (1683 B brotli), whose per-root controller is created on the first interaction and released when focus leaves. Submenus are documented in the menu contract as not implemented; a command palette, a popconfirm and a multi-select dropdown are documented compositions of these primitives.

Table: <DataTable /> with sorting, search, column filters, pagination, selection, expansion, tree rows, pinning, resizing, visibility, inline editing and keyboard cell navigation as props; grouping, pivot, clipboard, CSV export, server data sources and persisted state as separate entry points; createTable() underneath. Virtual rows are not shipped.

Not yet, and therefore not claimed: Firefox and WebKit test runs, screen-reader smoke tests, a command-line tool. The claim registry lists every public claim with its evidence and status.

Where to start

  • Installation: packages, the Vite plugin, the stylesheets.
  • Primitives: every primitive with its tier and measured cost.
  • Table: the data table and its specimens.
  • Proof: the runtime of this site, read live.