JGuang

Environment Provider

Environment Provider · Chakra UI

Preview
npm install @chakra-ui/react@3.37.0 @emotion/react@11.14.0

Environment Provider

Used to render components in iframes, Shadow DOM, or Electron.

Resolve the actual iframe or shadow root, document and window. The provider does not automatically relocate Emotion styles; consult the dedicated environment guide.

EnvironmentProvider points native DOM queries, focus and event handling at the correct Document or ShadowRoot. It does not copy CSS across documents and is not a theme provider.

Installation and setup

Use pinned @chakra-ui/react@3.37.0 and @emotion/react@11.14.0. The iframe example also uses react-frame-component@5.3.2; scoped iframe and Shadow DOM styles use @emotion/cache@11.14.0.

Native ChakraProvider and defaultSystem still provide the theme. Insert Emotion styles into the nested document's head, or into the ShadowRoot itself. The .chakra-theme wrapper receives Chakra CSS variables; an outer theme class does not cross document boundaries automatically.

Three runnable scenarios

  • Nested iframe: get the inner document through react-frame-component's useFrame(), wait for document.head, and pass value={() => document}. The slider and environment inspection button run in the inner frame.
  • Shadow DOM: create an open ShadowRoot, mount React content there with a Portal, and pass value={() => shadowRoot}. A Portal chooses the mount location; EnvironmentProvider supplies the native DOM-query context.
  • Reading context: useEnvironmentContext() exposes getRootNode(), getDocument() and getWindow(). Do not JSON-serialize the entire Document/Window. This example compares object identities and displays booleans, avoiding circular references.

Parameters and state

value is a root-node getter, not a color or string ID. Use the current component environment, never the outer JGuang website document for isolated preview controls.

The native controlled slider uses value and onValueChange, initially [40]. Pointer dragging or arrow keys update the value. Check environment compares root/document/window against the owned container. It is not an installation-success indication.

The frame/Shadow host and its style container are destroyed when the example unmounts. Do not manually flush a reused Emotion cache from an ordinary effect cleanup: React StrictMode effect replay could erase active styles.

Verification and limits

Check left/right arrows, visible focus, both themes and languages. Frame controls should focus within their own document; Shadow controls should query their ShadowRoot.

No microphone, camera or other permission is requested. Electron is an upstream use case, not a runtime verified by these browser examples. Original inline documentation and native API references remain in the source materials.

Provenance

JGuang authored these complete scenarios from the pinned upstream inline EnvironmentProvider guide, using native Chakra, Emotion and React APIs. They are not modified upstream demo files. Vendor originals and license notices remain unchanged; LOCAL_CHANGES.md records the composition boundary.

Installation and initialization

npm install @chakra-ui/react@3.37.0 @emotion/react@11.14.0

Initialize ChakraProvider with defaultSystem and Emotion before rendering. Preserve the host React version and inspect peer compatibility. Official npm installation supplies components, not these example source files. Use the resource setup guide for locale, next-themes and framework-specific SSR; copy the selected example source separately from npm installation.

Complete native usage example

This is the actual pinned example, not a generic API mock. Copy its source closure and retain the named export. Additional imports are listed per example below. This composition is explicitly authored by JGuang using native APIs.

// Local runnable compositions of the upstream inline EnvironmentProvider guide.
// Native provider, context, slider and Emotion APIs are not replaced or patched.
import { useCallback, useMemo, useState } from "react";
import { createPortal } from "react-dom";
import createCache from "@emotion/cache";
import { CacheProvider } from "@emotion/react";
import Frame, { useFrame } from "react-frame-component";
import { Box, Button, ChakraProvider, EnvironmentProvider, Slider, Stack, Text, defaultSystem, useEnvironmentContext } from "@chakra-ui/react";

const params = new URLSearchParams(location.search);
const zh = params.get("locale") === "zh";
const dark = params.get("theme") === "dark";
type NativeRoot = Document | ShadowRoot;

function EnvironmentControls({ expected }: { expected: NativeRoot }) {
  const { getRootNode, getDocument, getWindow } = useEnvironmentContext();
  const [value, setValue] = useState([40]);
  const [checked, setChecked] = useState<string>();
  function inspect() {
    const node = getRootNode();
    const owner = expected.nodeType === 9 ? expected as Document : expected.ownerDocument;
    setChecked(JSON.stringify({ root: node === expected, document: owner !== null && getDocument() === owner, window: owner !== null && getWindow() === owner.defaultView }));
  }
  return <Stack gap="4" width="100%" maxW="sm">
    <Text fontWeight="semibold">{expected.nodeType === 9 ? "Document" : "ShadowRoot"}</Text>
    <Text fontSize="sm">{zh ? "拖动或用方向键调整原生滑块,检查该组件使用的文档环境。" : "Drag or use arrow keys on the native slider, then check its document environment."}</Text>
    <Slider.Root value={value} onValueChange={event => setValue(event.value)}>
      <Slider.Label>{zh ? "环境内滑块" : "Slider in this environment"}</Slider.Label>
      <Slider.ValueText />
      <Slider.Control><Slider.Track><Slider.Range /></Slider.Track><Slider.Thumbs /></Slider.Control>
    </Slider.Root>
    <Button onClick={inspect}>{zh ? "检查环境" : "Check environment"}</Button>
    <Text role="status" fontFamily="mono" fontSize="xs" overflowWrap="anywhere">{checked ?? (zh ? "等待检查" : "Not checked yet")}</Text>
  </Stack>;
}

