An open API service indexing awesome lists of open source software.

https://github.com/stainless-code/layers

Headless manager for modal/dialog/drawer/popover/toast UI — open any layer from anywhere, manage it as an ordered named stack, and optionally await a typed result. UI-agnostic core + React/Preact/Vue/Solid/Angular/Svelte adapters.
https://github.com/stainless-code/layers

angular dialog drawer headless modal monorepo overlay popover preact react solid stack state-management svelte toast typescript vue

Last synced: 1 day ago
JSON representation

Headless manager for modal/dialog/drawer/popover/toast UI — open any layer from anywhere, manage it as an ordered named stack, and optionally await a typed result. UI-agnostic core + React/Preact/Vue/Solid/Angular/Svelte adapters.

Awesome Lists containing this project

README

          

# 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.

> Experimental — the API may change between minor releases. Pin your version. ([Stability & versioning](https://stainless-code.com/layers/concepts/stability))

Full docs: [stainless-code.com/layers](https://stainless-code.com/layers).

## Packages

| Package | Peer | Install |
| ------------------------------------------------------------------ | ------------------------------------------------------------------- | -------------------------------------------------- |
| [`@stainless-code/layers`](packages/core) | — | `bun add @stainless-code/layers` |
| [`@stainless-code/react-layers`](packages/react) | `react` | `bun add @stainless-code/react-layers` |
| [`@stainless-code/preact-layers`](packages/preact) | `preact` | `bun add @stainless-code/preact-layers` |
| [`@stainless-code/solid-layers`](packages/solid) | `solid-js` | `bun add @stainless-code/solid-layers` |
| [`@stainless-code/angular-layers`](packages/angular) | `@angular/core` | `bun add @stainless-code/angular-layers` |
| [`@stainless-code/vue-layers`](packages/vue) | `vue` | `bun add @stainless-code/vue-layers` |
| [`@stainless-code/lit-layers`](packages/lit) | `lit`, `@lit/context` | `bun add @stainless-code/lit-layers` |
| [`@stainless-code/alpine-layers`](packages/alpine) | `alpinejs` | `bun add @stainless-code/alpine-layers` |
| [`@stainless-code/svelte-layers`](packages/svelte) | `svelte` | `bun add @stainless-code/svelte-layers` |
| [`@stainless-code/layers-devtools`](packages/devtools) | — (Solid panel) | `bun add -d @stainless-code/layers-devtools` |
| [`@stainless-code/react-layers-devtools`](packages/react-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](https://stainless-code.com/layers/guides/devtools).

## Taste (React)

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

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

function ConfirmDialog({
call,
payload,
}: LayerComponentProps) {
return (


{payload.title}


void call.end(true)}>Yes
void call.end(false)}>No

);
}

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

function App() {
return (



);
}

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

## Docs

- [Getting started](https://stainless-code.com/layers/guides/getting-started)
- [When to use Layers](https://stainless-code.com/layers/concepts/when-to-use)
- [Concepts](https://stainless-code.com/layers/concepts)
- [Adapters](https://stainless-code.com/layers/adapters)
- [Reference](https://stainless-code.com/layers/reference)
- [Changelog](https://stainless-code.com/layers/changelog)

## Concepts

- **`useLayer(options)`** — wired handle (drive + observe). **`useLayerState`** / **`useLayerQueuedState`** / **`useQueuedStack`** — observe-only. Core **`createLayer(options, client)`** for headless callers. See [Concepts](https://stainless-code.com/layers/concepts).

## Develop

This is a [bun workspaces](https://bun.sh/docs/install/workspaces) monorepo; root scripts fan out across packages with `bun run --filter '*' `.

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

See [`.github/CONTRIBUTING.md`](.github/CONTRIBUTING.md) to contribute and [`AGENTS.md`](AGENTS.md) for agent instructions.

## License

MIT.