# Layer Provider

## Usage

Layer utilities provide the app-level provider used by overlay systems. Use `LayerProvider` at the app root for toast/layer configuration; use higher-level `Popover`, `HoverCard`, or `Tooltip` APIs for most overlay UI. Rendered layer content, not the provider's application subtree, uses theme body text defaults and exits ancestor surface/group membership. Establish intentional groups and complete required providers inside each layer. Every anchored layer keeps a gutter from each viewport edge — the spacing-4 step or the device safe-area inset, whichever is larger — and is capped to the viewport, never to the room beside its trigger. An app that floats a persistent bar over a viewport edge declares it once as `inset` on `LayerProvider` (`blockStart`, `blockEnd`, `inlineStart`, `inlineEnd`); each edge adds to that edge's gutter for every anchored layer and moves the toast viewport by the same amount, and defaults to zero. The inset is app configuration, not a theme value.

```ts
import { LayerProvider } from '@astryx-vue/core/LayerProvider'
```

`toast` takes `position` (the toast viewport corner), `maxVisible` (how many toasts are on screen at once), and its own `inset`, which overrides the provider inset per edge for toasts only.

Nested `LayerProvider` instances never open a second toast viewport: the outer one stays in charge of toasts. One that declares its own `inset`, though, narrows that inset for the anchored layers in its subtree.

## Best practices

| Guidance | Practices |
| --- | --- |
| Do | Declare a persistent bar floating over the viewport once, as `inset` on `LayerProvider`; every anchored layer and toast then stays clear of it. |
| Do | Use `LayerProvider` once near the app root when you need shared toast/layer configuration. |
| Do | Build on higher-level components like `Popover`, `HoverCard`, and `Tooltip` for common overlay patterns. |
| Don't | Add nested `LayerProvider` instances for anything but a subtree that declares its own `inset`: they add depth without a second toast viewport. |

## Examples

Common configurations, variations, and states.

### LayerProvider — Toast Viewport

Pin the toast viewport to the top end, cap it at two toasts, and push it down by 8px so it clears a bar floating over the top edge.

```vue
<script setup lang="ts">
import { LayerProvider } from '@astryx-vue/core/LayerProvider'
import { ToastViewport, useToast } from '@astryx-vue/core/Toast'

const toast = useToast()

// Pin the toast viewport to the top end, keep two on screen, and clear the top edge by 8px.
const toastConfig = {
  position: 'top-end' as const,
  maxVisible: 2,
  inset: { blockStart: 8 },
}

function showToasts() {
  toast({ body: 'Draft saved.', type: 'success' })
  toast({ body: 'Syncing 3 files…' })
  toast({ body: 'Storage is nearly full.', type: 'warning' })
}
</script>

<template>
  <div class="layer-provider-preview">
    <LayerProvider :toast="toastConfig">
      <button class="layer-provider-preview__trigger" type="button" @click="showToasts">
        Show toasts
      </button>
      <ToastViewport />
    </LayerProvider>
  </div>
</template>
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `toast` | `LayerToastConfig` | — | Toast viewport configuration: `position`, `maxVisible`, and a toast-only `inset` that overrides the provider inset per edge for toasts shown through `useToast()`. |
| `inset` | `LayerInset` | every edge `0` | A persistent bar floating over a viewport edge, declared once: `blockStart`, `blockEnd`, `inlineStart`, `inlineEnd` as pixel numbers or CSS lengths. Each edge adds to the gutter every anchored layer keeps from that edge and moves the toast viewport by the same amount. |

## Slots

| Slot | Description |
| --- | --- |
| `default` | Application subtree that can use the shared layer context. |

## LayerToastConfig

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `position` | `ToastPlacement` | `'bottom-end'` | Corner the toast viewport sits in: `top-start`, `top-center`, `top-end`, `bottom-start`, `bottom-center`, or `bottom-end`. A `placement` on `ToastViewport` still wins. |
| `maxVisible` | `number` | no limit | How many toasts stay on screen at once. When more are queued, only the newest ones render. |
| `inset` | `LayerInset` | — | Per-edge offset for the toast viewport only. An edge written here replaces the provider `inset` for that edge; edges left out keep the provider value. |

## LayerInset

| Field | Type | Description |
| --- | --- | --- |
| `blockStart` | `number \| string` | Offset added to the gutter at the top edge. A number is pixels; a string is any CSS length, such as `'4rem'` or `'env(safe-area-inset-top, 0px)'`. |
| `blockEnd` | `number \| string` | Same, for the bottom edge. |
| `inlineStart` | `number \| string` | Same, for the inline-start edge. |
| `inlineEnd` | `number \| string` | Same, for the inline-end edge. |

## Exports

| Export | Type | Description |
| --- | --- | --- |
| `useLayerConfig` | `() => ComputedRef \| null` | The nearest provider configuration, or `null` outside one. |
| `useLayerGutter` | `() => ComputedRef` | Distance an anchored layer keeps from each viewport edge: the larger of the spacing-4 step and the device safe area, plus the provider inset. |
| `resolveInset` | `(inset?: LayerInset) => ResolvedLayerInset` | Turns an inset into pixels. |
| `mergeInset` | `(primary?: LayerInset, fallback?: LayerInset) => ResolvedLayerInset` | Merges two insets edge by edge: an edge set on `primary` wins, the rest come from `fallback`. |

## Native attributes

The component renders no element of its own, so <code>class</code> and <code>style</code> are not forwarded.
