mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-15 06:52:04 +00:00
Merge pull request #1141 from MBombeck/ready/pr-1132
feat(labs): let the lab list's range bar use a wide card
This commit is contained in:
4 files changed
+222
-5
No files matched your search
@@ -106,4 +106,63 @@ describe("<LabList> columns", () => {
|
||||
const html = renderList([reading({})]);
|
||||
expect(html).toMatch(/class="[^"]*lucide-chevron-right[^"]*lg:invisible/);
|
||||
});
|
||||
|
||||
describe("on a wide list", () => {
|
||||
const NARROW_TIER =
|
||||
"lg:@max-5xl:grid-cols-[minmax(0,1fr)_max-content_12rem_72px_auto]";
|
||||
const WIDE_TIER =
|
||||
"@5xl:grid-cols-[minmax(0,1fr)_max-content_minmax(12rem,18rem)_72px_auto]";
|
||||
|
||||
it("makes the card a container, so the columns follow the list's width, not the window's", () => {
|
||||
const html = renderList([reading({})]);
|
||||
expect(html).toMatch(/<div[^>]*class="[^"]*@container[^"]*"/);
|
||||
});
|
||||
|
||||
it("leaves the lg table as it was and adds a wider tier from @5xl, the two excluding each other", () => {
|
||||
const html = renderList([reading({})]);
|
||||
expect(html).toContain(NARROW_TIER);
|
||||
expect(html).toContain(WIDE_TIER);
|
||||
// Name, badge, bar, trend and chevron: five columns in both tiers.
|
||||
expect(NARROW_TIER.split("_")).toHaveLength(5);
|
||||
expect(WIDE_TIER.split("_")).toHaveLength(5);
|
||||
});
|
||||
|
||||
it("keeps the trend column as wide as its 72px sparkline in both tiers", () => {
|
||||
expect(NARROW_TIER.split("_")[3]).toBe("72px");
|
||||
expect(WIDE_TIER.split("_")[3]).toBe("72px");
|
||||
});
|
||||
|
||||
it("keeps the name column the flexible one in both tiers", () => {
|
||||
expect(NARROW_TIER).toContain("[minmax(0,1fr)_");
|
||||
expect(WIDE_TIER).toContain("[minmax(0,1fr)_");
|
||||
});
|
||||
|
||||
it("lets the range bar fill its column from lg, and caps it on a phone", () => {
|
||||
const html = renderList([reading({})]);
|
||||
expect(html).toMatch(
|
||||
/data-slot="lab-reference-range-bar"[^>]*class="[^"]*max-w-48[^"]*lg:max-w-none/,
|
||||
);
|
||||
// The slot no longer pins the bar to 12rem itself.
|
||||
expect(html).not.toContain("lg:w-48");
|
||||
});
|
||||
|
||||
it("wraps a long analyte name from lg up and truncates it on a phone", () => {
|
||||
const longName = "A".repeat(20) + " " + "B".repeat(100);
|
||||
const html = renderList([reading({ analyte: longName })]);
|
||||
expect(html).toContain(longName);
|
||||
const cls = html.match(
|
||||
/data-slot="lab-list-analyte"[^>]*class="([^"]*)"|class="([^"]*)"[^>]*data-slot="lab-list-analyte"/,
|
||||
);
|
||||
const classes = (cls?.[1] ?? cls?.[2] ?? "").split(" ");
|
||||
expect(classes).toContain("truncate");
|
||||
for (const c of [
|
||||
"lg:overflow-visible",
|
||||
"lg:whitespace-normal",
|
||||
"lg:text-clip",
|
||||
"lg:[overflow-wrap:anywhere]",
|
||||
]) {
|
||||
expect(classes).toContain(c);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -93,8 +93,11 @@ function RangeBadgeCell({ status }: { status: LabResultDto["rangeStatus"] }) {
|
||||
|
||||
function LabRangeBarSlot({ reading }: { reading: LabResultDto }) {
|
||||
return (
|
||||
<div className={cn("w-full lg:w-48", MOBILE_CELL.rangeBar)}>
|
||||
<div className={cn("w-full", MOBILE_CELL.rangeBar)}>
|
||||
{/* A phone keeps the bar's own 12rem cap; from `lg` the bar fills its
|
||||
column, which is 12rem until the list is wide enough to grow it. */}
|
||||
<LabReferenceRangeBar
|
||||
className="lg:max-w-none"
|
||||
value={reading.value}
|
||||
referenceLow={reading.referenceLow}
|
||||
referenceHigh={reading.referenceHigh}
|
||||
@@ -255,15 +258,26 @@ export function LabList({ onAddFirst }: { onAddFirst?: () => void } = {}) {
|
||||
{t("labs.showingLatestOf", { shown, total })}
|
||||
</p>
|
||||
) : null}
|
||||
<Card>
|
||||
<CardContent className="divide-border grid grid-cols-1 divide-y p-0 lg:grid-cols-[minmax(0,1fr)_max-content_12rem_72px_auto] lg:gap-x-3">
|
||||
{/* `@container` makes the columns follow the width the list has, not the
|
||||
window's: below `@5xl` (64rem of card) the row is the `lg` table it
|
||||
always was (the two tiers exclude each other, so the result does not
|
||||
depend on the order the CSS is emitted in), from there up the range
|
||||
bar takes part of the extra width instead of all of it going to the
|
||||
name. The trend column stays 72px in both tiers: the sparkline is a
|
||||
fixed 72px glyph, and a wider column would only open an empty strip
|
||||
between it and the chevron. */}
|
||||
<Card className="@container">
|
||||
<CardContent className="divide-border grid grid-cols-1 divide-y p-0 lg:gap-x-3 lg:@max-5xl:grid-cols-[minmax(0,1fr)_max-content_12rem_72px_auto] @5xl:grid-cols-[minmax(0,1fr)_max-content_minmax(12rem,18rem)_72px_auto]">
|
||||
{groups.map((group) => {
|
||||
const inner = (
|
||||
<div className={cn("min-w-0 flex-1", MOBILE_CELL.reading)}>
|
||||
<div className="flex flex-wrap items-baseline gap-x-2 text-sm">
|
||||
{/* One line with an ellipsis on a phone; from `lg` the name
|
||||
wraps instead, so a long one (the schema allows 120
|
||||
characters) always reads in full. */}
|
||||
<span
|
||||
data-slot="lab-list-analyte"
|
||||
className="truncate font-medium"
|
||||
className="truncate font-medium lg:overflow-visible lg:[overflow-wrap:anywhere] lg:text-clip lg:whitespace-normal"
|
||||
>
|
||||
{group.analyte}
|
||||
</span>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { RangeBar } from "@/components/targets/range-bar";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
import { useLabNumber } from "./use-lab-format";
|
||||
|
||||
@@ -16,11 +17,14 @@ export function LabReferenceRangeBar({
|
||||
referenceLow,
|
||||
referenceHigh,
|
||||
unit,
|
||||
className,
|
||||
}: {
|
||||
value: number | null;
|
||||
referenceLow: number | null;
|
||||
referenceHigh: number | null;
|
||||
unit: string;
|
||||
/** Extra classes on the bar's wrapper; it caps itself at 12rem by default. */
|
||||
className?: string;
|
||||
}) {
|
||||
const labNumber = useLabNumber();
|
||||
const hasLow = referenceLow !== null && Number.isFinite(referenceLow);
|
||||
@@ -48,7 +52,7 @@ export function LabReferenceRangeBar({
|
||||
return (
|
||||
<div
|
||||
data-slot="lab-reference-range-bar"
|
||||
className="w-full max-w-48 shrink-0"
|
||||
className={cn("w-full max-w-48 shrink-0", className)}
|
||||
aria-label={rangeLabel}
|
||||
>
|
||||
<RangeBar
|
||||
|
||||
Reference in new issue
Block a user