Solid
Solid adapter — LayerClientContext, signal accessors, StackOutlet.
@stainless-code/solid-layers bridges stacks into Solid signals via from. The core is re-exported.
Install
npm install @stainless-code/solid-layerspnpm add @stainless-code/solid-layersyarn add @stainless-code/solid-layersbun add @stainless-code/solid-layersPeer: solid-js >=1.6.0
Client
Provide a LayerClient through LayerClientContext. Read it with useLayerClient():
import {
LayerClientContext,
LayerClient,
StackOutlet,
useLayerClient,
} from "@stainless-code/solid-layers";
const client = new LayerClient();
function App() {
return (
<LayerClientContext.Provider value={client}>
<StackOutlet stack="confirm" />
</LayerClientContext.Provider>
);
}
createStackHook also returns a bound StackProvider when you want a single-stack factory.
Render a stack
StackOutlet renders registered components with keyed Dynamic updates. For render-prop subscriptions, use StackSubscribe.
Confirm dialog
import {
layerOptions,
LayerClientContext,
LayerClient,
StackOutlet,
useLayer,
type LayerComponentProps,
} from "@stainless-code/solid-layers";
type ConfirmPayload = { title: string };
type ConfirmResponse = boolean;
function ConfirmDialog(props: LayerComponentProps<ConfirmPayload, ConfirmResponse>) {
return (
<div role="dialog">
<h2>{props.payload.title}</h2>
<button onClick={() => void props.call.end(true)}>Yes</button>
<button onClick={() => void props.call.end(false)}>No</button>
</div>
);
}
const confirm = layerOptions<ConfirmPayload, ConfirmResponse>({
stack: "confirm",
key: ["confirm", "remove"],
component: ConfirmDialog,
});
const client = new LayerClient();
function RemoveButton() {
const c = useLayer(confirm);
return (
<button
onClick={() => void c.open({ title: "Remove item?" })}
>
Remove
</button>
);
}
function App() {
return (
<LayerClientContext.Provider value={client}>
<StackOutlet stack="confirm" />
<RemoveButton />
</LayerClientContext.Provider>
);
}import {
layerOptions,
LayerClientContext,
LayerClient,
StackOutlet,
useLayer,
} from "@stainless-code/solid-layers";
function ConfirmDialog(props) {
return (
<div role="dialog">
<h2>{props.payload.title}</h2>
<button onClick={() => void props.call.end(true)}>Yes</button>
<button onClick={() => void props.call.end(false)}>No</button>
</div>
);
}
const confirm = layerOptions({
stack: "confirm",
key: ["confirm", "remove"],
component: ConfirmDialog,
});
const client = new LayerClient();
function RemoveButton() {
const c = useLayer(confirm);
return (
<button
onClick={() => void c.open({ title: "Remove item?" })}
>
Remove
</button>
);
}
function App() {
return (
<LayerClientContext.Provider value={client}>
<StackOutlet stack="confirm" />
<RemoveButton />
</LayerClientContext.Provider>
);
}Primitives
Options bag plus optional trailing LayerClient. Drive with useLayer(options); observe with useLayerState({ key, … }). Solid-idiomatic aliases: createStack, createQueuedStack, createLayerState, createLayerQueuedState.
| Export | Role |
|---|---|
useStack({ stack?, select?, compare? }, client?) |
Accessor<T> of the selected stack slice |
useQueuedStack({ stack?, select?, compare? }, client?) |
Queued snapshot accessor |
useLayer(options, client?) |
Drive — wired handle accessors + open() / dismiss() + reactive state / queued / top |
useLayerState({ key, stack?, select?, compare? }, client?) |
Observe — Accessor<LayerState[]> for mounted same-key layers |
useLayerQueuedState({ key, stack?, select?, compare? }, client?) |
Observe — queued same-key layers |
Read accessors with () — e.g. useStack({ stack: "confirm" })().
Ergonomic APIs
| Export | Role |
|---|---|
useStackHandles(stack?, rootProps?) |
{ states: Accessor, getCall } for headless rendering |
StackSubscribe |
Render-prop with Accessor<T> child argument |
useMutationFlow(call) |
pending is an Accessor<boolean>; run(fn).orEnd(response) |
useLayerGroup(call, options?) |
Child stack with Outlet component |
createStackHook(config?) |
StackProvider, useAppStack, AppHost, AppLayer |