# Environment

URL: https://ark-ui.com/docs/utilities/environment
Source: https://raw.githubusercontent.com/chakra-ui/ark/refs/heads/main/website/src/content/pages/utilities/environment.mdx

Set up components for custom environments like iframes, Shadow DOM, or Electron.

---

## Motivation

We use [Zag.js](https://zagjs.com/overview/composition#custom-window-environment) internally, which relies on DOM query
methods like `document.querySelectorAll` and `document.getElementById`. In custom environments like iframes, Shadow DOM,
or Electron, these methods might not work as expected.

To handle this, Ark UI includes the `EnvironmentProvider`, allowing you to set the appropriate root node or document,
ensuring correct DOM queries.

## Setup

To support custom environments like an iframe, Shadow DOM or Electron, render the `EnvironmentProvider` component to
provide the environment context to all Ark UI components.

**Example: setup**

#### React

```tsx
import { EnvironmentProvider } from '@ark-ui/react/environment'
import Frame from 'react-frame-component'

export const App = () => {
  return (
    <Frame title="IFrame Context">
      <EnvironmentProvider>{/* Your App */}</EnvironmentProvider>
    </Frame>
  )
}

```

#### Solid

```tsx
import { EnvironmentProvider } from '@ark-ui/solid/environment'

export const App = () => {
  return (
    <iframe title="IFrame Context">
      <EnvironmentProvider>{/* Your App */}</EnvironmentProvider>
    </iframe>
  )
}

```

#### Vue

```vue
<script setup lang="ts">
import { EnvironmentProvider } from '@ark-ui/vue/environment'
</script>

<template>
  <iframe title="IFrame Context">
    <EnvironmentProvider><!-- Your App --></EnvironmentProvider>
  </iframe>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { EnvironmentProvider } from '@ark-ui/svelte/environment'
</script>

<ifrmae title="IFrame Context">
  <EnvironmentProvider><!-- Your App --></EnvironmentProvider>
</ifrmae>

```

### Usage in iframe

The `EnvironmentProvider` component will automatically detect the current environment and set the correct environment
context. However, you can also manually set the `Document` like shown in this React example below:

```jsx
import Frame, { FrameContextConsumer } from 'react-frame-component'
import { EnvironmentProvider } from '@ark-ui/react'

export const App = () => (
  <Frame title="IFrame Context">
    <FrameContextConsumer>
      {({ document }) => <EnvironmentProvider value={document}>{/* Your App */}</EnvironmentProvider>}
    </FrameContextConsumer>
  </Frame>
)
```

### Usage in Shadow DOM

Here's an example of how to set the `EnvironmentProvider`'s value with Shadow DOM in Solid.js `Portal` component.

```jsx
import { EnvironmentProvider } from '@ark-ui/react'
import { Index, Portal } from 'solid-js/web'

export const App = () => {
  let portalNode
  return (
    <Portal ref={portalNode} useShadow={true}>
      <EnvironmentProvider value={() => portalNode?.shadowRoot ?? document}>{/* Your App */}</EnvironmentProvider>
    </Portal>
  )
}
```

## Context

Use the `useEnvironmentContext` hook to access the `RootNode`, `Document`, and `Window`.

**Example: usage**

#### React

```tsx
import { useEnvironmentContext } from '@ark-ui/react/environment'

export const Usage = () => {
  const { getRootNode } = useEnvironmentContext()

  return <pre>{JSON.stringify(getRootNode(), null, 2)}</pre>
}

```

#### Solid

```tsx
import { useEnvironmentContext } from '../use-environment-context'

export const Usage = () => {
  const environment = useEnvironmentContext()

  return <pre>{JSON.stringify(environment().getRootNode(), null, 2)}</pre>
}

```

#### Vue

```vue
<script setup lang="ts">
import { DEFAULT_ENVIRONMENT, useEnvironmentContext } from '@ark-ui/vue/environment'

const environment = useEnvironmentContext(DEFAULT_ENVIRONMENT)
</script>

<template>
  <pre>{{ JSON.stringify(environment.getRootNode(), null, 2) }}</pre>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { useEnvironmentContext } from '@ark-ui/svelte/environment'

  const environment = useEnvironmentContext()
</script>

<pre>{JSON.stringify(environment().getRootNode(), null, 2)}</pre>

```

## API Reference

**Component API Reference**

#### React

**EnvironmentProvider Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `RootNode | (() => RootNode)` | No |  |


#### Solid

**EnvironmentProvider Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `RootNode | (() => RootNode)` | No |  |


#### Vue

**EnvironmentProvider Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `RootNode | (() => RootNode)` | No |  |


#### Svelte

**EnvironmentProvider Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `MaybeFunction<RootNode>` | No | The root node to use for the environment. |
