Gauge: no value arc at the minimum
Docs / docs (push) Successful in 22s
Playwright Tests / test-playwright (1, 2) (push) Failing after 3m53s
Playwright Tests / test-playwright (2, 2) (push) Successful in 1m57s
pre-commit / pre-commit (push) Failing after 2m37s
Test Backend / test-backend (push) Failing after 3m6s
Compose Smoke Test / test-compose (push) Successful in 30s
Playwright Tests / merge-reports (push) Successful in 1m55s
Docs / docs (push) Successful in 22s
Playwright Tests / test-playwright (1, 2) (push) Failing after 3m53s
Playwright Tests / test-playwright (2, 2) (push) Successful in 1m57s
pre-commit / pre-commit (push) Failing after 2m37s
Test Backend / test-backend (push) Failing after 3m6s
Compose Smoke Test / test-compose (push) Successful in 30s
Playwright Tests / merge-reports (push) Successful in 1m55s
At 0 the value arc is a zero-length dash (pathLength 0), and its round caps still painted a primary dot on the dial in every look. The arc is now transparent while its fraction is not above 0. The widget spec puts a gauge at 0 on its panel and checks it in each look; its tile count, stale since the buttons widget, is 11. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
3c08e6ef1e
commit
f067fb60d4
@@ -64,6 +64,9 @@ export function Gauge({ value, min, max, precision, unit, label }: GaugeProps) {
|
||||
? 0
|
||||
: Math.min(1, Math.max(0, (value - min) / (max - min || 1))),
|
||||
)
|
||||
// At the minimum the reading is a zero-length dash, and its round caps would
|
||||
// still paint a dot on the dial. Nothing reads there, so nothing is drawn.
|
||||
const drawn = useTransform(fraction, (at) => (at > 0 ? 1 : 0))
|
||||
const { label: reading, numeric } = useAnimatedNumber(value, precision)
|
||||
return (
|
||||
<div className="flex min-h-0 flex-1 items-center justify-center">
|
||||
@@ -86,7 +89,7 @@ export function Gauge({ value, min, max, precision, unit, label }: GaugeProps) {
|
||||
fraction itself. */}
|
||||
<motion.path
|
||||
d={arcPath(GAUGE_START, GAUGE_START + GAUGE_SWEEP)}
|
||||
style={{ pathLength: fraction }}
|
||||
style={{ pathLength: fraction, opacity: drawn }}
|
||||
fill="none"
|
||||
stroke="var(--primary)"
|
||||
strokeWidth={9}
|
||||
|
||||
@@ -63,6 +63,9 @@ export function Gauge({ value, min, max, precision, unit, label }: GaugeProps) {
|
||||
? 0
|
||||
: Math.min(1, Math.max(0, (value - min) / (max - min || 1))),
|
||||
)
|
||||
// At the minimum the reading is a zero-length dash, and its round caps would
|
||||
// still paint a dot on the dial. Nothing reads there, so nothing is drawn.
|
||||
const drawn = useTransform(fraction, (at) => (at > 0 ? 1 : 0))
|
||||
const { label: reading, numeric } = useAnimatedNumber(value, precision)
|
||||
return (
|
||||
<div className="flex min-h-0 flex-1 items-center justify-center">
|
||||
@@ -91,6 +94,7 @@ export function Gauge({ value, min, max, precision, unit, label }: GaugeProps) {
|
||||
// fills and the active controls do.
|
||||
style={{
|
||||
pathLength: fraction,
|
||||
opacity: drawn,
|
||||
filter: "drop-shadow(0 0 4px var(--primary))",
|
||||
}}
|
||||
fill="none"
|
||||
|
||||
@@ -62,6 +62,9 @@ export function Gauge({ value, min, max, precision, unit, label }: GaugeProps) {
|
||||
? 0
|
||||
: Math.min(1, Math.max(0, (value - min) / (max - min || 1))),
|
||||
)
|
||||
// At the minimum the reading is a zero-length dash, and its round caps would
|
||||
// still paint a dot on the dial. Nothing reads there, so nothing is drawn.
|
||||
const drawn = useTransform(fraction, (at) => (at > 0 ? 1 : 0))
|
||||
const { label: reading, numeric } = useAnimatedNumber(value, precision)
|
||||
return (
|
||||
<div className="flex min-h-0 flex-1 items-center justify-center">
|
||||
@@ -84,7 +87,7 @@ export function Gauge({ value, min, max, precision, unit, label }: GaugeProps) {
|
||||
fraction itself. */}
|
||||
<motion.path
|
||||
d={arcPath(GAUGE_START, GAUGE_START + GAUGE_SWEEP)}
|
||||
style={{ pathLength: fraction }}
|
||||
style={{ pathLength: fraction, opacity: drawn }}
|
||||
fill="none"
|
||||
stroke="var(--primary)"
|
||||
strokeWidth={9}
|
||||
|
||||
@@ -24,7 +24,7 @@ const lockedName = `${flowName}_locked`
|
||||
const w = (name: string) => `${flowName}.${name}`
|
||||
|
||||
/** Every tile the dashboard carries, including the deliberately unbound one. */
|
||||
const TILES = 9
|
||||
const TILES = 11
|
||||
|
||||
test.use({ storageState: "playwright/.auth/user.json" })
|
||||
|
||||
@@ -58,6 +58,7 @@ test.beforeAll(async ({ browser }) => {
|
||||
{ name: "mode", dtype: "str" },
|
||||
{ name: "lamp", dtype: "bool" },
|
||||
{ name: "setpoint", dtype: "float" },
|
||||
{ name: "idle", dtype: "float" },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -76,6 +77,7 @@ test.beforeAll(async ({ browser }) => {
|
||||
await publish(page, w("grid"), 20)
|
||||
await publish(page, w("condition"), "sun")
|
||||
await publish(page, w("setpoint"), 21.5)
|
||||
await publish(page, w("idle"), 0)
|
||||
await publish(page, w("days"), [
|
||||
{ label: "Mon", icon: "sun", value: "21°" },
|
||||
{ label: "Tue", icon: "cloudy", value: "18°" },
|
||||
@@ -197,6 +199,14 @@ test.beforeAll(async ({ browser }) => {
|
||||
unit: "°C",
|
||||
},
|
||||
},
|
||||
{
|
||||
// At its minimum, where a gauge draws no reading at all.
|
||||
id: "idle",
|
||||
type: "gauge",
|
||||
title: "Idle",
|
||||
layout: { lg: { x: 4, y: 6, w: 2, h: 2 } },
|
||||
config: { message: w("idle"), dtype: "float", min: 0, max: 100 },
|
||||
},
|
||||
{
|
||||
id: "trend",
|
||||
type: "chart",
|
||||
@@ -716,6 +726,10 @@ for (const scheme of ["light", "dark"] as const) {
|
||||
// Every widget still draws, whichever set is asked to draw it.
|
||||
await expect(page.getByTestId("widget-frame")).toHaveCount(TILES)
|
||||
await expect(loadTile(page).getByTestId("bar-row")).toHaveCount(2)
|
||||
// The reading is a zero-length dash at the minimum, and round caps
|
||||
// would still paint it as a dot at either end of the dial.
|
||||
const dial = page.getByRole("img", { name: /^Idle:/ })
|
||||
await expect(dial.locator("path").nth(1)).toHaveCSS("opacity", "0")
|
||||
|
||||
await page.screenshot({
|
||||
path: `screenshots/widgets/${scheme}-${look}.png`,
|
||||
|
||||
Reference in New Issue
Block a user