diff --git a/projects/code/DEVELOPMENT.md b/projects/code/DEVELOPMENT.md
index 599835d4a1..ff4b5b3d0d 100644
--- a/projects/code/DEVELOPMENT.md
+++ b/projects/code/DEVELOPMENT.md
@@ -8,6 +8,7 @@
| `pnpm run test` | Run unit tests |
| `pnpm run test:watch` | Run unit tests in watch mode |
| `pnpm run test:axe` | Run accessibility tests |
+| `pnpm run test:ssr` | Run server-side rendering tests |
| `pnpm run test:coverage` | Run unit tests with coverage |
| `pnpm run test:lighthouse` | Run Lighthouse performance tests |
| `pnpm run ci` | Run the full CI pipeline |
diff --git a/projects/code/package.json b/projects/code/package.json
index 8313755b7e..f2ea7f56d0 100644
--- a/projects/code/package.json
+++ b/projects/code/package.json
@@ -4,7 +4,7 @@
"release": {
"extends": "../../release.config.js"
},
- "description": "Code authoring related components. Providing syntax-highlighted code blocks with support for multiple programming languages.",
+ "description": "NVIDIA Elements code authoring related components such as syntax-highlighted code blocks and an iframe isolation components.",
"keywords": [
"nvidia",
"web-components",
@@ -169,6 +169,18 @@
"./codeblock/languages/yaml.js": {
"types": "./dist/codeblock/languages/yaml.d.ts",
"default": "./dist/codeblock/languages/yaml.js"
+ },
+ "./iframe": {
+ "types": "./dist/iframe/index.d.ts",
+ "default": "./dist/iframe/index.js"
+ },
+ "./iframe/index.js": {
+ "types": "./dist/iframe/index.d.ts",
+ "default": "./dist/iframe/index.js"
+ },
+ "./iframe/define.js": {
+ "types": "./dist/iframe/define.d.ts",
+ "default": "./dist/iframe/define.js"
}
},
"sideEffects": [
@@ -184,6 +196,7 @@
"lint": "wireit",
"test": "wireit",
"test:axe": "wireit",
+ "test:ssr": "wireit",
"test:coverage": "wireit",
"test:watch": "wireit",
"test:lighthouse": "wireit"
@@ -233,6 +246,7 @@
"lint",
"publint",
"test:axe",
+ "test:ssr",
"test:coverage"
]
},
@@ -368,6 +382,28 @@
"NODE_ENV": "production"
}
},
+ "test:ssr": {
+ "command": "vitest run --config=vitest.ssr.ts",
+ "files": [
+ "dist/**/*.js",
+ "src/**/*.test.ssr.ts",
+ "tsconfig.json",
+ "vitest.ssr.ts"
+ ],
+ "output": [
+ "coverage/ssr/**"
+ ],
+ "dependencies": [
+ "../internals/vite:ci",
+ {
+ "script": "build",
+ "cascade": false
+ }
+ ],
+ "env": {
+ "NODE_ENV": "production"
+ }
+ },
"lint": {
"dependencies": [
"lint:eslint",
diff --git a/projects/code/src/bundle.ts b/projects/code/src/bundle.ts
index 979196b117..10c5627428 100644
--- a/projects/code/src/bundle.ts
+++ b/projects/code/src/bundle.ts
@@ -17,5 +17,7 @@ import '@nvidia-elements/code/codeblock/languages/typescript.js';
import '@nvidia-elements/code/codeblock/languages/xml.js';
import '@nvidia-elements/code/codeblock/languages/yaml.js';
import '@nvidia-elements/code/codeblock/define.js';
+import '@nvidia-elements/code/iframe/define.js';
export * from '@nvidia-elements/code/codeblock';
+export * from '@nvidia-elements/code/iframe';
diff --git a/projects/code/src/iframe/define.ts b/projects/code/src/iframe/define.ts
new file mode 100644
index 0000000000..06bd8e433e
--- /dev/null
+++ b/projects/code/src/iframe/define.ts
@@ -0,0 +1,13 @@
+// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { define } from '@nvidia-elements/core/internal';
+import { Iframe } from './iframe.js';
+
+define(Iframe);
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'nve-iframe': Iframe;
+ }
+}
diff --git a/projects/code/src/iframe/iframe.css b/projects/code/src/iframe/iframe.css
new file mode 100644
index 0000000000..24cb571e31
--- /dev/null
+++ b/projects/code/src/iframe/iframe.css
@@ -0,0 +1,18 @@
+/* SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+:host {
+ --width: var(--_width, fit-content);
+ --height: var(--_height, fit-content);
+ --border: none;
+ display: block;
+ width: fit-content;
+ height: fit-content;
+ border: var(--border);
+}
+
+iframe {
+ width: var(--width);
+ height: var(--height);
+ border: 0;
+}
diff --git a/projects/code/src/iframe/iframe.examples.ts b/projects/code/src/iframe/iframe.examples.ts
new file mode 100644
index 0000000000..d8fc98b411
--- /dev/null
+++ b/projects/code/src/iframe/iframe.examples.ts
@@ -0,0 +1,112 @@
+// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { html } from 'lit';
+import '@nvidia-elements/code/iframe/define.js';
+
+export default {
+ title: 'Code/Iframe',
+ component: 'nve-iframe'
+};
+
+/**
+ * @summary Supplies the iframe with Elements themes, utilities, fonts, and component registrations through its head template. Use this structure because iframe documents do not inherit resources from the parent document.
+ */
+export const Default = {
+ render: () => html`
+
+
+ Elements iframe example
+
+
+
+
+
+
+ isolated iframe content
+
+
+ `
+};
+
+/**
+ * @summary Synchronizes the iframe height with expandable content so the host layout avoids empty space or internal scrollbars. Use for previews whose intrinsic height changes after interaction.
+ * @tags test-case
+ */
+export const DynamicHeight = {
+ render: () => html`
+
+
+ Dynamic iframe height
+
+
+
+
+
+
+
+
+
Dynamic height in iframe
+
+
+ The iframe expands when this content opens and contracts when it closes.
+
+
+
+
+ `
+};
+
+/**
+ * @summary Overrides intrinsic iframe dimensions with `--width` and `--height` to create a stable preview viewport. Use when you need to inspect embedded content at a fixed size regardless of its rendered bounds.
+ * @tags test-case
+ */
+export const FixedSize = {
+ render: () => html`
+
+
override iframe size
+
+ `
+};
+
+/**
+ * @summary The iframe browsing-context boundary clips popovers at its viewport and prevents them from escaping. Keep overlays inside the frame, or render them outside the iframe when they must overlap surrounding content.
+ * @tags test-case
+ */
+export const OverflowClip = {
+ render: () => html`
+
+
+ Clipped iframe popover
+
+
+
+
+
+
+
+ Popovers are clipped by the iframe.
+ Open popover
+
+
+
+ `
+};
+
+/**
+ * @summary Regenerates the iframe document when its source template changes. Use for live previews or generated output that must stay synchronized with edits made in the parent document.
+ * @tags test-case
+ */
+export const DynamicallyUpdatedContent = {
+ render: () => html`
+
+
+
Initial iframe content.
+
+
+
+ `
+};
diff --git a/projects/code/src/iframe/iframe.test.axe.ts b/projects/code/src/iframe/iframe.test.axe.ts
new file mode 100644
index 0000000000..a7dc2306cd
--- /dev/null
+++ b/projects/code/src/iframe/iframe.test.axe.ts
@@ -0,0 +1,29 @@
+// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { html } from 'lit';
+import { describe, expect, it, beforeEach, afterEach } from 'vitest';
+import { createFixture, elementIsStable, removeFixture } from '@internals/testing';
+import { runAxe } from '@internals/testing/axe';
+import { Iframe } from '@nvidia-elements/code/iframe';
+import '@nvidia-elements/code/iframe/define.js';
+
+describe(Iframe.metadata.tag, () => {
+ let fixture: HTMLElement;
+ let element: Iframe;
+
+ beforeEach(async () => {
+ fixture = await createFixture(html``);
+ element = fixture.querySelector