sveltelean
Versionv0.2.0 GitHub

No JavaScript dialog

We do not build a JavaScript dialog when <dialog> is sufficient. The browser provides the modal top layer, page inertness, Escape, focus return and the backdrop; an open-state controller, a focus trap and a portal would duplicate them and add a dependence on hydration. Enforced by the dialog contract's "What the package does not do" section and by the native-only fixture, whose production build emits a Svelte Lean chunk of 0 B.

No listener per instance

We do not create one event listener per primitive instance by default. A Tier 1 behavior installs one listener per event type on the document runtime and routes along composedPath(); a thousand tabs roots keep one click and one keydown. Enforced by the forbidden changes, by tabs.test.ts and by the release gate in listeners.spec.ts, which counts listeners two independent ways for 1 and 1000 roots.

No MutationObserver discovery

We do not use a generic MutationObserver to discover primitives or run their lifecycle. A root inserted later is found by the router on its first event, so the observer would only add work on every unrelated DOM update and eager controllers for untouched instances. Enforced by ADR 0004, by tests that mount roots after registration, and by the audit command grep -rn MutationObserver packages/*/src, which returns nothing (audit).

No mirrored native state

We do not mirror native browser state into Svelte state or stores without a reason. open, checked, disabled and focus already exist in the DOM; a copy creates synchronization work and a second value that can be wrong. Tabs keep their selection in aria-selected, tabindex and hidden, and the behavior source contains no WeakMap, which its unit test asserts. The table's state object is application state by design, not a mirror.

No Provider

We do not require a Provider because other libraries have one. Theme lives in CSS tokens on the root; the runtime attaches to the document; there is no context to wrap the application in and no .svelte file in the runtime packages. Enforced by the forbidden changes and the audit command grep -rni provider packages/*/src, which returns nothing.

No positioning engine

We do not ship a positioning engine when CSS anchor positioning and the invoker's implicit anchor solve the case. Popovers are placed by position-area in the stylesheet; where the browser lacks it, the popover keeps the platform's default placement, and that fallback is documented rather than hidden. No package has a positioning dependency (grep -rni floating-ui packages/*/src returns nothing).

No forced virtualization

We do not force virtualization onto small tables, and we do not turn every cell into a persistent component. <DataTable /> renders a native <table>; virtual rows are a future, optional entry point and are not shipped today. Supporting a feature does not mean shipping it: grouping, pivot, clipboard, export, server data and persisted state stay out of the bundle until imported, which the table-basic fixture asserts.

No hidden runtime cost

We do not hide runtime cost. Every primitive page carries a runtime block with its tier, its shared listeners and its measured behavior JavaScript, read from the contract and the size file; the tabs registration including the shared kernel is 1521 B brotli. The proof page reads the listeners of the page you are on, and every number on the site comes from a committed measurement file or reads "not measured".

Also not

  • No random ids for ARIA relationships; ids are authored, so server output is correct.
  • No document or window access at module evaluation; every entry imports under Node.
  • No eval, no new Function, no string-to-code attributes; a strict Content Security Policy has nothing to object to in the packages.
  • No Tailwind or CSS-in-JS dependency in any package.
  • No production dependency without a written reason why the platform is insufficient.
  • No root entry that registers every behavior; registration is a subpath and a side effect.
  • No rename of a protocol attribute, event, token or export without a deprecation window.

The full list, with the reasons, is the "Forbidden changes" section of AGENTS.md; the costs of these choices are on Trade-offs.