Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions .agents/skills/elements/references/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ Instructions for migrating a project from deprecated Elements APIs to the latest
- The public npm registry hosts the public packages under the `@nvidia-elements` scope.
- Internal NVIDIA teams should keep using Artifactory. Artifactory proxies the public npm registry.
- Component APIs, `nve-*` tag names, and the theming system remain the same unless a rule below says to change them.
- The new packages reset version numbers to `0.x`. Use the latest available public package versions instead of copying old internal versions.
- The `0.x` public packages contain the same non-deprecated components as the latest internal releases. Deprecated or removed APIs need explicit migration.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixing outdated migration data

- The initial public `0.x` packages were transitional preview releases. Stable public releases started at `2.0.0`, following the internal `1.x` generation.
- Use stable `2.x` versions instead of transitional `0.x` packages or old internal versions. Deprecated or removed APIs need explicit migration.
- Prefer lint-driven changes. Install `@nvidia-elements/lint`, run ESLint, build a work list from the findings, and fix one category at a time.

## Recommended Agent Workflow
Expand Down Expand Up @@ -117,12 +117,14 @@ Before:

After:

Use stable `2.x` versions. The `^2.0.0` ranges accept later `2.x` releases and exclude transitional `0.x` versions. Run `nve packages.list` to check published versions before updating.

```json
{
"dependencies": {
"@nvidia-elements/core": "0.x",
"@nvidia-elements/themes": "0.x",
"@nvidia-elements/styles": "0.x"
"@nvidia-elements/core": "^2.0.0",
"@nvidia-elements/themes": "^2.0.0",
"@nvidia-elements/styles": "^2.0.0"
}
}
```
Expand Down
3 changes: 3 additions & 0 deletions projects/core/.visual/tree.slotted-link-after.png

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added test to prevent regression of case where a link is slotted to a tree node and the ::after is not correctly applied creating a broken touch target

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion projects/core/src/tree/tree-node.css
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ slot:not(:has-slotted) {
margin-inline-start: var(--nve-ref-space-xxxs);
padding: var(--nve-ref-size-200) var(--nve-ref-size-200) var(--nve-ref-size-200) var(--nve-ref-size-100);
min-height: var(--min-height);
position: relative;

& slot {
width: fit-content;
Expand All @@ -68,7 +69,6 @@ slot:not(:has-slotted) {
min-width: 0;
flex-shrink: 1;
display: block;
position: relative;
}
}

Expand Down
24 changes: 24 additions & 0 deletions projects/core/src/tree/tree.test.visual.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,30 @@ describe('tree visual', () => {
);
expect(report.maxDiffPercentage).toBeLessThan(1);
});

test('slotted link ::after should fill visible node space', async () => {
const report = await visualRunner.render(
'tree.slotted-link-after',
`
<script type="module">
import '@nvidia-elements/core/tree/define.js';
</script>
<style>
nve-tree-node a::after {
background: oklch(0.63 0.26 29.23 / 0.5);
color: white;
}
</style>
<nve-tree>
<nve-tree-node>
<!-- link ::after should fill visible space -->
<a href="#">•︎•︎•︎•︎•︎•︎</a>
</nve-tree-node>
</nve-tree>
`
);
expect(report.maxDiffPercentage).toBeLessThan(1);
});
});

