import { describe, expect, it } from "vitest"; import { badgeClass, buttonClass, cardClass, cn, focusRing, inputClass, overlayScrim, proseBody, segmentedClass, statusNoteClass, transitionUi, } from "./variants"; describe("ui variants", () => { it("joins classes without falsey values", () => { expect(cn("a", false, undefined, null, "b")).toBe("a b"); }); it("builds stable primary button classes", () => { const klass = buttonClass({ variant: "primary", size: "sm" }); expect(klass).toContain("bg-cinnabar"); expect(klass).toContain("px-3"); expect(klass).toContain("focus-visible:ring-2"); }); it("uses layered radius tokens (button md / card lg / badge pill)", () => { expect(buttonClass({ variant: "primary" })).toContain("rounded-md"); expect(cardClass()).toContain("rounded-lg"); expect(badgeClass()).toContain("rounded-full"); expect(inputClass()).toContain("rounded-md"); }); it("gives the primary button a press-darken and cream disabled state", () => { const klass = buttonClass({ variant: "primary" }); expect(klass).toContain("hover:bg-cinnabar-active"); expect(klass).toContain("active:bg-cinnabar-active"); expect(klass).toContain("disabled:bg-cinnabar-disabled"); expect(klass).not.toContain("hover:bg-cinnabar/95"); }); it("shares one interaction-transition token across controls", () => { expect(transitionUi).toContain("duration-fast"); expect(transitionUi).toContain("ease-standard"); expect(buttonClass({ variant: "primary" })).toContain(transitionUi); expect(inputClass()).toContain(transitionUi); }); it("builds a coral inline link button variant", () => { const klass = buttonClass({ variant: "link" }); expect(klass).toContain("text-cinnabar"); expect(klass).toContain("underline-offset-4"); expect(klass).toContain("hover:underline"); }); it("supports a large button size for prominent CTAs", () => { expect(buttonClass({ size: "lg" })).toContain("px-5"); }); it("layers card surface tones and can drop the shadow", () => { expect(cardClass({ tone: "card" })).toContain("bg-surface-card"); expect(cardClass({ tone: "soft" })).toContain("bg-surface-soft"); expect(cardClass()).toContain("bg-panel"); expect(cardClass({ flat: true })).not.toContain("shadow-paper"); expect(cardClass({ interactive: true })).toContain("hover:border-cinnabar/40"); }); it("keeps the legacy string cardClass signature working", () => { const klass = cardClass("mt-4"); expect(klass).toContain("mt-4"); expect(klass).toContain("bg-panel"); expect(klass).toContain("rounded-lg"); }); it("keeps warning badges readable on the paper background", () => { const klass = badgeClass({ variant: "warning" }); expect(klass).toContain("bg-overdue/10"); expect(klass).toContain("text-ink"); }); it("marks invalid inputs with conflict styling", () => { const klass = inputClass({ state: "error" }); expect(klass).toContain("border-conflict"); expect(klass).toContain("focus-visible:ring-conflict/25"); }); it("gives warning status notes a non-color icon slot friendly shell", () => { const klass = statusNoteClass({ variant: "warning" }); expect(klass).toContain("border-overdue"); expect(klass).toContain("px-3"); }); it("builds segmented control chrome", () => { const klass = segmentedClass(); expect(klass).toContain("inline-flex"); expect(klass).toContain("border-line"); }); it("shares the cinnabar focus ring with the button base", () => { expect(focusRing).toContain("focus-visible:ring-2"); expect(focusRing).toContain("focus-visible:ring-cinnabar/35"); expect(buttonClass({ variant: "primary" })).toContain(focusRing); }); it("renders manuscript body as serif prose scale", () => { expect(proseBody).toContain("font-serif"); expect(proseBody).toContain("text-prose"); }); it("provides a full-screen overlay scrim below dialog chrome", () => { expect(overlayScrim).toContain("fixed"); expect(overlayScrim).toContain("inset-0"); expect(overlayScrim).toContain("z-40"); }); });