Component demo · Instrument readouts and controls
Seven Segment
index.htm as it is written with the smart-industrial package
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<title>Seven Segment Display Overview Demo</title>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" type="text/css" href="node_modules/smart-industrial/source/styles/smart.default.css" />
<link rel="stylesheet" type="text/css" href="node_modules/smart-industrial/source/styles/smart.industrial-elements.css" />
<link rel="stylesheet" type="text/css" href="node_modules/smart-industrial/source/styles/smart.industrial.css" />
<link rel="stylesheet" type="text/css" href="node_modules/smart-industrial/source/styles/smart.industrial-dark.css" />
<link rel="stylesheet" type="text/css" href="styles.css" />
</head>
<body class="viewport" theme="industrial">
<div class="smart-demo-container">
<section id="overview">
<h2>Smart.SevenSegment is a numeric display in the style of a seven-segment LED readout.</h2>
<p>
It is used for panel meters, totalizers and batch counters. The display is rendered as SVG, so it stays sharp at any size, and takes its colour from the theme. Unlit segments are drawn faintly, as on a real LED display.
</p>
</section>
<section>
<h2>Live reading</h2>
<div class="row">
<smart-seven-segment id="live" digits="5" precision-digits="1" unit="L/min"></smart-seven-segment>
</div>
</section>
<section>
<h2>Digits and precision</h2>
<div class="row">
<div class="cell"><smart-seven-segment id="d1" digits="4"></smart-seven-segment><span>4 digits, no decimals</span></div>
<div class="cell"><smart-seven-segment id="d2" digits="6" precision-digits="2" unit="kWh"></smart-seven-segment><span>6 digits, 2 decimals</span></div>
<div class="cell"><smart-seven-segment id="d3" digits="4" precision-digits="1" unit="°C"></smart-seven-segment><span>negative values</span></div>
</div>
</section>
<section>
<h2>Leading zeros</h2>
<p>A counter usually shows leading zeros; a measurement usually does not.</p>
<div class="row">
<div class="cell"><smart-seven-segment id="z1" digits="6"></smart-seven-segment><span>blank padding</span></div>
<div class="cell"><smart-seven-segment id="z2" digits="6" leading-zeros></smart-seven-segment><span>leading zeros</span></div>
</div>
</section>
<section>
<h2>Blank and over-range values</h2>
<p>An empty value blanks the display. A value that does not fit in the configured number of digits lights the top bar of every digit, or the bottom bar when it is negative.</p>
<div class="row">
<div class="cell"><smart-seven-segment id="b1" digits="4"></smart-seven-segment><span>value = null</span></div>
<div class="cell"><smart-seven-segment id="b2" digits="4"></smart-seven-segment><span>value = 123456</span></div>
</div>
</section>
<section>
<h2>Size and colour</h2>
<p>The height is set with a CSS variable. The colour follows the theme unless it is overridden.</p>
<div class="row">
<div class="cell"><smart-seven-segment id="s1" class="small" digits="4" precision-digits="1"></smart-seven-segment><span>small</span></div>
<div class="cell"><smart-seven-segment id="s2" class="large" digits="4" precision-digits="1"></smart-seven-segment><span>large</span></div>
<div class="cell"><smart-seven-segment id="s3" digits="4" precision-digits="1" color="#e5484d"></smart-seven-segment><span>explicit colour</span></div>
</div>
</section>
</div>
<!-- scripts -->
<script type="module" src="node_modules/smart-industrial/source/modules/smart.sevensegment.js"></script>
<script type="module" src="index.js"></script>
<script>
/* Shown once every element has rendered, so nothing moves on the way in (styles/demos.css). */
addEventListener('load', function () {
var all = Array.prototype.slice.call(document.querySelectorAll('*')),
ready = function () { document.body.classList.add('ready'); };
Promise.all(all.map(function (e) { return e.localName.indexOf('smart-') === 0 ? customElements.whenDefined(e.localName) : null; })).then(function () {
return Promise.all(all.filter(function (e) { return typeof e.whenRendered === 'function' && !e.isRendered; }).map(function (e) { return e.whenRendered(); }));
}).then(function () { requestAnimationFrame(function () { requestAnimationFrame(ready); }); }, ready);
});
</script>
</body>
</html>
index.js
/// <reference path="../../../source/typescript/smart.elements.d.ts" />
window.onload = function () {
const set = (id, value) => { document.getElementById(id).value = value; };
set('d1', 8420);
set('d2', 1247.85);
set('d3', -12.4);
set('z1', 4207);
set('z2', 4207);
set('b1', null);
set('b2', 123456);
set('s1', 62.4);
set('s2', 62.4);
set('s3', 62.4);
/* Live reading: a flow that drifts the way a real one does. */
const live = document.getElementById('live');
let tick = 0;
setInterval(function () {
tick += 0.08;
live.value = 312 + Math.sin(tick) * 48 + (Math.random() - 0.5) * 4;
}, 200);
live.value = 312;
};
styles.css
.smart-demo-container {
max-width: 960px;
}
section {
margin-bottom: 34px;
}
section h2 {
font-size: 16px;
font-weight: 500;
margin: 0 0 8px;
}
section p {
color: var(--smart-text-secondary-color);
margin: 0 0 14px;
max-width: 74ch;
}
.row {
display: flex;
flex-wrap: wrap;
gap: 22px;
align-items: flex-end;
}
.cell {
display: flex;
flex-direction: column;
gap: 8px;
}
.cell > span {
color: var(--smart-text-tertiary-color);
font-size: 11px;
}
.small {
--smart-seven-segment-height: 32px;
}
.large {
--smart-seven-segment-height: 84px;
}
/* ── Demo chrome, shared by the Industrial demos ─────────────────────────
Headings, prose, buttons and notes are the same on every demo page. This block
is appended by scripts and comes last, so it wins over the rules above. */
.smart-demo-container {
padding: 4px 0 32px;
}
.smart-demo-container section {
margin-bottom: 36px;
}
.smart-demo-container section h2 {
margin: 0 0 8px;
font-size: 17px;
font-weight: 600;
line-height: 1.35;
color: var(--smart-text-color);
}
.smart-demo-container #overview h2 {
margin-bottom: 10px;
font-size: 20px;
max-width: 78ch;
}
.smart-demo-container section > p {
margin: 0 0 14px;
max-width: 84ch;
font-size: 14px;
line-height: 1.55;
color: var(--smart-text-secondary-color);
}
.smart-demo-container code {
padding: 1px 5px;
border-radius: 2px;
background: var(--smart-ui-state-hover);
font-family: Consolas, "Courier New", monospace;
font-size: 12px;
}
.smart-demo-container .demo-actions {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px 10px;
margin-top: 12px;
}
.smart-demo-container .demo-actions label {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 13px;
color: var(--smart-text-color);
}
.smart-demo-container .demo-actions button,
.smart-demo-container .demo-button {
min-height: 30px;
padding: 0 12px;
border: 1px solid var(--smart-border);
border-radius: 3px;
background: var(--smart-industrial-panel-background, var(--smart-surface));
color: var(--smart-text-color);
font: inherit;
font-size: 13px;
font-weight: 500;
letter-spacing: 0;
text-transform: none;
cursor: pointer;
}
.smart-demo-container .demo-actions button:hover,
.smart-demo-container .demo-button:hover {
border-color: var(--smart-ui-state-border-hover);
background: var(--smart-ui-state-hover);
color: var(--smart-ui-state-color-hover);
}
.smart-demo-container .demo-actions button.demo-button-primary,
.smart-demo-container .demo-button-primary {
border-color: var(--smart-primary);
background: var(--smart-primary);
color: var(--smart-primary-color, #fff);
}
.smart-demo-container .demo-actions button[disabled],
.smart-demo-container .demo-button[disabled] {
opacity: 0.5;
cursor: default;
}
.smart-demo-container .demo-actions select,
.smart-demo-container .demo-actions input[type="text"],
.smart-demo-container .demo-actions input[type="number"] {
min-height: 30px;
padding: 2px 6px;
border: 1px solid var(--smart-border);
border-radius: 3px;
background: var(--smart-background);
color: var(--smart-text-color);
font: inherit;
font-size: 13px;
}
.smart-demo-container .hint,
.smart-demo-container .demo-log,
.smart-demo-container .demo-counts {
margin: 10px 0 0;
font-size: 12px;
line-height: 1.5;
color: var(--smart-text-secondary-color);
opacity: 1;
}
.smart-demo-container .demo-log,
.smart-demo-container .demo-counts {
font-family: Consolas, "Courier New", monospace;
}
.smart-demo-container .log {
list-style: none;
margin: 10px 0 0;
padding: 0;
font-size: 12px;
font-variant-numeric: tabular-nums;
color: var(--smart-text-secondary-color);
opacity: 1;
}
.smart-demo-container .log li {
padding: 2px 0;
}
The same demo in Angular, generated from the HTML demo. The frameworks guide has the project setup.
angular/app.component.html
<div class="angular-root" theme="industrial">
<div class="smart-demo-container">
<section id="overview">
<h2>Smart.SevenSegment is a numeric display in the style of a seven-segment LED readout.</h2>
<p>
It is used for panel meters, totalizers and batch counters. The display is rendered as SVG, so it stays sharp at any size, and takes its colour from the theme. Unlit segments are drawn faintly, as on a real LED display.
</p>
</section>
<section>
<h2>Live reading</h2>
<div class="row">
<smart-seven-segment id="live" [digits]="5" [precisionDigits]="1" unit="L/min"></smart-seven-segment>
</div>
</section>
<section>
<h2>Digits and precision</h2>
<div class="row">
<div class="cell"><smart-seven-segment id="d1" [digits]="4"></smart-seven-segment><span>4 digits, no decimals</span></div>
<div class="cell"><smart-seven-segment id="d2" [digits]="6" [precisionDigits]="2" unit="kWh"></smart-seven-segment><span>6 digits, 2 decimals</span></div>
<div class="cell"><smart-seven-segment id="d3" [digits]="4" [precisionDigits]="1" unit="°C"></smart-seven-segment><span>negative values</span></div>
</div>
</section>
<section>
<h2>Leading zeros</h2>
<p>A counter usually shows leading zeros; a measurement usually does not.</p>
<div class="row">
<div class="cell"><smart-seven-segment id="z1" [digits]="6"></smart-seven-segment><span>blank padding</span></div>
<div class="cell"><smart-seven-segment id="z2" [digits]="6" [leadingZeros]="true"></smart-seven-segment><span>leading zeros</span></div>
</div>
</section>
<section>
<h2>Blank and over-range values</h2>
<p>An empty value blanks the display. A value that does not fit in the configured number of digits lights the top bar of every digit, or the bottom bar when it is negative.</p>
<div class="row">
<div class="cell"><smart-seven-segment id="b1" [digits]="4"></smart-seven-segment><span>value = null</span></div>
<div class="cell"><smart-seven-segment id="b2" [digits]="4"></smart-seven-segment><span>value = 123456</span></div>
</div>
</section>
<section>
<h2>Size and colour</h2>
<p>The height is set with a CSS variable. The colour follows the theme unless it is overridden.</p>
<div class="row">
<div class="cell"><smart-seven-segment id="s1" class="small" [digits]="4" [precisionDigits]="1"></smart-seven-segment><span>small</span></div>
<div class="cell"><smart-seven-segment id="s2" class="large" [digits]="4" [precisionDigits]="1"></smart-seven-segment><span>large</span></div>
<div class="cell"><smart-seven-segment id="s3" [digits]="4" [precisionDigits]="1" color="#e5484d"></smart-seven-segment><span>explicit colour</span></div>
</div>
</section>
</div>
</div>
angular/app.component.ts
import { Component, AfterViewInit, OnDestroy } from '@angular/core';
import { SevenSegmentModule } from 'smart-industrial/angular/sevensegment';
import { runDemo } from './demo';
/**
* Smart.UI Industrial - SevenSegment in Angular.
*
* The template is the HTML demo's markup: the elements are the wrappers, so what is
* written on them is checked against their inputs. demo.ts drives them the way the
* plant's data would, once every element in the view has rendered.
*/
@Component({
selector: 'app-root',
standalone: true,
imports: [SevenSegmentModule],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent implements AfterViewInit, OnDestroy {
private unmounted = false;
ngAfterViewInit(): void {
const root = document.querySelector('.angular-root') as HTMLElement,
pending: Promise<void>[] = [];
root.querySelectorAll('*').forEach((element: any) => {
if (typeof element.whenRendered === 'function' && !element.isRendered) {
pending.push(element.whenRendered());
}
});
Promise.all(pending).then(() => {
if (!this.unmounted) {
runDemo();
}
});
}
ngOnDestroy(): void {
this.unmounted = true;
}
}
angular/demo.ts
// @ts-nocheck
/* The HTML demo's script, as it was written: page code that feeds the elements, not a typed
API. The types are on the wrappers in app.component.ts. */
export function runDemo(): void {
const set = (id, value) => { document.getElementById(id).value = value; };
set('d1', 8420);
set('d2', 1247.85);
set('d3', -12.4);
set('z1', 4207);
set('z2', 4207);
set('b1', null);
set('b2', 123456);
set('s1', 62.4);
set('s2', 62.4);
set('s3', 62.4);
/* Live reading: a flow that drifts the way a real one does. */
const live = document.getElementById('live');
let tick = 0;
setInterval(function () {
tick += 0.08;
live.value = 312 + Math.sin(tick) * 48 + (Math.random() - 0.5) * 4;
}, 200);
live.value = 312;
}
angular/app.component.css
.smart-demo-container {
max-width: 960px;
}
section {
margin-bottom: 34px;
}
section h2 {
font-size: 16px;
font-weight: 500;
margin: 0 0 8px;
}
section p {
color: var(--smart-text-secondary-color);
margin: 0 0 14px;
max-width: 74ch;
}
.row {
display: flex;
flex-wrap: wrap;
gap: 22px;
align-items: flex-end;
}
.cell {
display: flex;
flex-direction: column;
gap: 8px;
}
.cell > span {
color: var(--smart-text-tertiary-color);
font-size: 11px;
}
.small {
--smart-seven-segment-height: 32px;
}
.large {
--smart-seven-segment-height: 84px;
}
/* ── Demo chrome, shared by the Industrial demos ─────────────────────────
Headings, prose, buttons and notes are the same on every demo page. This block
is appended by scripts and comes last, so it wins over the rules above. */
.smart-demo-container {
padding: 4px 0 32px;
}
.smart-demo-container section {
margin-bottom: 36px;
}
.smart-demo-container section h2 {
margin: 0 0 8px;
font-size: 17px;
font-weight: 600;
line-height: 1.35;
color: var(--smart-text-color);
}
.smart-demo-container #overview h2 {
margin-bottom: 10px;
font-size: 20px;
max-width: 78ch;
}
.smart-demo-container section > p {
margin: 0 0 14px;
max-width: 84ch;
font-size: 14px;
line-height: 1.55;
color: var(--smart-text-secondary-color);
}
.smart-demo-container code {
padding: 1px 5px;
border-radius: 2px;
background: var(--smart-ui-state-hover);
font-family: Consolas, "Courier New", monospace;
font-size: 12px;
}
.smart-demo-container .demo-actions {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px 10px;
margin-top: 12px;
}
.smart-demo-container .demo-actions label {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 13px;
color: var(--smart-text-color);
}
.smart-demo-container .demo-actions button,
.smart-demo-container .demo-button {
min-height: 30px;
padding: 0 12px;
border: 1px solid var(--smart-border);
border-radius: 3px;
background: var(--smart-industrial-panel-background, var(--smart-surface));
color: var(--smart-text-color);
font: inherit;
font-size: 13px;
font-weight: 500;
letter-spacing: 0;
text-transform: none;
cursor: pointer;
}
.smart-demo-container .demo-actions button:hover,
.smart-demo-container .demo-button:hover {
border-color: var(--smart-ui-state-border-hover);
background: var(--smart-ui-state-hover);
color: var(--smart-ui-state-color-hover);
}
.smart-demo-container .demo-actions button.demo-button-primary,
.smart-demo-container .demo-button-primary {
border-color: var(--smart-primary);
background: var(--smart-primary);
color: var(--smart-primary-color, #fff);
}
.smart-demo-container .demo-actions button[disabled],
.smart-demo-container .demo-button[disabled] {
opacity: 0.5;
cursor: default;
}
.smart-demo-container .demo-actions select,
.smart-demo-container .demo-actions input[type="text"],
.smart-demo-container .demo-actions input[type="number"] {
min-height: 30px;
padding: 2px 6px;
border: 1px solid var(--smart-border);
border-radius: 3px;
background: var(--smart-background);
color: var(--smart-text-color);
font: inherit;
font-size: 13px;
}
.smart-demo-container .hint,
.smart-demo-container .demo-log,
.smart-demo-container .demo-counts {
margin: 10px 0 0;
font-size: 12px;
line-height: 1.5;
color: var(--smart-text-secondary-color);
opacity: 1;
}
.smart-demo-container .demo-log,
.smart-demo-container .demo-counts {
font-family: Consolas, "Courier New", monospace;
}
.smart-demo-container .log {
list-style: none;
margin: 10px 0 0;
padding: 0;
font-size: 12px;
font-variant-numeric: tabular-nums;
color: var(--smart-text-secondary-color);
opacity: 1;
}
.smart-demo-container .log li {
padding: 2px 0;
}
The same demo in React, generated from the HTML demo. The frameworks guide has the project setup.
react/App.jsx
import 'smart-industrial/source/styles/smart.default.css';
import 'smart-industrial/source/styles/smart.industrial-elements.css';
import 'smart-industrial/source/styles/smart.industrial.css';
import 'smart-industrial/source/styles/smart.industrial-dark.css';
import './App.css';
import React from 'react';
import { SevenSegment } from 'smart-industrial/react/sevensegment';
/* The demo logic is the HTML demo's: it feeds the elements the way a plant's data would. */
const App = () => {
const root = React.useRef(null);
React.useEffect(() => {
/* The elements render after React has mounted them, and the demo's logic - written
for a page's load event - reads their parts, so it waits for every element in the
tree to have rendered first. */
const pending = Array.from(root.current.querySelectorAll('*'))
.filter((element) => typeof element.whenRendered === 'function' && !element.isRendered)
.map((element) => element.whenRendered());
let unmounted = false;
Promise.all(pending).then(() => {
if (unmounted) {
return;
}
const set = (id, value) => { document.getElementById(id).value = value; };
set('d1', 8420);
set('d2', 1247.85);
set('d3', -12.4);
set('z1', 4207);
set('z2', 4207);
set('b1', null);
set('b2', 123456);
set('s1', 62.4);
set('s2', 62.4);
set('s3', 62.4);
/* Live reading: a flow that drifts the way a real one does. */
const live = document.getElementById('live');
let tick = 0;
setInterval(function () {
tick += 0.08;
live.value = 312 + Math.sin(tick) * 48 + (Math.random() - 0.5) * 4;
}, 200);
live.value = 312;
});
return () => {
unmounted = true;
};
}, []);
return (
<div className="react-root" ref={root} theme="industrial">
<div className="smart-demo-container">
<section id="overview">
<h2>Smart.SevenSegment is a numeric display in the style of a seven-segment LED readout.</h2>
<p>It is used for panel meters, totalizers and batch counters. The display is rendered as SVG, so it stays sharp at any size, and takes its colour from the theme. Unlit segments are drawn faintly, as on a real LED display.</p>
</section>
<section>
<h2>Live reading</h2>
<div className="row">
<SevenSegment id="live" digits={5} precisionDigits={1} unit="L/min"></SevenSegment>
</div>
</section>
<section>
<h2>Digits and precision</h2>
<div className="row">
<div className="cell">
<SevenSegment id="d1" digits={4}></SevenSegment>
<span>4 digits, no decimals</span>
</div>
<div className="cell">
<SevenSegment id="d2" digits={6} precisionDigits={2} unit="kWh"></SevenSegment>
<span>6 digits, 2 decimals</span>
</div>
<div className="cell">
<SevenSegment id="d3" digits={4} precisionDigits={1} unit="°C"></SevenSegment>
<span>negative values</span>
</div>
</div>
</section>
<section>
<h2>Leading zeros</h2>
<p>A counter usually shows leading zeros; a measurement usually does not.</p>
<div className="row">
<div className="cell">
<SevenSegment id="z1" digits={6}></SevenSegment>
<span>blank padding</span>
</div>
<div className="cell">
<SevenSegment id="z2" digits={6} leadingZeros></SevenSegment>
<span>leading zeros</span>
</div>
</div>
</section>
<section>
<h2>Blank and over-range values</h2>
<p>An empty value blanks the display. A value that does not fit in the configured number of digits lights the top bar of every digit, or the bottom bar when it is negative.</p>
<div className="row">
<div className="cell">
<SevenSegment id="b1" digits={4}></SevenSegment>
<span>value = null</span>
</div>
<div className="cell">
<SevenSegment id="b2" digits={4}></SevenSegment>
<span>value = 123456</span>
</div>
</div>
</section>
<section>
<h2>Size and colour</h2>
<p>The height is set with a CSS variable. The colour follows the theme unless it is overridden.</p>
<div className="row">
<div className="cell">
<SevenSegment id="s1" className="small" digits={4} precisionDigits={1}></SevenSegment>
<span>small</span>
</div>
<div className="cell">
<SevenSegment id="s2" className="large" digits={4} precisionDigits={1}></SevenSegment>
<span>large</span>
</div>
<div className="cell">
<SevenSegment id="s3" digits={4} precisionDigits={1} color="#e5484d"></SevenSegment>
<span>explicit colour</span>
</div>
</div>
</section>
</div>
</div>
);
};
export default App;
react/App.css
.smart-demo-container {
max-width: 960px;
}
section {
margin-bottom: 34px;
}
section h2 {
font-size: 16px;
font-weight: 500;
margin: 0 0 8px;
}
section p {
color: var(--smart-text-secondary-color);
margin: 0 0 14px;
max-width: 74ch;
}
.row {
display: flex;
flex-wrap: wrap;
gap: 22px;
align-items: flex-end;
}
.cell {
display: flex;
flex-direction: column;
gap: 8px;
}
.cell > span {
color: var(--smart-text-tertiary-color);
font-size: 11px;
}
.small {
--smart-seven-segment-height: 32px;
}
.large {
--smart-seven-segment-height: 84px;
}
/* ── Demo chrome, shared by the Industrial demos ─────────────────────────
Headings, prose, buttons and notes are the same on every demo page. This block
is appended by scripts and comes last, so it wins over the rules above. */
.smart-demo-container {
padding: 4px 0 32px;
}
.smart-demo-container section {
margin-bottom: 36px;
}
.smart-demo-container section h2 {
margin: 0 0 8px;
font-size: 17px;
font-weight: 600;
line-height: 1.35;
color: var(--smart-text-color);
}
.smart-demo-container #overview h2 {
margin-bottom: 10px;
font-size: 20px;
max-width: 78ch;
}
.smart-demo-container section > p {
margin: 0 0 14px;
max-width: 84ch;
font-size: 14px;
line-height: 1.55;
color: var(--smart-text-secondary-color);
}
.smart-demo-container code {
padding: 1px 5px;
border-radius: 2px;
background: var(--smart-ui-state-hover);
font-family: Consolas, "Courier New", monospace;
font-size: 12px;
}
.smart-demo-container .demo-actions {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px 10px;
margin-top: 12px;
}
.smart-demo-container .demo-actions label {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 13px;
color: var(--smart-text-color);
}
.smart-demo-container .demo-actions button,
.smart-demo-container .demo-button {
min-height: 30px;
padding: 0 12px;
border: 1px solid var(--smart-border);
border-radius: 3px;
background: var(--smart-industrial-panel-background, var(--smart-surface));
color: var(--smart-text-color);
font: inherit;
font-size: 13px;
font-weight: 500;
letter-spacing: 0;
text-transform: none;
cursor: pointer;
}
.smart-demo-container .demo-actions button:hover,
.smart-demo-container .demo-button:hover {
border-color: var(--smart-ui-state-border-hover);
background: var(--smart-ui-state-hover);
color: var(--smart-ui-state-color-hover);
}
.smart-demo-container .demo-actions button.demo-button-primary,
.smart-demo-container .demo-button-primary {
border-color: var(--smart-primary);
background: var(--smart-primary);
color: var(--smart-primary-color, #fff);
}
.smart-demo-container .demo-actions button[disabled],
.smart-demo-container .demo-button[disabled] {
opacity: 0.5;
cursor: default;
}
.smart-demo-container .demo-actions select,
.smart-demo-container .demo-actions input[type="text"],
.smart-demo-container .demo-actions input[type="number"] {
min-height: 30px;
padding: 2px 6px;
border: 1px solid var(--smart-border);
border-radius: 3px;
background: var(--smart-background);
color: var(--smart-text-color);
font: inherit;
font-size: 13px;
}
.smart-demo-container .hint,
.smart-demo-container .demo-log,
.smart-demo-container .demo-counts {
margin: 10px 0 0;
font-size: 12px;
line-height: 1.5;
color: var(--smart-text-secondary-color);
opacity: 1;
}
.smart-demo-container .demo-log,
.smart-demo-container .demo-counts {
font-family: Consolas, "Courier New", monospace;
}
.smart-demo-container .log {
list-style: none;
margin: 10px 0 0;
padding: 0;
font-size: 12px;
font-variant-numeric: tabular-nums;
color: var(--smart-text-secondary-color);
opacity: 1;
}
.smart-demo-container .log li {
padding: 2px 0;
}
The same demo in Vue, generated from the HTML demo. The frameworks guide has the project setup.
vue/App.vue
<template>
<div class="vue-root" theme="industrial" v-pre>
<div class="smart-demo-container">
<section id="overview">
<h2>Smart.SevenSegment is a numeric display in the style of a seven-segment LED readout.</h2>
<p>
It is used for panel meters, totalizers and batch counters. The display is rendered as SVG, so it stays sharp at any size, and takes its colour from the theme. Unlit segments are drawn faintly, as on a real LED display.
</p>
</section>
<section>
<h2>Live reading</h2>
<div class="row">
<smart-seven-segment id="live" digits="5" precision-digits="1" unit="L/min"></smart-seven-segment>
</div>
</section>
<section>
<h2>Digits and precision</h2>
<div class="row">
<div class="cell"><smart-seven-segment id="d1" digits="4"></smart-seven-segment><span>4 digits, no decimals</span></div>
<div class="cell"><smart-seven-segment id="d2" digits="6" precision-digits="2" unit="kWh"></smart-seven-segment><span>6 digits, 2 decimals</span></div>
<div class="cell"><smart-seven-segment id="d3" digits="4" precision-digits="1" unit="°C"></smart-seven-segment><span>negative values</span></div>
</div>
</section>
<section>
<h2>Leading zeros</h2>
<p>A counter usually shows leading zeros; a measurement usually does not.</p>
<div class="row">
<div class="cell"><smart-seven-segment id="z1" digits="6"></smart-seven-segment><span>blank padding</span></div>
<div class="cell"><smart-seven-segment id="z2" digits="6" leading-zeros></smart-seven-segment><span>leading zeros</span></div>
</div>
</section>
<section>
<h2>Blank and over-range values</h2>
<p>An empty value blanks the display. A value that does not fit in the configured number of digits lights the top bar of every digit, or the bottom bar when it is negative.</p>
<div class="row">
<div class="cell"><smart-seven-segment id="b1" digits="4"></smart-seven-segment><span>value = null</span></div>
<div class="cell"><smart-seven-segment id="b2" digits="4"></smart-seven-segment><span>value = 123456</span></div>
</div>
</section>
<section>
<h2>Size and colour</h2>
<p>The height is set with a CSS variable. The colour follows the theme unless it is overridden.</p>
<div class="row">
<div class="cell"><smart-seven-segment id="s1" class="small" digits="4" precision-digits="1"></smart-seven-segment><span>small</span></div>
<div class="cell"><smart-seven-segment id="s2" class="large" digits="4" precision-digits="1"></smart-seven-segment><span>large</span></div>
<div class="cell"><smart-seven-segment id="s3" digits="4" precision-digits="1" color="#e5484d"></smart-seven-segment><span>explicit colour</span></div>
</div>
</section>
</div>
</div>
</template>
<script>
import { onMounted } from "vue";
import "smart-industrial/source/styles/smart.default.css";
import "smart-industrial/source/styles/smart.industrial-elements.css";
import "smart-industrial/source/styles/smart.industrial.css";
import "smart-industrial/source/styles/smart.industrial-dark.css";
import "smart-industrial/source/modules/smart.sevensegment.js";
export default {
name: "app",
setup() {
onMounted(() => {
/* The elements render after Vue has mounted them, and the demo's logic - written for
a page's load event - reads their parts, so it waits for every element in the tree
to have rendered first. */
const pending = Array.from(document.querySelector(".vue-root").querySelectorAll("*"))
.filter((element) => typeof element.whenRendered === "function" && !element.isRendered)
.map((element) => element.whenRendered());
Promise.all(pending).then(() => {
const set = (id, value) => { document.getElementById(id).value = value; };
set('d1', 8420);
set('d2', 1247.85);
set('d3', -12.4);
set('z1', 4207);
set('z2', 4207);
set('b1', null);
set('b2', 123456);
set('s1', 62.4);
set('s2', 62.4);
set('s3', 62.4);
/* Live reading: a flow that drifts the way a real one does. */
const live = document.getElementById('live');
let tick = 0;
setInterval(function () {
tick += 0.08;
live.value = 312 + Math.sin(tick) * 48 + (Math.random() - 0.5) * 4;
}, 200);
live.value = 312;
});
});
}
};
</script>
<style>
.smart-demo-container {
max-width: 960px;
}
section {
margin-bottom: 34px;
}
section h2 {
font-size: 16px;
font-weight: 500;
margin: 0 0 8px;
}
section p {
color: var(--smart-text-secondary-color);
margin: 0 0 14px;
max-width: 74ch;
}
.row {
display: flex;
flex-wrap: wrap;
gap: 22px;
align-items: flex-end;
}
.cell {
display: flex;
flex-direction: column;
gap: 8px;
}
.cell > span {
color: var(--smart-text-tertiary-color);
font-size: 11px;
}
.small {
--smart-seven-segment-height: 32px;
}
.large {
--smart-seven-segment-height: 84px;
}
/* ── Demo chrome, shared by the Industrial demos ─────────────────────────
Headings, prose, buttons and notes are the same on every demo page. This block
is appended by scripts and comes last, so it wins over the rules above. */
.smart-demo-container {
padding: 4px 0 32px;
}
.smart-demo-container section {
margin-bottom: 36px;
}
.smart-demo-container section h2 {
margin: 0 0 8px;
font-size: 17px;
font-weight: 600;
line-height: 1.35;
color: var(--smart-text-color);
}
.smart-demo-container #overview h2 {
margin-bottom: 10px;
font-size: 20px;
max-width: 78ch;
}
.smart-demo-container section > p {
margin: 0 0 14px;
max-width: 84ch;
font-size: 14px;
line-height: 1.55;
color: var(--smart-text-secondary-color);
}
.smart-demo-container code {
padding: 1px 5px;
border-radius: 2px;
background: var(--smart-ui-state-hover);
font-family: Consolas, "Courier New", monospace;
font-size: 12px;
}
.smart-demo-container .demo-actions {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px 10px;
margin-top: 12px;
}
.smart-demo-container .demo-actions label {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 13px;
color: var(--smart-text-color);
}
.smart-demo-container .demo-actions button,
.smart-demo-container .demo-button {
min-height: 30px;
padding: 0 12px;
border: 1px solid var(--smart-border);
border-radius: 3px;
background: var(--smart-industrial-panel-background, var(--smart-surface));
color: var(--smart-text-color);
font: inherit;
font-size: 13px;
font-weight: 500;
letter-spacing: 0;
text-transform: none;
cursor: pointer;
}
.smart-demo-container .demo-actions button:hover,
.smart-demo-container .demo-button:hover {
border-color: var(--smart-ui-state-border-hover);
background: var(--smart-ui-state-hover);
color: var(--smart-ui-state-color-hover);
}
.smart-demo-container .demo-actions button.demo-button-primary,
.smart-demo-container .demo-button-primary {
border-color: var(--smart-primary);
background: var(--smart-primary);
color: var(--smart-primary-color, #fff);
}
.smart-demo-container .demo-actions button[disabled],
.smart-demo-container .demo-button[disabled] {
opacity: 0.5;
cursor: default;
}
.smart-demo-container .demo-actions select,
.smart-demo-container .demo-actions input[type="text"],
.smart-demo-container .demo-actions input[type="number"] {
min-height: 30px;
padding: 2px 6px;
border: 1px solid var(--smart-border);
border-radius: 3px;
background: var(--smart-background);
color: var(--smart-text-color);
font: inherit;
font-size: 13px;
}
.smart-demo-container .hint,
.smart-demo-container .demo-log,
.smart-demo-container .demo-counts {
margin: 10px 0 0;
font-size: 12px;
line-height: 1.5;
color: var(--smart-text-secondary-color);
opacity: 1;
}
.smart-demo-container .demo-log,
.smart-demo-container .demo-counts {
font-family: Consolas, "Courier New", monospace;
}
.smart-demo-container .log {
list-style: none;
margin: 10px 0 0;
padding: 0;
font-size: 12px;
font-variant-numeric: tabular-nums;
color: var(--smart-text-secondary-color);
opacity: 1;
}
.smart-demo-container .log li {
padding: 2px 0;
}
</style>
What the demo shows
- Live reading
- Digits and precision
- Leading zeros
- Blank and over-range values
- Size and colour
Also in instrument readouts and controls
Bar GraphBit FieldJog PanelKnobMomentary ButtonNumeric KeypadPanel MeterSelector SwitchThermometerTouch Keyboard