function template(theme: '' | 'dark' = '') {
Expand Down
292 changes: 279 additions & 13 deletions projects/internals/patterns/src/agent.examples.ts

Large diffs are not rendered by default.

119 changes: 119 additions & 0 deletions projects/internals/patterns/src/code.examples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import '@nvidia-elements/core/format-datetime/define.js';
import '@nvidia-elements/core/grid/define.js';
import '@nvidia-elements/core/icon/define.js';
import '@nvidia-elements/core/password/define.js';
import '@nvidia-elements/core/switch/define.js';
import '@nvidia-elements/core/tree/define.js';
import '@nvidia-elements/monaco/diff-editor/define.js';

export default {
title: 'Patterns/Code',
Expand Down Expand Up @@ -170,6 +172,43 @@ export const FileTree = {
`
};

/**
* @summary Expandable changed-file tree with additions and deletions aligned beside each file. Use during Git reviews to scan the scope of changes without losing the repository hierarchy.
* @tags pattern
*/
export const FileTreeGitDiff = {
render: () => html`
<nve-tree behavior-expand aria-label="Changed robot software files" style="max-width: 360px">

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add tree example in context of code patterns

<nve-tree-node expanded>
<span nve-text="body muted">src</span>
<nve-tree-node>
<code nve-text="code" title="src/robot_state.py">robot_state.py</code>
<div slot="suffix" nve-layout="row gap:xs">
<nve-badge container="flat" status="success" aria-label="18 added lines">+18</nve-badge>
<nve-badge container="flat" status="failed" aria-label="6 deleted lines">−6</nve-badge>
</div>
</nve-tree-node>
<nve-tree-node expanded>
<span nve-text="body muted">navigation</span>
<nve-tree-node>
<code nve-text="code" title="src/navigation/planner.py">planner.py</code>
<div slot="suffix" nve-layout="row gap:xs">
<nve-badge container="flat" status="success" aria-label="32 added lines">+32</nve-badge>
<nve-badge container="flat" status="failed" aria-label="12 deleted lines">−12</nve-badge>
</div>
</nve-tree-node>
</nve-tree-node>
</nve-tree-node>
<nve-tree-node>
<code nve-text="code" title="robot.yaml">robot.yaml</code>
<div slot="suffix" nve-layout="row gap:xs">
<nve-badge container="flat" status="success" aria-label="9 added lines">+9</nve-badge>
</div>
</nve-tree-node>
</nve-tree>
`
};

/**
* @summary Commit details with author, copyable hash, and expandable file changes. Use after an assistant edits a repository to show the scope of a change and distinguish added, modified, deleted, and renamed files.
* @tags pattern
Expand Down Expand Up @@ -274,3 +313,83 @@ export const EnvironmentVariables = {
</nve-card>
`
};

/**
* @summary Git change review for a warehouse robot navigation configuration with branch context and read-only comparisons. Use before merging robot behavior changes to inspect revised parameters in side-by-side or inline views.
* @tags pattern
*/
export const GitReviewDiff = {
render() {
return html`
<div id="git-review-diff" nve-layout="column gap:sm align:horizontal-stretch">
<div nve-layout="row gap:md align:wrap align:space-between full:width">
<code nve-text="code sm">config/warehouse-navigation.json</code>
<nve-switch>
<label>Side by side</label>
<input type="checkbox" checked />
</nve-switch>
</div>
<nve-monaco-diff-editor aria-label="Warehouse robot navigation configuration changes" style="height: 480px"></nve-monaco-diff-editor>

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added example of monaco git diff in context of code patterns

</div>
<script type="module">
const review = document.querySelector('#git-review-diff');
const diff = review.querySelector('nve-monaco-diff-editor');
const sideBySide = review.querySelector('input[type="checkbox"]');

const initialize = () => {
const { editor, monaco } = diff;
if (!editor || !monaco || editor.getModel()) return;

const original = monaco.editor.createModel(JSON.stringify({
robot_id: 'AMR-07',
scenario: 'warehouse-aisle-3',
navigation: {
max_speed_mps: 1.2,
obstacle_clearance_m: 0.35,
blocked_aisle_behavior: 'pause',
planner: 'grid_search'
}
}, null, 2), 'json');
const modified = monaco.editor.createModel(JSON.stringify({
robot_id: 'AMR-07',
scenario: 'warehouse-aisle-3',
navigation: {
max_speed_mps: 0.8,
obstacle_clearance_m: 0.6,
blocked_aisle_behavior: 'replan',
planner: 'grid_search',
replanning: {
enabled: true,
retry_interval_s: 2,
max_attempts: 3
}
}
}, null, 2), 'json');

editor.updateOptions({
readOnly: true,
originalEditable: false,
renderSideBySide: sideBySide.checked,
useInlineViewWhenSpaceIsLimited: false,
originalAriaLabel: 'Base warehouse navigation configuration on main',
modifiedAriaLabel: 'Proposed warehouse navigation configuration',
minimap: { enabled: false },
scrollBeyondLastLine: false
});
editor.setModel({ original, modified });
editor.onDidDispose(() => {
editor.setModel(null);
original.dispose();
modified.dispose();
});
};

diff.addEventListener('ready', initialize);
initialize();
sideBySide.addEventListener('change', () => {
diff.editor?.updateOptions({ renderSideBySide: sideBySide.checked });
});
</script>
`;
}
};
22 changes: 17 additions & 5 deletions projects/markdown/src/markdown/markdown.examples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import { html } from 'lit';
import '@nvidia-elements/core/button/define.js';
import '@nvidia-elements/markdown/markdown/define.js';
import '@nvidia-elements/markdown/styles/index.css';

Expand Down Expand Up @@ -249,12 +250,15 @@ This content has <strong>HTML</strong> mixed with markdown.
};

/**
* @summary Progressive streaming demo simulating AI assistant responses with block-by-block content rendering
* @summary Progressive AI response streaming with a restart action. Use to replay content from the beginning and inspect how markdown renders as new blocks arrive.
* @tags test-case
*/
export const JavaScriptDriven = {
export const StreamingContent = {
render: () => html`
<div>
<div nve-layout="column gap:md">
<div>
<nve-button id="restart-markdown-stream" type="button">Restart stream</nve-button>
</div>

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add button to re-trigger streaming markdown example

<nve-markdown id="programmatic-markdown"></nve-markdown>

<script type="module">
Expand Down Expand Up @@ -312,19 +316,27 @@ The component uses a reactive approach:
// Split content into blocks/paragraphs for progressive display
const blocks = fullContent.split('\\n');
let currentBlockIndex = 0;
let streamTimeout;
function streamContent() {
if (!element.isConnected) return;
if (currentBlockIndex < blocks.length) {
// Add 1 block at a time to preserve markdown structure
currentBlockIndex++;
const currentContent = blocks.slice(0, currentBlockIndex).join(' \\n');

element.source = currentContent;

setTimeout(streamContent, 300);
streamTimeout = setTimeout(streamContent, 300);
}
}
document.getElementById('restart-markdown-stream').addEventListener('click', () => {
clearTimeout(streamTimeout);
currentBlockIndex = 0;
element.source = '';
streamTimeout = setTimeout(streamContent, 300);
});
// Start streaming after a brief delay
setTimeout(streamContent, 1000);
streamTimeout = setTimeout(streamContent, 1000);
</script>
</div>
`
Expand Down
36 changes: 28 additions & 8 deletions projects/site/public/static/themes/classic.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
--nve-config-color-scheme-light: true;
--nve-config-experimental: true;
--nve-config-theme-classic: true;
/* eslint-disable-line @nve/lint/no-unknown-css-variable */
--nve-ref-color-neutral-100: oklch(99.1% 0 none);
--nve-ref-color-neutral-200: oklch(98.1% 0 none);
--nve-ref-color-neutral-300: oklch(95.3% 0 none);
Expand All @@ -19,6 +18,19 @@
--nve-ref-color-neutral-1000: oklch(60.3% 0 none);
--nve-ref-color-neutral-1100: oklch(50.3% 0 none);
--nve-ref-color-neutral-1200: oklch(24.3% 0 none);
--nve-ref-color-gray-denim-100: oklch(99.1% 0 none);
--nve-ref-color-gray-denim-200: oklch(98.1% 0 none);
--nve-ref-color-gray-denim-300: oklch(95.3% 0 none);
--nve-ref-color-gray-denim-400: oklch(93% 0 none);
--nve-ref-color-gray-denim-500: oklch(90.8% 0 none);
--nve-ref-color-gray-denim-600: oklch(88.4% 0 none);
--nve-ref-color-gray-denim-700: oklch(85.1% 0 none);
--nve-ref-color-gray-denim-800: oklch(79.1% 0 none);
--nve-ref-color-gray-denim-900: oklch(63.01% 0 0);
--nve-ref-color-gray-denim-1000: oklch(60.3% 0 none);
--nve-ref-color-gray-denim-1100: oklch(50.3% 0 none);
--nve-ref-color-gray-denim-1200: oklch(24.3% 0 none);

--nve-ref-border-radius-lg: 16px;
--nve-ref-shadow-100: 0 1px 1px rgb(0 0 0 / 0.06), 0 2px 2px rgb(0 0 0 / 0.05), 0 4px 4px rgb(0 0 0 / 0.04);
--nve-ref-shadow-200: 0 2px 2px rgb(0 0 0 / 0.06), 0 4px 4px rgb(0 0 0 / 0.05), 0 8px 8px rgb(0 0 0 / 0.04);
Expand All @@ -43,7 +55,7 @@
var(--nve-ref-color-scheme-inverse) 5.3%);
--nve-sys-layer-container-accent-background: color-mix(in oklch,
var(--nve-sys-layer-container-background),
var(--nve-ref-color-scheme-inverse) 5.3%);
var(--nve-ref-color-scheme-inverse) 2.3%);
--nve-sys-layer-overlay-accent-background: color-mix(in oklch,
var(--nve-sys-layer-overlay-background),
var(--nve-ref-color-scheme-inverse) 5.3%);
Expand Down Expand Up @@ -273,10 +285,6 @@
--gap: var(--nve-ref-space-xxs);
}

