# Presence

> Mounts and unmounts content with a real entrance and exit through one direction-aware transition, tracking opening/open/closing state, marking the panel inert while it closes, and firing lifecycle callbacks.

- Package: `fancy-ui-svelte` (Svelte 5 + Tailwind CSS v4)
- Category: Effects
- Tags: animation, presence, transition, mount, exit, micro-interaction
- Types: `PresenceProps`
- Docs: https://fancy-ui.rama.app/docs/components/presence
- Source: https://github.com/RamaHerbin/fancy-ui/tree/main/src/lib/fancy-ui/presence

## Import

```svelte
<script lang="ts">
  import { Presence } from 'fancy-ui-svelte';
</script>
```

Setup (once per project): `npm install fancy-ui-svelte`, then add `@import "fancy-ui-svelte/tailwind.css";` after `@import "tailwindcss";` in your main CSS file. Full guide: https://fancy-ui.rama.app/llms.txt

React: `import { Presence } from 'fancy-ui-react';` (`class` becomes `className`, snippets become `ReactNode`, DOM callbacks are camel-cased; exact names on https://fancy-ui.rama.app/docs/components/react/presence.md).

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `open` (required) | `boolean` | — | Whether the content is mounted and, once the entrance settles, visible |
| `preset` | `"fade" \| "fade-up" \| "fade-down" \| "fade-left" \| "fade-right" \| "scale" \| "blur" \| "zoom"` | `"fade"` | The entrance/exit look |
| `duration` | `number` | `300` | Entrance duration in ms |
| `exitDuration` | `number` | `200` | Exit duration in ms — shorter than the entrance by default; leaving reads faster than arriving |
| `delay` | `number` | `0` | Delay in ms before the entrance starts; applied to the exit too |
| `distance` | `number` | `16` | Entrance travel distance in px for the four directional presets — the exit travels half as far |
| `inert` | `boolean` | `true` | Whether the panel is inert while closing (Svelte already does this natively for any transitioning element — false is an explicit opt-out) |
| `onEnterEnd` | `() => void` | — | Fires once the entrance transition settles (onintroend) |
| `onExitEnd` | `() => void` | — | Fires once the exit transition settles (onoutroend) — not guaranteed if the component is destroyed mid-exit |
| `class` | `string` | — | Additional CSS classes, merged onto the root |
| `ref` | `HTMLDivElement \| null` | `null` | Bindable reference to the root element — null while closed |

## Snippets

| Snippet | Description |
| --- | --- |
| `children` | Panel content |

## Examples

### Basic Usage

```svelte
<script lang="ts">
	import { Presence } from "fancy-ui-svelte";
	import { Checkbox } from "fancy-ui-svelte";

	let agreed = $state(false);
</script>

<div class="flex w-full flex-col gap-2 p-6">
	<Checkbox bind:checked={agreed}>I agree to the terms and conditions</Checkbox>

	<Presence open={!agreed} duration={200} exitDuration={150}>
		<p class="text-destructive text-sm">You must agree before continuing.</p>
	</Presence>
</div>
```

### Presets

Switch between the entrance/exit looks.

```svelte
<script lang="ts">
	import { Presence } from "fancy-ui-svelte";
	import { Button } from "fancy-ui-svelte";

	const presets = ["fade", "fade-up", "scale", "blur", "zoom"] as const;
	let preset = $state<(typeof presets)[number]>("fade-up");
	let open = $state(true);
</script>

<div class="flex w-full flex-col gap-4 p-6">
	<div class="flex flex-wrap gap-2">
		{#each presets as p (p)}
			<button
				type="button"
				class={`rounded-full border px-3 py-1 text-xs capitalize ${
					preset === p
						? "bg-primary text-primary-foreground border-primary"
						: "border-border text-muted-foreground"
				}`}
				onclick={() => (preset = p)}
			>
				{p}
			</button>
		{/each}
	</div>

	<Button variant="outline" size="sm" class="self-start" onclick={() => (open = !open)}>
		{open ? "Hide" : "Show"} panel
	</Button>

	<div
		class="bg-muted/40 border-border flex h-24 items-center justify-center rounded-lg border border-dashed"
	>
		<Presence {open} {preset}>
			<div class="bg-card border-border rounded-lg border p-4 shadow-sm">
				<p class="text-foreground text-sm font-medium">{preset} preset</p>
			</div>
		</Presence>
	</div>
</div>
```
