Metric
One validated value or aggregate with units, scope and unavailable state.
Use the web element directly without the semantic runtime.
A registered presentation adapter can bind this component to host-owned meaning and state.
The standard recipe resolver does not select this component automatically.
Import and live example#
One exact count metric scoped to the authorized people result.
Interactive preview requires JavaScript.
View the complete example source
import {registerAeliqoElements} from "@varendo/web";
import {
AeliqoCardCollectionElement,
AeliqoDeltaElement,
AeliqoDetailElement,
AeliqoFilterBuilderElement,
AeliqoKeyValueElement,
AeliqoMetricElement,
AeliqoRecordListElement,
AeliqoSelectionSummaryElement,
AeliqoTableElement,
type AeliqoKeyValueItem,
type AeliqoTableColumn,
type AeliqoTableRow,
} from "@varendo/web/data";
import type {ResultRef,
Scalar,
} from "@varendo/core";
import type {AeliqoDataColumn, AeliqoDataScope, AeliqoFieldOption} from "@varendo/web/data";
const catalogRef: ResultRef = {
id: "aeliqo-catalog-example",
revision: "1",
outputId: "people",
queryDigest: "catalog-query",
scopeDigest: "catalog-scope",
};
const catalogRows: readonly Readonly<Record<string, Scalar>>[] = [
{id: "ada", name: "Ada Lovelace", team: "Research", date: "2026-09-08", amount: 120},
{id: "lin", name: "Lin Chen", team: "Product", date: "2026-09-09", amount: 96},
{id: "grace", name: "Grace Hopper", team: "Research", date: "2026-09-10", amount: 144},
];
const catalogColumns: readonly AeliqoDataColumn[] = [
{key: "id", label: "ID", type: "text", sortable: true},
{key: "name", label: "Name", type: "text", sortable: true},
{key: "team", label: "Team", type: "text"},
{key: "date", label: "Date", type: "date", sortable: true},
{key: "amount", label: "Amount", type: "integer", align: "end"},
];
const catalogFields: readonly AeliqoFieldOption[] = [
{id: "name", label: "Name", type: "text"},
{id: "team", label: "Team", type: "text"},
{id: "amount", label: "Amount", type: "integer"},
];
const catalogScope: AeliqoDataScope = {
loaded: catalogRows.length,
filteredTotal: catalogRows.length,
populationDigest: catalogRef.scopeDigest,
kind: "filtered",
label: "Authorized people",
};
const tableColumns: readonly AeliqoTableColumn[] = catalogColumns.map(({key, label, sortable, align}) => ({key, label, ...(sortable === undefined ? {} : {sortable}), ...(align === undefined ? {} : {align})}));
const tableRows: readonly AeliqoTableRow[] = catalogRows.map((row) => ({id: row.id ?? null, name: row.name ?? null, team: row.team ?? null, date: row.date ?? null, amount: row.amount ?? null}));
const personKeys = ["string:3:ada", "string:5:grace"] as const;
registerAeliqoElements();
const host = document.querySelector<HTMLElement>("#aeliqo-example") ?? (() => {
const created = document.createElement("div");
created.id = "aeliqo-example";
(document.body ?? document.documentElement).append(created);
return created;
})();
function createCatalogRoot(container: HTMLElement): HTMLElement {
const root = document.createElement("div");
root.dataset.catalogSourceRoot = "true";
root.style.display = "grid";
root.style.gap = "12px";
container.append(root);
return root;
}
function createCatalogElement<T extends HTMLElement>(tagName: string, container: HTMLElement): T {
const element = document.createElement(tagName) as T;
element.setAttribute("data-aeliqo-theme", "light");
container.append(element);
return element;
}
function appendSlottedText(root: HTMLElement, slot: string, textContent: string): void {
const content = document.createElement("span");
content.slot = slot;
content.textContent = textContent;
root.append(content);
}
const root = createCatalogRoot(host);
(((root) => {
const element = createCatalogElement<AeliqoMetricElement>("aeliqo-metric", root);
element.label = "Authorized people";
element.value = catalogRows.length;
element.unit = "records";
element.scope = catalogScope;
element.description = "Current filtered result";
}))(root);
Purpose#
Show one labeled value with its unit and scope. A missing value reads as unavailable, never as an invented zero.
When to use it#
- Show a single KPI, count, or total on a dashboard.
- Report a value the application already computed and validated.
- Attach a unit, description, and scope to a number.
- Show an unavailable state when the value is missing.
When to use a different component#
- Use Delta to compare a current value against a baseline.
- Use Trend to show how a value changes over time.
Properties and defaults#
Value and displayValue are host supplied; the component formats and labels without computing a metric.
| Property | Use and ownership | Declared type | Initial value |
|---|---|---|---|
label | Provides the visible label and accessible name for the component. | string | '' |
value | Controls the current value. Apply accepted user proposals back to this property. | AeliqoDataValue | undefined | undefined |
displayValue | Provides the exact preformatted value shown to users when host formatting is authoritative. | string | undefined | undefined |
unit | Provides the unit label associated with the numeric value. | string | '' |
description | Provides supporting text associated with the control or value. | string | '' |
scope | Supplies the visible authorization and population scope associated with the displayed value or rows. | AeliqoDataScope | undefined | undefined |
status | Supplies the explicit ready, loading, empty, partial, stale, or error state. | AeliqoDataStatus | 'ready' |
message | Provides the user-facing status, error, or recovery message. | string | '' |
format | Selects the declared value format. It changes presentation without changing metric meaning. | AeliqoMetricFormat | 'plain' |
locale | Selects locale-sensitive formatting and parsing behavior. | string | '' |
Events#
- None; read-only presentation
States and failure handling#
Relevant states:
- ready
- loading
- empty
- partial
- stale
- error
Expected result: The exact value and scope are displayed without silently expanding or recalculating the result.
Keyboard, focus, and accessibility#
Keyboard behavior:
- Not focusable unless a numeric value exposes review focus
Exposed semantics:
- aria-describedby
- dd
- dl
- dt
- role
Responsive behavior#
Let long labels and formatted values wrap instead of clipping. Keep the unit visually associated with the value at text zoom.
Style hooks#
- Shadow parts:
description,label,metric,number,scope,status,unit,value - Varendo design tokens referenced:
--aeliqo-color-muted,--aeliqo-space-4,--aeliqo-typography-font-size-caption,--aeliqo-typography-font-size-heading,--aeliqo-typography-font-weight-semibold
Related components#
Generated TypeScript declaration#
View generated declaration
export declare class AeliqoMetricElement extends LitElement {
static readonly aeliqoVersion = "0.1.0";
static readonly properties: {
label: {
type: StringConstructor;
};
value: {
attribute: boolean;
};
displayValue: {
attribute: string;
type: StringConstructor;
};
unit: {
type: StringConstructor;
};
description: {
type: StringConstructor;
};
scope: {
attribute: boolean;
};
status: {
type: StringConstructor;
};
message: {
type: StringConstructor;
};
format: {
type: StringConstructor;
};
locale: {
type: StringConstructor;
};
};
label: string;
value: AeliqoDataValue | undefined;
displayValue: string | undefined;
unit: string;
description: string;
scope: AeliqoDataScope | undefined;
status: AeliqoDataStatus;
message: string;
format: AeliqoMetricFormat;
locale: string;
protected render(): import("lit").TemplateResult<1>;
private get effectiveStatus();
private isUnavailable;
private valueForStatus;
private renderUnit;
private get hasDisplayableValue();
private describedBy;
private renderStatus;
private get scopeText();
private get numericValue();
private renderValue;
static readonly styles: import("lit").CSSResult[];
}Version#
This page documents the Varendo 0.6 component contract.
