mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 14:16:12 +00:00
refactor(insights): one TrendTile frame for the trend tiles
The dashboard KPI tile, the derived-insight sparkline tile, both skeletons and the three still-building states of the vitals board each spelled out the same tile frame by hand, and some clipped their content while others did not. TrendTile owns the frame; the vitals board's three building states share one BuildingTile. The rendered classes are unchanged.
This commit is contained in:
1 parent
3aadc03424
commit
a97abe64b9
6 files changed
+180
-89
No files matched your search
@@ -0,0 +1,39 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { renderToStaticMarkup } from "react-dom/server";
|
||||
|
||||
import { TrendTile } from "../trend-tile";
|
||||
|
||||
describe("<TrendTile>", () => {
|
||||
it("paints the tile frame on the card inset and clips its content", () => {
|
||||
const html = renderToStaticMarkup(<TrendTile>x</TrendTile>);
|
||||
for (const c of [
|
||||
"bg-card",
|
||||
"border",
|
||||
"rounded-xl",
|
||||
"p-4",
|
||||
"md:p-6",
|
||||
"h-full",
|
||||
"min-w-0",
|
||||
"overflow-hidden",
|
||||
]) {
|
||||
expect(html).toContain(c);
|
||||
}
|
||||
expect(html).toContain('data-slot="trend-tile"');
|
||||
expect(html).not.toContain("shadow");
|
||||
});
|
||||
|
||||
it("keeps the caller's slot, state and rhythm", () => {
|
||||
const html = renderToStaticMarkup(
|
||||
<TrendTile
|
||||
data-slot="vitals-tile"
|
||||
data-state="provisional"
|
||||
className="gap-3"
|
||||
>
|
||||
x
|
||||
</TrendTile>,
|
||||
);
|
||||
expect(html).toContain('data-slot="vitals-tile"');
|
||||
expect(html).toContain('data-state="provisional"');
|
||||
expect(html).toContain("gap-3");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
/**
|
||||
* The frame of a metric trend tile: the dashboard KPI strip (`TrendCard`),
|
||||
* the derived-insight tiles (`SparklineDeltaTile`), their skeletons and the
|
||||
* "still building" states of the vitals board.
|
||||
*
|
||||
* Seven copies spelled this frame out by hand, and they had started to
|
||||
* differ (some clipped their content, some did not). The frame is a dense
|
||||
* tile of its own rather than a `Card`: it sits in a grid of equal-height
|
||||
* tiles (`h-full`), insets on the card padding (`p-4 md:p-6`, UI standards
|
||||
* §1), carries no shadow, and clips a value that would otherwise push the
|
||||
* grid cell wider (`min-w-0 overflow-hidden`).
|
||||
*
|
||||
* The vertical rhythm inside belongs to the tile: pass `gap-3` for a stacked
|
||||
* state, or let the children set their own `mt-*` steps as the loaded tiles do.
|
||||
*/
|
||||
function TrendTile({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="trend-tile"
|
||||
className={cn(
|
||||
"bg-card border-border flex h-full w-full min-w-0 flex-col overflow-hidden rounded-xl border p-4 md:p-6",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export { TrendTile };
|
||||
Reference in new issue
Block a user