diff --git a/projects/core/src/dialog/dialog.ts b/projects/core/src/dialog/dialog.ts
index 0492ceb13..744e6b93e 100644
--- a/projects/core/src/dialog/dialog.ts
+++ b/projects/core/src/dialog/dialog.ts
@@ -21,7 +21,7 @@ import styles from './dialog.css?inline';
/**
* @element nve-dialog
- * @description Dialog is a component that appears above main content. A modal dialog displays critical information that requires user attention and interrupts user flow. [MDN Popover API](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API)
+ * @description Dialog is a component that appears above main content. A modal dialog displays critical information that requires user attention and interrupts user flow.
* @documentation https://nvidia.github.io/elements/docs/elements/dialog/
* @since 0.6.0
* @entrypoint \@nvidia-elements/core/dialog
diff --git a/projects/core/src/drawer/drawer.ts b/projects/core/src/drawer/drawer.ts
index da9a02c59..37369391c 100644
--- a/projects/core/src/drawer/drawer.ts
+++ b/projects/core/src/drawer/drawer.ts
@@ -18,7 +18,7 @@ import styles from './drawer.css?inline';
/**
* @element nve-drawer
- * @description Drawer are to display content that is out of context of the rest of the page (notifications, navigation, settings). Or use [Panel](./docs/elements/panel/) inline as its content couples with or closely relates to the content on the page (details, extra actions/options). [MDN Popover API](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API)
+ * @description Drawer are to display content that is out of context of the rest of the page (notifications, navigation, settings).
* @documentation https://nvidia.github.io/elements/docs/elements/drawer/
* @since 0.16.0
* @entrypoint \@nvidia-elements/core/drawer
diff --git a/projects/core/src/gauge/gauge.examples.ts b/projects/core/src/gauge/gauge.examples.ts
index 7c5156b76..da9c5203b 100644
--- a/projects/core/src/gauge/gauge.examples.ts
+++ b/projects/core/src/gauge/gauge.examples.ts
@@ -14,10 +14,7 @@ export default {
*/
export const Default = {
render: () => html`
-
- 50%
- 66%
-
+ 66%
`};
/**
diff --git a/projects/core/src/notification/notification.ts b/projects/core/src/notification/notification.ts
index 9cb402e4b..77e2146f8 100644
--- a/projects/core/src/notification/notification.ts
+++ b/projects/core/src/notification/notification.ts
@@ -20,7 +20,7 @@ import styles from './notification.css?inline';
/**
* @element nve-notification
- * @description Displays real time updates without interrupting the user's workflow to communicate an important message or status. [MDN Popover API](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API)
+ * @description Displays real time updates without interrupting the user's workflow to communicate an important message or status.
* @documentation https://nvidia.github.io/elements/docs/elements/notification/
* @since 0.6.0
* @entrypoint \@nvidia-elements/core/notification
diff --git a/projects/core/src/toast/toast.ts b/projects/core/src/toast/toast.ts
index 87f3ce44e..e7e4b9f06 100644
--- a/projects/core/src/toast/toast.ts
+++ b/projects/core/src/toast/toast.ts
@@ -21,7 +21,7 @@ import styles from './toast.css?inline';
/**
* @element nve-toast
- * @description A contextual popup that displays a status. Toasts are [triggered](https://w3c.github.io/aria/#tooltip) by clicking, focusing, or tapping an element and cannot have interactive elements within them. [MDN Popover API](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API)
+ * @description A contextual popup that displays a status. Toasts are [triggered](https://w3c.github.io/aria/#tooltip) by clicking, focusing, or tapping an element and cannot have interactive elements within them.
* @documentation https://nvidia.github.io/elements/docs/elements/toast/
* @since 0.6.0
* @entrypoint \@nvidia-elements/core/toast
diff --git a/projects/core/src/tooltip/tooltip.ts b/projects/core/src/tooltip/tooltip.ts
index 107a38d58..fd5963a3e 100644
--- a/projects/core/src/tooltip/tooltip.ts
+++ b/projects/core/src/tooltip/tooltip.ts
@@ -17,7 +17,7 @@ import styles from './tooltip.css?inline';
/**
* @element nve-tooltip
- * @description A contextual popup that displays a plaintext description. Tooltips are [triggered](https://w3c.github.io/aria/#tooltip) by hovering, focusing, or tapping an element and cannot have interactive elements within them. [MDN Popover API](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API)
+ * @description A contextual popup that displays a plaintext description. Trigger tooltips by hovering, focusing, or tapping an element and cannot have interactive elements within them.
* @documentation https://nvidia.github.io/elements/docs/elements/tooltip/
* @since 0.6.0
* @entrypoint \@nvidia-elements/core/tooltip
diff --git a/projects/markdown/src/markdown/markdown.examples.ts b/projects/markdown/src/markdown/markdown.examples.ts
index 7ba4f9c7b..eec79f797 100644
--- a/projects/markdown/src/markdown/markdown.examples.ts
+++ b/projects/markdown/src/markdown/markdown.examples.ts
@@ -17,7 +17,7 @@ export const Default = {
render: () => html`
- # Default
+ ## Markdown
This is a default markdown component in its initial state.
diff --git a/projects/site/src/_11ty/layouts/common.js b/projects/site/src/_11ty/layouts/common.js
index de8027b74..f3e708506 100644
--- a/projects/site/src/_11ty/layouts/common.js
+++ b/projects/site/src/_11ty/layouts/common.js
@@ -219,7 +219,7 @@ export const renderDocsNav = data => /* html */ `
DESIGN.md
-
+
Elements
Accordion
Alert
@@ -231,6 +231,7 @@ export const renderDocsNav = data => /* html */ `
Card
Chat Message
Checkbox
+ Codeblock
Color
Combobox
Copy Button
@@ -285,8 +286,15 @@ export const renderDocsNav = data => /* html */ `
Input
Input Group
Logo
+ Markdown
+ Markdown CSS
Menu
Month
+ Monaco Input
+ Monaco Diff Input
+ Monaco Editor
+ Monaco Diff Editor
+ Monaco Problems
Notification
Page
Page Header
@@ -342,26 +350,6 @@ export const renderDocsNav = data => /* html */ `
Trend
-
- Code
- Codeblock
-
-
-
- Monaco
- Input
- Diff Input
- Editor
- Diff Editor
- Problems
-
-
-
- Markdown
- Markdown
- CSS Utility
-
-
Labs
diff --git a/projects/site/src/docs/elements/index.11ty.js b/projects/site/src/docs/elements/index.11ty.js
index f72877630..1398595f4 100644
--- a/projects/site/src/docs/elements/index.11ty.js
+++ b/projects/site/src/docs/elements/index.11ty.js
@@ -1,4 +1,5 @@
import { siteData } from '../../index.11tydata.js';
+import { parseFragment, serialize } from 'parse5';
export const data = {
title: 'Components',
@@ -27,6 +28,225 @@ const escapeHtml = value =>
const sortByTitle = (a, b) => a.title.localeCompare(b.title);
+const defaultExamplesByTag = new Map(
+ siteData.examples
+ .filter(example => example.name === 'Default' && !example.element.includes('nve-panel'))
+ .map(example => [example.element, example])
+);
+
+const disallowedPreviewElements = new Set(['base', 'embed', 'iframe', 'link', 'meta', 'object', 'script']);
+const previewUrlAttributes = new Set(['action', 'formaction', 'href', 'poster', 'src', 'xlink:href']);
+const safePreviewProtocols = new Set(['http:', 'https:', 'mailto:', 'tel:']);
+
+const isSafePreviewUrl = value => {
+ try {
+ return safePreviewProtocols.has(new URL(value, 'https://elements.invalid').protocol);
+ } catch {
+ return false;
+ }
+};
+
+const sanitizePreviewNode = node => {
+ if (!Array.isArray(node.childNodes)) return;
+ node.childNodes = node.childNodes.filter(child => !disallowedPreviewElements.has(child.nodeName));
+ node.childNodes.forEach(child => {
+ if (Array.isArray(child.attrs)) {
+ child.attrs = child.attrs.filter(attribute => {
+ const name = attribute.name.toLowerCase();
+ if (name.startsWith('on') || name === 'srcdoc') return false;
+ if (previewUrlAttributes.has(name)) return isSafePreviewUrl(attribute.value);
+ return true;
+ });
+ }
+
+ sanitizePreviewNode(child);
+ if (child.content) sanitizePreviewNode(child.content);
+ });
+};
+
+const sanitizePreviewTemplate = template => {
+ const fragment = parseFragment(String(template ?? ''));
+ sanitizePreviewNode(fragment);
+ return serialize(fragment).trim();
+};
+
+const flattenNestedContainers = template =>
+ template.replace(/<(nve-(?:grid|accordion-group|accordion))(?=[\s>])([^>]*)>/g, (match, tag, attributes) =>
+ attributes.includes('container=') ? match : `<${tag} container="flat"${attributes}>`
+ );
+
+const renderPopoverMock = ({ title, content, type = 'popover' }) => /* html */ `
+
+
+ ${title}
+ ×
+
+
${content}
+
`;
+
+const renderMonacoMock = tag => {
+ const isDiff = tag.includes('diff');
+ const isProblems = tag.includes('problems');
+ const title = isProblems ? 'Problems' : isDiff ? 'Changes' : 'pipeline.ts';
+
+ if (isProblems) {
+ return /* html */ `
+
+
${title}
+
+
× Type mismatch in deployment config
+
! Unused environment variable
+
2 problems in 2 files
+
+
`;
+ }
+
+ const codePane = (label, value) => /* html */ `
+
+ ${label ? `
${label}
` : ''}
+
+ 1const model = '${value}';
+ 2deploy(model);
+ 3monitor('gpu');
+
+
`;
+
+ return /* html */ `
+
+
${title}
+
+ ${isDiff ? codePane('Original', 'v1') + codePane('Modified', 'v2') : codePane('', 'nemotron')}
+
+
`;
+};
+
+const previewOverrides = {
+ 'nve-dialog': renderPopoverMock({
+ title: 'Deploy model?',
+ content: 'Review the configuration before continuing.',
+ type: 'dialog'
+ }),
+ 'nve-drawer': /* html */ `
+
+
+ Session details
+ ×
+
+
+
`,
+ 'nve-dropdown': /* html */ `
+
+ Actions
+ Open details
+ Duplicate
+ Archive
+
`,
+ 'nve-dropdown-group': /* html */ `
+
+
+ Create
+ Workspace ›
+ Deployment
+
+
+ Training
+ Inference
+
+
`,
+ 'nve-grid': /* html */ `
+
+
+ Model
+ Status
+ GPUs
+
+
+ Nemotron
+ Running
+ 8
+
+
+ Cosmos
+ Ready
+ 4
+
+ `,
+ 'nve-notification': renderPopoverMock({
+ title: 'Deployment ready',
+ content: 'The new endpoint is available.',
+ type: 'notification'
+ }),
+ 'nve-page': /* html */ `
+ `,
+ 'nve-page-loader': /* html */ `
+
+
+ Loading workspace
+
`,
+ 'nve-panel': /* html */ `
+
+
+ Deployment
+ Session details
+
+
+
+ Status
+ Ready
+
+
+ GPUs
+ 8 × H100
+
+
+
`,
+ 'nve-toast': renderPopoverMock({ title: 'Changes saved', content: 'Your settings are up to date.', type: 'toast' }),
+ 'nve-toggletip': renderPopoverMock({
+ title: 'GPU allocation',
+ content: 'Choose a pool that matches the workload.',
+ type: 'toggletip'
+ }),
+ 'nve-tooltip': /* html */ `
+ Copy deployment ID
`,
+ 'nve-tree': /* html */ `
+
+
+ Infrastructure
+ Training
+ Inference
+
+ Datasets
+ `,
+ 'nve-monaco-diff-editor': renderMonacoMock('nve-monaco-diff-editor'),
+ 'nve-monaco-diff-input': renderMonacoMock('nve-monaco-diff-input'),
+ 'nve-monaco-editor': renderMonacoMock('nve-monaco-editor'),
+ 'nve-monaco-input': renderMonacoMock('nve-monaco-input'),
+ 'nve-monaco-problems': renderMonacoMock('nve-monaco-problems')
+};
+
+const getPreviewTemplate = tag => {
+ const defaultTemplate = defaultExamplesByTag.get(tag)?.template;
+ const template =
+ previewOverrides[tag] ??
+ (defaultTemplate ? sanitizePreviewTemplate(defaultTemplate) : `${escapeHtml(tag)}`);
+
+ return flattenNestedContainers(template);
+};
+
const createComponentCatalog = componentDocs => {
const docsByTag = new Map(componentDocs.filter(hasComponentTag).map(component => [component.data.tag, component]));
@@ -44,43 +264,328 @@ const createComponentCatalog = componentDocs => {
description: element.manifest?.description?.trim() ?? `Documentation for ${doc.data.title}.`,
href: doc.url,
packageName: element.package,
+ preview: '',
tag: element.name,
title: doc.data.title,
version: element.version
};
})
+ .map(component => {
+ const preview = getPreviewTemplate(component.tag);
+
+ return {
+ ...component,
+ preview
+ };
+ })
.sort(sortByTitle);
return [...createCatalogSection(isElementsComponentDoc), ...createCatalogSection(isLibraryComponentDoc)];
};
-const renderComponentLink = component => /* html */ `
-
-
-
-
-
${escapeHtml(component.title)}
-
${escapeHtml(component.tag)}
-
-
-
+const renderComponentCard = component => /* html */ `
+
+
+
+
+
${escapeHtml(component.title)}
${escapeHtml(component.description)}
-
-
- `;
+
+
+
+ `;
+
+const renderPreviewScript = () => /* html */ `
+`;
export function render(data) {
const components = createComponentCatalog(data.collections.componentDocs);
return /* html */ `
NVIDIA Elements Components
@@ -91,7 +596,9 @@ export function render(data) {
stable nve-* APIs, design tokens, accessibility guidance, and examples.
-
- ${components.map(renderComponentLink).join('')}
-
`;
+
+ ${components.map(renderComponentCard).join('')}
+
+
+${renderPreviewScript()}`;
}