function ScopedEnvironment({ root, styleContainer }: { root: NativeRoot; styleContainer: HTMLElement | ShadowRoot }) {
  const cache = useMemo(() => createCache({ key: "jguang-chakra-environment", container: styleContainer }), [styleContainer]);
  // Both containers belong to this example's frame/shadow host and disappear
  // with it. Manually flushing a memoized cache in an effect cleanup would
  // erase styles during React StrictMode's setup/cleanup replay.
  return <CacheProvider value={cache}><ChakraProvider value={defaultSystem}>
    <EnvironmentProvider value={() => root}>
      <Box className={`chakra-theme ${dark ? "dark" : "light"}`} bg="bg" color="fg" p="5" minH="300px">
        <EnvironmentControls expected={root}/>
      </Box>
    </EnvironmentProvider>
  </ChakraProvider></CacheProvider>;
}

function FrameEnvironment() {
  const { document } = useFrame();
  return document?.head ? <ScopedEnvironment root={document} styleContainer={document.head}/> : null;
}

export function EnvironmentProviderIframe() {
  return <Frame title={zh ? "原生环境:嵌套 iframe" : "Native environment: nested iframe"} style={{ width: "100%", height: 340, border: "1px solid #8886", borderRadius: 12 }} initialContent={`<!doctype html><html lang="${zh ? "zh-CN" : "en"}" class="${dark ? "dark" : "light"}"><head><style>body{margin:0}html{color-scheme:${dark ? "dark" : "light"}}</style></head><body><div></div></body></html>`}><FrameEnvironment/></Frame>;
}

export function EnvironmentProviderShadow() {
  const [root, setRoot] = useState<ShadowRoot | null>(null);
  const host = useCallback((node: HTMLDivElement | null) => {
    if (node) setRoot(node.shadowRoot ?? node.attachShadow({ mode: "open" }));
  }, []);
  return <div ref={host} data-native-shadow-environment style={{ width: "100%", border: "1px solid #8886", borderRadius: 12, overflow: "hidden" }}>
    {root && createPortal(<ScopedEnvironment root={root} styleContainer={root}/>, root)}
  </div>;
}

export function EnvironmentProviderContext() {
  return <EnvironmentProvider value={() => document}><EnvironmentControls expected={document}/></EnvironmentProvider>;
}

All examples and reproduction requirements

Names identify demos, not component variant props. Copy every sourceFiles entry for the selected example. The compositions alias denotes local files, not a package. Preserve relative imports or rewrite the alias to your project's actual path. React peers are inspected separately; editor examples retain the coherent pinned Tiptap extension family.

Iframe

environment-provider-iframe · Named export EnvironmentProviderIframe · JGuang native composition

npm install @chakra-ui/react@3.37.0 @emotion/cache@11.14.0 @emotion/react@11.14.0 react-frame-component@5.3.2
  • authored/examples/environment-provider.tsx

Shadow

environment-provider-shadow · Named export EnvironmentProviderShadow · JGuang native composition

npm install @chakra-ui/react@3.37.0 @emotion/cache@11.14.0 @emotion/react@11.14.0 react-frame-component@5.3.2
  • authored/examples/environment-provider.tsx

Context

environment-provider-context · Named export EnvironmentProviderContext · JGuang native composition

npm install @chakra-ui/react@3.37.0 @emotion/cache@11.14.0 @emotion/react@11.14.0 react-frame-component@5.3.2
  • authored/examples/environment-provider.tsx

Native API and source references

The source viewer retains original declarations, imports and inheritance. Ark UI event contracts, Chakra style props and recipe types stay in their native packages; this guide does not flatten or invent their defaults. Code comments remain original source, not translated prose.

  • npm/@chakra-ui/react@3.37.0/dist/types/components/environment/index.d.ts

State and installation checks

Run strict types, the target production build and real interactions. Test labels/focus/keyboard, both themes, narrow layout, empty/loading/error states where supported and cleanup after unmount. Remote demo endpoints, uploads and downloads are constrained in the preview; configure your own services. Copying a command or reaching preview-ready does not prove installation or backend success.

Provenance and license boundaries

https://github.com/chakra-ui/chakra-ui/tree/2e7517745cff2fcde0b8012f136cf99611ff262a

These are JGuang practical bilingual notes, not a full translation of upstream MDX. Original documentation and example bytes remain in vendor. Preserve repository MIT, compositions ISC metadata and separate dependency notices. The original metadata discrepancy and any missing full notices remain explicit review items; paid Chakra Pro is excluded.