nve-badge:not([container]) {
--border: var(--nve-ref-border-width-sm) solid var(--state-color-base);
}

nve-badge:not([status], [color]) {
--state-color-base: var(--nve-sys-support-accent-color);
}
Expand Down Expand Up @@ -940,8 +948,7 @@
--nve-config-color-scheme-dark: true;
--nve-config-experimental: true;
--nve-config-theme-classic-dark: true;
/* eslint-disable-line @nve/lint/no-unknown-css-variable */
--nve-ref-color-neutral-100: oklch(10% 0 0);
--nve-ref-color-neutral-100: oklch(0% 0 0);
--nve-ref-color-neutral-200: oklch(20.02% 0 0);
--nve-ref-color-neutral-300: oklch(25.2% 0 0);
--nve-ref-color-neutral-400: oklch(28.09% 0 0);
Expand All @@ -953,6 +960,19 @@
--nve-ref-color-neutral-1000: oklch(77.31% 0 0);
--nve-ref-color-neutral-1100: oklch(85.45% 0 0);
--nve-ref-color-neutral-1200: oklch(90.67% 0 0);
--nve-ref-color-gray-denim-100: oklch(0% 0 0);
--nve-ref-color-gray-denim-200: oklch(20.02% 0 0);
--nve-ref-color-gray-denim-300: oklch(25.2% 0 0);
--nve-ref-color-gray-denim-400: oklch(28.09% 0 0);
--nve-ref-color-gray-denim-500: oklch(31.32% 0 0);
--nve-ref-color-gray-denim-600: oklch(35.23% 0 0);
--nve-ref-color-gray-denim-700: oklch(40.17% 0 0);
--nve-ref-color-gray-denim-800: oklch(49.26% 0 0);
--nve-ref-color-gray-denim-900: oklch(56.24% 0 0);
--nve-ref-color-gray-denim-1000: oklch(77.31% 0 0);
--nve-ref-color-gray-denim-1100: oklch(85.45% 0 0);
--nve-ref-color-gray-denim-1200: oklch(90.67% 0 0);

