Skeleton, Breadcrumbs, Link, Button, Image, Meter, NumberField Floating components: Tooltip (hover/focus), Popover (click, with focus trap and dismiss), HoverCard (hover with safe area). Simple components: Alert (role=alert), Badge (role=status), Skeleton (loading placeholder with data attributes). Navigation: Breadcrumbs (nav>ol>li with separators), Link (accessible anchor with disabled), Button (with disabled click suppression). Data/Form: Image (Img+Fallback with loading status), Meter (like Progress for known ranges), NumberField (spinbutton with inc/dec). 302 tests across 46 files, typecheck clean, build produces 176 files.
46 lines
1.4 KiB
TypeScript
46 lines
1.4 KiB
TypeScript
// packages/core/src/components/meter/meter.tsx
|
|
import type { JSX } from "solid-js";
|
|
import { splitProps } from "solid-js";
|
|
|
|
export interface MeterProps extends JSX.HTMLAttributes<HTMLDivElement> {
|
|
/** Current value of the meter. */
|
|
value: number;
|
|
/** Minimum value. @default 0 */
|
|
min?: number | undefined;
|
|
/** Maximum value. @default 100 */
|
|
max?: number | undefined;
|
|
/** Custom label function for aria-valuetext. */
|
|
getValueLabel?: ((value: number, max: number) => string) | undefined;
|
|
}
|
|
|
|
/**
|
|
* Displays a scalar measurement within a known range (e.g., disk usage, password strength).
|
|
* Unlike Progress, Meter always has a determinate value.
|
|
*/
|
|
export function Meter(props: MeterProps): JSX.Element {
|
|
const [local, rest] = splitProps(props, ["value", "min", "max", "getValueLabel"]);
|
|
|
|
const min = () => local.min ?? 0;
|
|
const max = () => local.max ?? 100;
|
|
|
|
const valueLabel = (): string | undefined => {
|
|
if (local.getValueLabel) return local.getValueLabel(local.value, max());
|
|
return undefined;
|
|
};
|
|
|
|
return (
|
|
// biome-ignore lint/a11y/useFocusableInteractive: meter is read-only, not interactive
|
|
<div
|
|
role="meter"
|
|
aria-valuenow={local.value}
|
|
aria-valuemin={min()}
|
|
aria-valuemax={max()}
|
|
aria-valuetext={valueLabel()}
|
|
data-value={local.value}
|
|
data-min={min()}
|
|
data-max={max()}
|
|
{...rest}
|
|
/>
|
|
);
|
|
}
|