refactor: update DayIndicators component and tests for improved clarity and accuracy

- Revised comments in DayIndicators component and test files to better describe the functionality of colored segments and rounding behavior.
- Updated test descriptions to reflect changes in rendering logic for single and multiple segments.
- Adjusted class names in the component and tests to ensure correct application of rounded styles based on segment positions.
This commit is contained in:
2026-03-03 18:19:52 +03:00
parent 68a153e4a7
commit 8bf92bd4a1
2 changed files with 15 additions and 15 deletions

View File

@@ -1,6 +1,6 @@
/** /**
* Unit tests for DayIndicators: rounding is position-based (first / last / only child), * Unit tests for DayIndicators: rounding is position-based (first / last segment),
* not by indicator type, so multiple segments form one pill. * not by indicator type, so one or multiple segments form one pill.
*/ */
import { describe, it, expect } from "vitest"; import { describe, it, expect } from "vitest";
@@ -20,13 +20,14 @@ describe("DayIndicators", () => {
expect(container.firstChild).toBeNull(); expect(container.firstChild).toBeNull();
}); });
it("renders one segment with only-child rounding (e.g. vacation only)", () => { it("renders one segment as pill (e.g. vacation only)", () => {
const { container } = render( const { container } = render(
<DayIndicators {...baseProps} vacationCount={1} /> <DayIndicators {...baseProps} vacationCount={1} />
); );
const wrapper = container.querySelector("[aria-hidden]"); const wrapper = container.querySelector("[aria-hidden]");
expect(wrapper).toBeInTheDocument(); expect(wrapper).toBeInTheDocument();
expect(wrapper?.className).toContain("[&>:only-child]:rounded-full"); expect(wrapper?.className).toContain("[&>:first-child]:rounded-l-[3px]");
expect(wrapper?.className).toContain("[&>:last-child]:rounded-r-[3px]");
const spans = wrapper?.querySelectorAll("span"); const spans = wrapper?.querySelectorAll("span");
expect(spans).toHaveLength(1); expect(spans).toHaveLength(1);
}); });
@@ -38,10 +39,10 @@ describe("DayIndicators", () => {
const wrapper = container.querySelector("[aria-hidden]"); const wrapper = container.querySelector("[aria-hidden]");
expect(wrapper).toBeInTheDocument(); expect(wrapper).toBeInTheDocument();
expect(wrapper?.className).toContain( expect(wrapper?.className).toContain(
"[&>:first-child:not(:only-child)]:rounded-l-[3px]" "[&>:first-child]:rounded-l-[3px]"
); );
expect(wrapper?.className).toContain( expect(wrapper?.className).toContain(
"[&>:last-child:not(:only-child)]:rounded-r-[3px]" "[&>:last-child]:rounded-r-[3px]"
); );
const spans = wrapper?.querySelectorAll("span"); const spans = wrapper?.querySelectorAll("span");
expect(spans).toHaveLength(2); expect(spans).toHaveLength(2);
@@ -59,10 +60,10 @@ describe("DayIndicators", () => {
const wrapper = container.querySelector("[aria-hidden]"); const wrapper = container.querySelector("[aria-hidden]");
expect(wrapper).toBeInTheDocument(); expect(wrapper).toBeInTheDocument();
expect(wrapper?.className).toContain( expect(wrapper?.className).toContain(
"[&>:first-child:not(:only-child)]:rounded-l-[3px]" "[&>:first-child]:rounded-l-[3px]"
); );
expect(wrapper?.className).toContain( expect(wrapper?.className).toContain(
"[&>:last-child:not(:only-child)]:rounded-r-[3px]" "[&>:last-child]:rounded-r-[3px]"
); );
const spans = wrapper?.querySelectorAll("span"); const spans = wrapper?.querySelectorAll("span");
expect(spans).toHaveLength(3); expect(spans).toHaveLength(3);

View File

@@ -1,9 +1,9 @@
/** /**
* Colored dots for calendar day: duty (green), unavailable (amber), vacation (blue), events (accent). * Colored segments (pill bar) for calendar day: duty (green), unavailable (amber), vacation (blue), events (accent).
* Ported from webapp calendar day-indicator markup and markers.css. * Ported from webapp calendar day-indicator markup and markers.css.
* *
* Rounding is position-based (first / last / only child), not by indicator type, so multiple * Rounding is position-based (first / last segment), so one or multiple segments always form a pill:
* segments form one "pill": only the left and right ends are rounded. * first segment gets left rounding, last segment gets right rounding (single segment gets both).
*/ */
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
@@ -17,7 +17,7 @@ export interface DayIndicatorsProps {
vacationCount: number; vacationCount: number;
/** Whether the day has external calendar events (e.g. holiday). */ /** Whether the day has external calendar events (e.g. holiday). */
hasEvents: boolean; hasEvents: boolean;
/** When true (e.g. today cell), use darker dots for contrast. */ /** When true (e.g. today cell), use darker segments for contrast. */
isToday?: boolean; isToday?: boolean;
className?: string; className?: string;
} }
@@ -50,9 +50,8 @@ export function DayIndicators({
<div <div
className={cn( className={cn(
"flex w-[65%] justify-center gap-0.5 mt-1.5", "flex w-[65%] justify-center gap-0.5 mt-1.5",
"[&>:only-child]:h-1.5 [&>:only-child]:min-w-[6px] [&>:only-child]:max-w-[6px] [&>:only-child]:rounded-full", "[&>:first-child]:rounded-l-[3px]",
"[&>:first-child:not(:only-child)]:rounded-l-[3px]", "[&>:last-child]:rounded-r-[3px]",
"[&>:last-child:not(:only-child)]:rounded-r-[3px]",
className className
)} )}
aria-hidden aria-hidden