<!-- Source: https://motion.svelte.page/examples/use-presence-data -->

# usePresenceData

> Read AnimatePresence custom data from an entering or exiting child.

**Source:** [https://motion.svelte.page/examples/use-presence-data](https://motion.svelte.page/examples/use-presence-data)

**Markdown mirror:** [https://motion.svelte.page/examples/use-presence-data.md](https://motion.svelte.page/examples/use-presence-data.md)

---

This mirror preserves the prose, implementation notes, and runnable Svelte source behind the live example page.

## FIG-001: directional exits via usePresenceData.

The parent passes `custom={direction}` to AnimatePresence. The keyed child reads that value with `usePresenceData()` so its enter and exit variants know which way to travel.

**Metadata:** tag: `PRESENCE-DATA` | api: `usePresenceData` | mode: `popLayout`

### Notes

- The controls update `direction` before the keyed slide changes.
- The slide calls `usePresenceData()`, so it can read parent custom data while entering and while held for exit.
- `mode="popLayout"` lets the leaving slide pop out of layout while the new slide enters.

### Source

#### Default.svelte

Source file: [src/lib/examples/use-presence-data/demos/Default.svelte](https://github.com/humanspeak/svelte-motion/blob/main/docs/src/lib/examples/use-presence-data/demos/Default.svelte)

```svelte
<script lang="ts" module>
    const iconsProps = {
        xmlns: 'http://www.w3.org/2000/svg',
        width: '24',
        height: '24',
        viewBox: '0 0 24 24',
        fill: 'none',
        stroke: 'currentColor',
        strokeWidth: '2',
        strokeLinecap: 'round',
        strokeLinejoin: 'round'
    }
</script>

<script lang="ts">
    import { AnimatePresence, MotionConfig, motion, wrap } from '@humanspeak/svelte-motion'
    import PresenceDataSlide from './PresenceDataSlide.svelte'

    const items = [1, 2, 3, 4, 5, 6]

    let selectedItem = $state(items[0])
    let direction: 1 | -1 = $state(1)

    const color = $derived(`var(--presence-hue-${selectedItem})`)

    function setSlide(newDirection: 1 | -1) {
        selectedItem = wrap(1, items.length, selectedItem + newDirection)
        direction = newDirection
    }
</script>

<!-- dk-strip: docs-kit positioning shell — stripped from the published code. -->
<div class="dk-demo-shell">
    <MotionConfig>
        <div class="strip">
            <div class="strip-head">
                <span class="micro">// use-presence-data</span>
                <span class="micro readout">
                    slide {String(selectedItem).padStart(2, '0')} / custom={direction}
                </span>
            </div>

            <div class="container">
                <motion.button
                    initial={false}
                    animate={{ backgroundColor: color }}
                    aria-label="Previous"
                    class="button"
                    onclick={() => setSlide(-1)}
                    whileFocus={{ outline: `2px solid ${color}` }}
                    whileTap={{ scale: 0.9 }}
                >
                    <svg {...iconsProps}>
                        <path d="m12 19-7-7 7-7" />
                        <path d="M19 12H5" />
                    </svg>
                </motion.button>

                <AnimatePresence custom={direction} initial={false} mode="popLayout">
                    {#key selectedItem}
                        <PresenceDataSlide slideKey={selectedItem} {color} />
                    {/key}
                </AnimatePresence>

                <motion.button
                    initial={false}
                    animate={{ backgroundColor: color }}
                    aria-label="Next"
                    class="button"
                    onclick={() => setSlide(1)}
                    whileFocus={{ outline: `2px solid ${color}` }}
                    whileTap={{ scale: 0.9 }}
                >
                    <svg {...iconsProps}>
                        <path d="M5 12h14" />
                        <path d="m12 5 7 7-7 7" />
                    </svg>
                </motion.button>
            </div>

            <div class="strip-foot">
                <span class="micro">mode: poplayout / exit reads usePresenceData()</span>
            </div>
        </div>
    </MotionConfig>
</div>

<style>
    .dk-demo-shell {
        --presence-hue-1: #ff0088;
        --presence-hue-2: #dd00ee;
        --presence-hue-3: #9911ff;
        --presence-hue-4: #0d63f8;
        --presence-hue-5: #0cdcf7;
        --presence-hue-6: #4ff0b7;

        min-height: 360px;
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 2rem;
    }

    .strip {
        width: 100%;
        max-width: 420px;
        display: flex;
        flex-direction: column;
        gap: 0.75rem;
    }

    .micro {
        font-family: var(--brut-mono, monospace);
        font-size: 0.6875rem;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        color: var(--brut-ink-3, #9a9a9a);
    }

    .readout {
        color: var(--brut-accent, #247768);
        font-variant-numeric: tabular-nums;
    }

    .strip-head,
    .strip-foot {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 1rem;
        border-bottom: 1px dashed var(--brut-rule-2, #bbc4c0);
        padding-bottom: 0.5rem;
    }

    .strip-foot {
        border-bottom: none;
        border-top: 1px dashed var(--brut-rule-2, #bbc4c0);
        padding-top: 0.75rem;
        padding-bottom: 0;
        justify-content: center;
    }

    .container {
        position: relative;
        height: 12rem;
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 1rem;
    }

    .dk-demo-shell :global(.button) {
        position: relative;
        z-index: 1;
        width: 40px;
        height: 40px;
        display: flex;
        align-items: center;
        justify-content: center;
        border: 1px solid var(--brut-ink, #0a0a0a);
        outline-offset: 2px;
        color: #ffffff;
        cursor: pointer;
    }

    .dk-demo-shell :global(.button svg) {
        width: 24px;
        height: 24px;
    }
</style>
```

#### PresenceDataSlide.svelte

Source file: [src/lib/examples/use-presence-data/demos/PresenceDataSlide.svelte](https://github.com/humanspeak/svelte-motion/blob/main/docs/src/lib/examples/use-presence-data/demos/PresenceDataSlide.svelte)

```svelte
<script lang="ts">
    /**
     * Slide that reads AnimatePresence custom data with usePresenceData.
     *
     * @component
     * @param color CSS color used as the slide background.
     * @param slideKey Numeric slide id displayed by the example.
     */
    import { motion, usePresenceData, type Variants } from '@humanspeak/svelte-motion'

    const { color, slideKey }: { color: string; slideKey: number } = $props()

    const direction = $derived(usePresenceData<1 | -1>() ?? 1)
    const variants: Variants = {
        enter: (custom) => ({
            opacity: 0,
            x: (custom as number) > 0 ? 56 : -56
        }),
        center: {
            opacity: 1,
            x: 0,
            transition: {
                delay: 0.16,
                type: 'spring',
                visualDuration: 0.34,
                bounce: 0.36
            }
        },
        exit: (custom) => ({
            opacity: 0,
            x: (custom as number) > 0 ? -56 : 56
        })
    }
</script>

<motion.div
    key={String(slideKey)}
    class="slide"
    data-presence-direction={direction}
    {variants}
    initial="enter"
    animate="center"
    exit="exit"
    style={`background-color: ${color};`}
>
    <span>{String(slideKey).padStart(2, '0')}</span>
</motion.div>

<style>
    :global(.dk-demo-shell .slide) {
        width: 150px;
        height: 150px;
        display: grid;
        place-items: center;
        border: 1px solid var(--brut-ink, #0a0a0a);
        box-shadow: 6px 6px 0 var(--brut-rule, #d6dedb);
        transform-origin: 50% 50%;
        font-family: var(--brut-mono, monospace);
        font-size: 2rem;
        font-weight: 700;
        color: #ffffff;
    }
</style>
```
