{"slug":"presence","title":"Presence","description":"Supporting exit animations using the presence machine.","contentType":"component","framework":"react","content":"The presence machine is a state machine that helps you manage exit animations in\nyour project.\n\nIn the DOM, when a component is removed from the tree or hidden, it's removed\ninstantly. The presence machine suspends the component to allow its exit\nanimation before removing or hiding it.\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.31.0](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\nTo use the presence machine in your project, run the following command in your\ncommand line:\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\nFirst, import the presence package into your project\n\n```jsx\nimport * as presence from \"@zag-js/presence\"\n```\n\nThe presence package exports two key functions:\n\n- `machine` — The state machine logic for the presence.\n- `connect` — The function that translates the machine's state to JSX attributes\n  and event handlers.\n\nNext, import the required hooks and functions for your framework and use the\npresence machine in your project 🔥\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## 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"}