Skip to content

Latest commit

 

History

History
111 lines (85 loc) · 5.99 KB

File metadata and controls

111 lines (85 loc) · 5.99 KB

Layers

Layers

Modals are just async functions you forgot to await.

Headless layer/stack manager — modals, dialogs, drawers, popovers, toasts are layers in named stacks. Open any layer from anywhere and await a typed result. A zero-dependency core plus React, Preact, Solid, Angular, Vue, Lit, Alpine, and Svelte adapters. State coordination, not UI ownership: Layers owns ordering, keys, transitions, blockers, and the await client.open(...) contract; you own rendering, focus, portals, and a11y.

core bundle size

Experimental — the API may change between minor releases. Pin your version. (Stability & versioning)

Full docs: stainless-code.com/layers.

Packages

Package Peer Install
@stainless-code/layers bun add @stainless-code/layers
@stainless-code/react-layers react bun add @stainless-code/react-layers
@stainless-code/preact-layers preact bun add @stainless-code/preact-layers
@stainless-code/solid-layers solid-js bun add @stainless-code/solid-layers
@stainless-code/angular-layers @angular/core bun add @stainless-code/angular-layers
@stainless-code/vue-layers vue bun add @stainless-code/vue-layers
@stainless-code/lit-layers lit, @lit/context bun add @stainless-code/lit-layers
@stainless-code/alpine-layers alpinejs bun add @stainless-code/alpine-layers
@stainless-code/svelte-layers svelte bun add @stainless-code/svelte-layers
@stainless-code/layers-devtools — (Solid panel) bun add -d @stainless-code/layers-devtools
@stainless-code/react-layers-devtools react, @stainless-code/react-layers, @tanstack/react-devtools bun add -d @stainless-code/react-layers-devtools

Install only the adapter for your framework — it pulls the core in transitively and re-exports it, so adapter APIs (StackProvider, useStack, …) and core APIs (LayerClient, layerOptions, …) both come from the one package. Each adapter lists its framework as a required peer. Svelte ships two entries: @stainless-code/svelte-layers (runes, 5.7+) and @stainless-code/svelte-layers/store (stores, 3+). Devtools packages are optional; see Devtools.

Taste (React)

import {
  layerOptions,
  StackProvider,
  StackOutlet,
  useLayer,
  type LayerComponentProps,
} from "@stainless-code/react-layers";

type ConfirmPayload = { title: string };
type ConfirmResponse = boolean;

function ConfirmDialog({
  call,
  payload,
}: LayerComponentProps<ConfirmPayload, ConfirmResponse>) {
  return (
    <div role="dialog">
      <h2>{payload.title}</h2>
      <button onClick={() => void call.end(true)}>Yes</button>
      <button onClick={() => void call.end(false)}>No</button>
    </div>
  );
}

const confirm = layerOptions<ConfirmPayload, ConfirmResponse>({
  stack: "confirm",
  key: ["confirm", "remove"],
  component: ConfirmDialog,
});

function App() {
  return (
    <StackProvider>
      <StackOutlet stack="confirm" />
    </StackProvider>
  );
}

function useRemove() {
  const c = useLayer(confirm);
  return async () => {
    const ok = await c.open({ title: "Remove?" });
    //    ^? boolean
  };
}

Docs

Concepts

  • useLayer(options) — wired handle (drive + observe). useLayerState / useLayerQueuedState / useQueuedStack — observe-only. Core createLayer(options, client) for headless callers. See Concepts.

Develop

This is a bun workspaces monorepo; root scripts fan out across packages with bun run --filter '*' <script>.

bun install
bun run check          # build (core-first) + format + lint + test + test:dom + typecheck

See .github/CONTRIBUTING.md to contribute and AGENTS.md for agent instructions.

License

MIT.