{"slug":"presence","title":"Presence","description":"Supporting exit animations using the presence machine.","contentType":"component","framework":"react","content":"Presence helps manage mount/unmount transitions with exit animations.\n\nWhen a component is hidden or removed, the DOM usually removes it immediately.\nPresence keeps it mounted long enough for exit animations to finish.\n\n> The presence machine requires using **CSS animations** to animate the\n> component's exit.\n\n## Resources\n\n\n[Latest version: v1.35.3](https://www.npmjs.com/package/@zag-js/presence)\n[Logic Visualizer](https://zag-visualizer.vercel.app/presence)\n[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/presence)\n\n\n\n## Installation\n\nInstall the presence package:\n\n```bash\nnpm install @zag-js/presence @zag-js/react\n# or\nyarn add @zag-js/presence @zag-js/react\n```\n\n## Usage\n\nImport the presence package:\n\n```jsx\nimport * as presence from \"@zag-js/presence\"\n```\n\nThe presence package exports two key functions:\n\n- `machine` - State machine logic.\n- `connect` - Maps machine state to JSX props and event handlers.\n\nThen use the framework integration helpers:\n\n```tsx\nimport * as presence from \"@zag-js/presence\"\nimport { useMachine, normalizeProps } from \"@zag-js/react\"\n\ninterface PresenceProps {\n  present: boolean\n  unmountOnExit?: boolean\n  onExitComplete?: () => void\n}\n\nfunction Presence(props: PresenceProps) {\n  const { unmountOnExit, present, onExitComplete, ...rest } = props\n\n  const service = useMachine(presence.machine, {\n    present,\n    onExitComplete,\n  })\n\n  const api = presence.connect(service, normalizeProps)\n\n  if (!api.present && unmountOnExit) return null\n\n  return (\n    <div\n      hidden={!api.present}\n      data-state={api.skip ? undefined : present ? \"open\" : \"closed\"}\n      ref={api.setNode}\n      {...rest}\n    />\n  )\n}\n```\n\n### Running code after exit animation\n\nUse `onExitComplete` to run logic after the exit animation finishes.\n\n```jsx\nconst service = useMachine(presence.machine, {\n  present: open,\n  onExitComplete() {\n    console.log(\"Exit animation finished\")\n  },\n})\n```\n\n### Applying presence changes immediately\n\nSet `immediate` to `true` to skip deferring present-state changes to the next\nframe.\n\n```jsx\nconst service = useMachine(presence.machine, {\n  present: open,\n  immediate: true,\n})\n```\n\n## Styling guide\n\nTo style any entry and exit animations, set up the `@keyframes` and apply the\nanimations.\n\n```css\n@keyframes enter {\n  from {\n    scale: 0.9;\n    opacity: 0;\n  }\n\n  to {\n    opacity: 1;\n    scale: 1;\n  }\n}\n\n@keyframes exit {\n  to {\n    opacity: 0;\n    scale: 0.9;\n  }\n}\n\n[data-state=\"open\"] {\n  animation: enter 0.15s ease-out;\n}\n\n[data-state=\"closed\"] {\n  animation: exit 0.1s ease-in;\n}\n```\n\nYou can then use the `Presence` component in your project.\n\n```jsx\nfunction Example() {\n  const [open, setOpen] = React.useState(true)\n  return (\n    <>\n      <button onClick={() => setOpen((c) => !c)}>Toggle</button>\n      <Presence present={open} unmountOnExit>\n        <div>Content</div>\n      </Presence>\n    </>\n  )\n}\n```\n\n## Methods and Properties\n\n### Machine Context\n\nThe presence machine exposes the following context properties:\n\n**`present`**\nType: `boolean`\nDescription: Whether the node is present (controlled by the user)\n\n**`onExitComplete`**\nType: `VoidFunction`\nDescription: Function called when the animation ends in the closed state\n\n**`immediate`**\nType: `boolean`\nDescription: Whether to synchronize the present change immediately or defer it to the next frame\n\n### Machine API\n\nThe presence `api` exposes the following methods:\n\n**`skip`**\nType: `boolean`\nDescription: Whether the animation should be skipped.\n\n**`present`**\nType: `boolean`\nDescription: Whether the node is present in the DOM.\n\n**`setNode`**\nType: `(node: HTMLElement) => void`\nDescription: Function to set the node (as early as possible)\n\n**`unmount`**\nType: `VoidFunction`\nDescription: Function to programmatically unmount the node","package":"@zag-js/presence","editUrl":"https://github.com/chakra-ui/zag/edit/main/website/data/components/presence.mdx"}