Skip to content

Commit 5675997

Browse files
committed
feat(core): progress gauge
Signed-off-by: Cory Rylan <crylan@nvidia.com>
1 parent 1cda122 commit 5675997

18 files changed

Lines changed: 841 additions & 1 deletion

config/vale/styles/config/vocabularies/Elements/accept.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,3 +358,5 @@ spark line
358358
spark lines
359359
Alternatively
360360
misprefixed
361+
indicate
362+
utilization
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading

projects/core/package.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,18 @@
605605
"types": "./dist/progress-bar/define.d.ts",
606606
"default": "./dist/progress-bar/define.js"
607607
},
608+
"./progress-gauge": {
609+
"types": "./dist/progress-gauge/index.d.ts",
610+
"default": "./dist/progress-gauge/index.js"
611+
},
612+
"./progress-gauge/index.js": {
613+
"types": "./dist/progress-gauge/index.d.ts",
614+
"default": "./dist/progress-gauge/index.js"
615+
},
616+
"./progress-gauge/define.js": {
617+
"types": "./dist/progress-gauge/define.d.ts",
618+
"default": "./dist/progress-gauge/define.js"
619+
},
608620
"./progress-ring": {
609621
"types": "./dist/progress-ring/index.d.ts",
610622
"default": "./dist/progress-ring/index.js"

projects/core/src/bundle.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import '@nvidia-elements/core/panel/define.js';
4747
import '@nvidia-elements/core/password/define.js';
4848
import '@nvidia-elements/core/preferences-input/define.js';
4949
import '@nvidia-elements/core/progress-bar/define.js';
50+
import '@nvidia-elements/core/progress-gauge/define.js';
5051
import '@nvidia-elements/core/progress-ring/define.js';
5152
import '@nvidia-elements/core/progressive-filter-chip/define.js';
5253
import '@nvidia-elements/core/pulse/define.js';
@@ -115,6 +116,7 @@ export * from '@nvidia-elements/core/panel';
115116
export * from '@nvidia-elements/core/password';
116117
export * from '@nvidia-elements/core/preferences-input';
117118
export * from '@nvidia-elements/core/progress-bar';
119+
export * from '@nvidia-elements/core/progress-gauge';
118120
export * from '@nvidia-elements/core/progress-ring';
119121
export * from '@nvidia-elements/core/progressive-filter-chip';
120122
export * from '@nvidia-elements/core/pulse';

projects/core/src/index.test.lighthouse.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ describe('lighthouse report', () => {
1515
expect(report.scores.performance).toBe(100);
1616
expect(report.scores.accessibility).toBe(100);
1717
expect(report.scores.bestPractices).toBe(100);
18-
expect(report.payload.javascript.requests['index.js'].kb).toBeLessThan(130.5);
18+
expect(report.payload.javascript.requests['index.js'].kb).toBeLessThan(132);
1919

2020
// if sudden drop in size, check vite bundle config and bundle demo to ensure side effects are properly preserved
2121
expect(report.payload.javascript.requests['index.js'].kb).toBeGreaterThan(120);
@@ -62,6 +62,7 @@ describe('lighthouse report', () => {
6262
import '@nvidia-elements/core/password/define.js';
6363
import '@nvidia-elements/core/preferences-input/define.js';
6464
import '@nvidia-elements/core/progress-bar/define.js';
65+
import '@nvidia-elements/core/progress-gauge/define.js';
6566
import '@nvidia-elements/core/progress-ring/define.js';
6667
import '@nvidia-elements/core/progressive-filter-chip/define.js';
6768
import '@nvidia-elements/core/radio/define.js';
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { define } from '@nvidia-elements/core/internal';
5+
import { ProgressGauge } from '@nvidia-elements/core/progress-gauge';
6+
7+
define(ProgressGauge);
8+
9+
declare global {
10+
interface HTMLElementTagNameMap {
11+
'nve-progress-gauge': ProgressGauge;
12+
}
13+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
export * from './progress-gauge.js';
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/* SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
2+
/* SPDX-License-Identifier: Apache-2.0 */
3+
4+
:host {
5+
--color: var(--nve-sys-text-emphasis-color);
6+
--background: var(--nve-sys-interaction-background);
7+
--accent-color: var(--nve-sys-interaction-color);
8+
--gauge-width: 12px;
9+
--font-size: var(--nve-ref-font-size-400);
10+
--gap: var(--nve-ref-space-xs);
11+
--width: 128px;
12+
--height: var(--width);
13+
--_animation-duration: var(--nve-ref-animation-duration-250);
14+
display: inline-block;
15+
position: relative;
16+
width: var(--width);
17+
height: var(--height);
18+
container-type: inline-size;
19+
contain: content;
20+
text-box: trim-both cap alphabetic;
21+
}
22+
23+
:host([size='sm']) {
24+
--font-size: var(--nve-ref-font-size-300);
25+
--width: 96px;
26+
}
27+
28+
:host([size='lg']) {
29+
--font-size: var(--nve-ref-font-size-500);
30+
--width: 160px;
31+
}
32+
33+
[internal-host] {
34+
display: grid;
35+
place-items: center;
36+
position: relative;
37+
height: 100%;
38+
}
39+
40+
:host([container='half']) {
41+
--height: calc(var(--width) / 2);
42+
}
43+
44+
:host([container='half']) [internal-host] {
45+
place-items: end center;
46+
}
47+
48+
svg {
49+
position: absolute;
50+
inset: 0;
51+
width: 100%;
52+
height: 100%;
53+
overflow: visible;
54+
}
55+
56+
path {
57+
fill: none;
58+
stroke-linecap: round;
59+
stroke-width: var(--gauge-width);
60+
}
61+
62+
:host([container='half']) path {
63+
stroke-linecap: butt;
64+
}
65+
66+
path.background {
67+
stroke: var(--background);
68+
}
69+
70+
path.gauge {
71+
animation: gauge-progress-in var(--_animation-duration) var(--nve-ref-animation-easing-100);
72+
stroke: var(--accent-color);
73+
stroke-dasharray: var(--_progress) 100;
74+
transition: stroke-dasharray var(--_animation-duration) var(--nve-ref-animation-easing-100);
75+
will-change: stroke-dasharray;
76+
}
77+
78+
path.gauge[empty] {
79+
animation: none;
80+
stroke-linecap: butt;
81+
}
82+
83+
slot {
84+
display: flex;
85+
flex-direction: column;
86+
place-items: center;
87+
justify-content: center;
88+
height: 100%;
89+
gap: var(--gap);
90+
color: var(--color);
91+
font-size: var(--font-size);
92+
font-weight: var(--nve-ref-font-weight-medium);
93+
}
94+
95+
:host([container='half']) slot {
96+
transform: translateY(10cqw);
97+
}
98+
99+
::slotted(*) {
100+
color: var(--color);
101+
font-size: var(--font-size);
102+
}
103+
104+
:host([status='success']) {
105+
--accent-color: var(--nve-sys-support-success-emphasis-color);
106+
--background: var(--nve-sys-support-success-muted-color);
107+
}
108+
109+
:host([status='warning']) {
110+
--accent-color: var(--nve-sys-support-warning-emphasis-color);
111+
--background: var(--nve-sys-support-warning-muted-color);
112+
}
113+
114+
:host([status='danger']) {
115+
--accent-color: var(--nve-sys-support-danger-emphasis-color);
116+
--background: var(--nve-sys-support-danger-muted-color);
117+
}
118+
119+
:host([status='accent']) {
120+
--accent-color: var(--nve-sys-accent-secondary-background);
121+
}
122+
123+
@media (prefers-reduced-motion: reduce) {
124+
:host {
125+
--_animation-duration: 0s;
126+
}
127+
}
128+
129+
@keyframes gauge-progress-in {
130+
from {
131+
stroke-dasharray: 0 100;
132+
}
133+
134+
to {
135+
stroke-dasharray: var(--_progress) 100;
136+
}
137+
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { html } from 'lit';
5+
import '@nvidia-elements/core/progress-gauge/define.js';
6+
7+
export default {
8+
title: 'Elements/Progress Gauge',
9+
component: 'nve-progress-gauge',
10+
};
11+
12+
/**
13+
* @summary 270-degree progress gauges for displaying system resource utilization.
14+
*/
15+
export const Default = {
16+
render: () => html`
17+
<div nve-layout="row gap:sm">
18+
<nve-progress-gauge value="50">50%</nve-progress-gauge>
19+
<nve-progress-gauge status="accent" value="66">66%</nve-progress-gauge>
20+
</div>
21+
`};
22+
23+
/**
24+
* @summary Container variants compare the default 270-degree gauge with the compact half gauge for telemetry layouts with tighter vertical space.
25+
* @tags test-case
26+
*/
27+
export const Container = {
28+
render: () => html`
29+
<div nve-layout="row gap:sm align:vertical-center">
30+
<nve-progress-gauge status="accent" value="66">66%</nve-progress-gauge>
31+
<nve-progress-gauge container="half" status="accent" value="66">66%</nve-progress-gauge>
32+
</div>
33+
`};
34+
35+
/**
36+
* @summary Gauges with values from 0% to 100% for displaying system resource utilization.
37+
* @tags test-case
38+
*/
39+
export const Values = {
40+
render: () => html`
41+
<div nve-layout="row gap:sm">
42+
<nve-progress-gauge value="0">0%</nve-progress-gauge>
43+
<nve-progress-gauge value="33">33%</nve-progress-gauge>
44+
<nve-progress-gauge value="66">66%</nve-progress-gauge>
45+
<nve-progress-gauge value="100">100%</nve-progress-gauge>
46+
</div>
47+
`};
48+
49+
/**
50+
* @summary Progress gauges with custom max values for mission checkpoints, validation clips, and map tile processing.
51+
* @tags test-case
52+
*/
53+
export const Max = {
54+
render: () => html`
55+
<div nve-layout="row gap:sm">
56+
<nve-progress-gauge status="accent" max="20" value="5">5/20</nve-progress-gauge>
57+
<nve-progress-gauge max="20" value="10">10/20</nve-progress-gauge>
58+
<nve-progress-gauge max="20" value="15">15/20</nve-progress-gauge>
59+
</div>
60+
`};
61+
62+
/**
63+
* @summary Progress gauges with accent, success, warning, and danger colors for autonomous system health and readiness signals.
64+
* @tags test-case
65+
*/
66+
export const Status = {
67+
render: () => html`
68+
<div nve-layout="row gap:sm">
69+
<nve-progress-gauge value="50">50%</nve-progress-gauge>
70+
<nve-progress-gauge status="accent" value="75">75%</nve-progress-gauge>
71+
<nve-progress-gauge status="success" value="75">75%</nve-progress-gauge>
72+
<nve-progress-gauge status="warning" value="75">2.1m</nve-progress-gauge>
73+
<nve-progress-gauge status="danger" value="75">0Hz</nve-progress-gauge>
74+
</div>
75+
`};
76+
77+
/**
78+
* @summary Small progress gauge paired with route-solve text for compact autonomous vehicle task rows.
79+
* @tags test-case
80+
*/
81+
export const WithText = {
82+
render: () => html`
83+
<div nve-layout="row gap:xs align:vertical-center" nve-text="medium">
84+
<nve-progress-gauge status="accent" size="sm" value="50" aria-labelledby="route-solve-label">2.4s</nve-progress-gauge>
85+
<span id="route-solve-label">Route solve</span>
86+
</div>
87+
`};
88+
89+
/**
90+
* @summary Progress gauges in small, medium, and large sizes for dense robotics and autonomous vehicle dashboards.
91+
* @tags test-case
92+
*/
93+
export const Sizing = {
94+
render: () => html`
95+
<div nve-layout="row gap:sm">
96+
<nve-progress-gauge size="sm" value="50">30Hz</nve-progress-gauge>
97+
<nve-progress-gauge size="md" value="50">12Hz</nve-progress-gauge>
98+
<nve-progress-gauge size="lg" value="50">84%</nve-progress-gauge>
99+
</div>
100+
`};
101+
102+
/**
103+
* @summary Use for displaying real-time system utilization and performance metrics.
104+
* @tags pattern
105+
*/
106+
export const Dynamic = {
107+
render: () => html`
108+
<div nve-layout="row gap:sm">
109+
<nve-progress-gauge id="dynamic-gpu-progress-gauge" status="success" value="0">
110+
<span>0%</span>
111+
<span nve-text="body sm muted">GPU</span>
112+
</nve-progress-gauge>
113+
</div>
114+
<script type="module">
115+
const gauge = document.querySelector('#dynamic-gpu-progress-gauge');
116+
const valueElement = gauge.querySelector('span');
117+
setInterval(() => {
118+
const value = Math.floor(Math.random() * 101);
119+
gauge.value = value;
120+
gauge.status = value >= 80 ? 'danger' : value >= 60 ? 'warning' : 'success';
121+
valueElement.textContent = value + '%';
122+
}, 1500);
123+
</script>
124+
`};

0 commit comments

Comments
 (0)