--nve-ref-color-scheme-base: var(--nve-ref-color-black);
--nve-ref-color-scheme-inverse: var(--nve-ref-color-white);

Expand Down
13 changes: 11 additions & 2 deletions projects/site/src/_11ty/layouts/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -489,13 +489,22 @@ export function renderGlobalsScript(data = { disableTheme: false }) {
}

export function renderBasePageHeader(data) {
const isCatalogPage = [
'/docs/elements/',
'/docs/code/',
'/docs/markdown/',
'/docs/media/',
'/docs/monaco/',
'/docs/viewport/'
].some(path => data.page.url.startsWith(path));

return /* html */ `
<nve-page-header slot="header">
<nve-logo slot="prefix" color="brand-green" size="sm" aria-label="NVIDIA Elements Design System">NV</nve-logo>
<a slot="prefix" href="/">NVIDIA Elements</a>
<nve-button container="flat" ${data.page.url.includes('docs') ? 'selected' : ''} class="header-btn"><a href="/">Catalog</a></nve-button>
<nve-button container="flat" ${isCatalogPage ? 'selected' : ''} class="header-btn"><a href="/docs/elements/">Catalog</a></nve-button>
${ELEMENTS_PLAYGROUND_BASE_URL ? /* html */ `<nve-button container="flat" class="header-btn"><a href="${ELEMENTS_PLAYGROUND_BASE_URL}/ui/elements-playground/browse.html" target="_blank">Playground</a></nve-button>` : ''}
<nve-button container="flat" class="header-btn"><a href="/docs/integrations/">Starters</a></nve-button>
<nve-button container="flat" ${data.page.url.startsWith('/docs/integrations/') ? 'selected' : ''} class="header-btn"><a href="/docs/integrations/">Starters</a></nve-button>

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor corrections to selection visual state based on page path

<nve-button container="flat" class="header-btn"><a href="${ELEMENTS_REPO_BASE_URL}" target="_blank">GitHub</a></nve-button>
<nve-button slot="suffix" id="system-options-panel-btn" container="flat">System Themes</nve-button>
<nve-icon-button class="header-menu-btn" role="button" command="--toggle" commandfor="sidenav-panel" container="flat" slot="suffix" icon-name="menu" aria-label="menu"></nve-icon-button>
Expand Down
Loading
Loading