feat(FN-4369): complete Step 2 — normalize badge dimensions
Fusion-Task-Id: FN-4369 Fusion-Task-Lineage: 3f08cecf-2e6c-41a6-804f-645c4b809e4a
This commit is contained in:
5
.changeset/fn-4369-badge-heights.md
Normal file
5
.changeset/fn-4369-badge-heights.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@runfusion/fusion": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Normalize task card badge heights so planning, merging, urgent, high, and low pills render at the same height.
|
||||||
@@ -130,21 +130,28 @@
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-status-badge {
|
.card-status-badge,
|
||||||
|
.card-priority-badge,
|
||||||
|
.card-size-badge {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-size: 0.625rem;
|
font-size: 0.625rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
line-height: 1;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.5px;
|
padding: calc(var(--space-xs) / 2) var(--space-sm);
|
||||||
padding: 2px 8px;
|
border: var(--btn-border-width) solid transparent;
|
||||||
border-radius: var(--radius-pill);
|
border-radius: var(--radius-pill);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-status-badge {
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
.card-status-badge.stalled-review {
|
.card-status-badge.stalled-review {
|
||||||
background: color-mix(in srgb, var(--color-warning) 18%, transparent);
|
background: color-mix(in srgb, var(--color-warning) 18%, transparent);
|
||||||
color: var(--color-warning);
|
color: var(--color-warning);
|
||||||
border: var(--btn-border-width) solid color-mix(in srgb, var(--color-warning) 30%, transparent);
|
border-color: color-mix(in srgb, var(--color-warning) 30%, transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-stalled-review-reason {
|
.card-stalled-review-reason {
|
||||||
@@ -227,14 +234,7 @@
|
|||||||
|
|
||||||
/* Size badge: positioned in card header, subtle color coding for effort estimation */
|
/* Size badge: positioned in card header, subtle color coding for effort estimation */
|
||||||
.card-size-badge {
|
.card-size-badge {
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
font-size: 0.625rem;
|
|
||||||
font-weight: 600;
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 0.5px;
|
letter-spacing: 0.5px;
|
||||||
padding: 2px 8px;
|
|
||||||
border-radius: var(--radius-pill);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Size S: subtle green tint (low effort) */
|
/* Size S: subtle green tint (low effort) */
|
||||||
@@ -256,14 +256,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.card-priority-badge {
|
.card-priority-badge {
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
font-size: 0.625rem;
|
|
||||||
font-weight: 600;
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 0.4px;
|
letter-spacing: 0.4px;
|
||||||
padding: 2px 8px;
|
|
||||||
border-radius: var(--radius-pill);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-priority-badge--low {
|
.card-priority-badge--low {
|
||||||
@@ -1215,9 +1208,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Card: smaller status badges for 280px width */
|
/* Card: smaller status badges for 280px width */
|
||||||
.card-status-badge {
|
.card-status-badge,
|
||||||
|
.card-priority-badge,
|
||||||
|
.card-size-badge {
|
||||||
font-size: 0.5625rem;
|
font-size: 0.5625rem;
|
||||||
padding: 1px 6px;
|
padding: calc(var(--space-xs) / 4) calc((var(--space-xs) * 3) / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-stalled-review-reason {
|
.card-stalled-review-reason {
|
||||||
|
|||||||
@@ -0,0 +1,99 @@
|
|||||||
|
import { describe, it, expect, vi } from "vitest";
|
||||||
|
import { render } from "@testing-library/react";
|
||||||
|
import { TaskCard } from "../TaskCard";
|
||||||
|
import type { Task } from "@fusion/core";
|
||||||
|
import { loadAllAppCss } from "../../test/cssFixture";
|
||||||
|
|
||||||
|
vi.mock("lucide-react", () => ({
|
||||||
|
Link: () => null,
|
||||||
|
GitBranch: () => null,
|
||||||
|
Clock: () => null,
|
||||||
|
Pencil: () => null,
|
||||||
|
Layers: () => null,
|
||||||
|
ChevronDown: () => null,
|
||||||
|
Folder: () => null,
|
||||||
|
GitPullRequest: () => null,
|
||||||
|
CircleDot: () => null,
|
||||||
|
Target: () => null,
|
||||||
|
Bot: () => null,
|
||||||
|
Trash2: () => null,
|
||||||
|
RotateCw: () => null,
|
||||||
|
Zap: () => null,
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("../ProviderIcon", () => ({
|
||||||
|
ProviderIcon: () => null,
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("../../hooks/useTaskDiffStats", () => ({
|
||||||
|
useTaskDiffStats: () => ({ stats: null, loading: false }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const noop = () => {};
|
||||||
|
|
||||||
|
function makeTask(overrides: Partial<Task> = {}): Task {
|
||||||
|
return {
|
||||||
|
id: "FN-001",
|
||||||
|
title: "Badge height",
|
||||||
|
column: "in-progress",
|
||||||
|
status: "planning" as Task["status"],
|
||||||
|
steps: [],
|
||||||
|
dependencies: [],
|
||||||
|
description: "",
|
||||||
|
...overrides,
|
||||||
|
} as Task;
|
||||||
|
}
|
||||||
|
|
||||||
|
function mountCss() {
|
||||||
|
const style = document.createElement("style");
|
||||||
|
style.textContent = loadAllAppCss();
|
||||||
|
document.head.appendChild(style);
|
||||||
|
return () => style.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("TaskCard badge heights (FN-4369)", () => {
|
||||||
|
it("keeps planning, merging, and priority pills at identical dimensions", () => {
|
||||||
|
const cleanupCss = mountCss();
|
||||||
|
|
||||||
|
const planning = render(
|
||||||
|
<TaskCard task={makeTask({ id: "FN-100", column: "in-progress", status: "planning" as Task["status"] })} onOpenDetail={noop} addToast={noop} />,
|
||||||
|
).container.querySelector(".card-status-badge");
|
||||||
|
|
||||||
|
const merging = render(
|
||||||
|
<TaskCard task={makeTask({ id: "FN-101", column: "in-review", status: "merging" as Task["status"] })} onOpenDetail={noop} addToast={noop} />,
|
||||||
|
).container.querySelector(".card-status-badge");
|
||||||
|
|
||||||
|
const urgent = render(
|
||||||
|
<TaskCard task={makeTask({ id: "FN-102", priority: "urgent" as Task["priority"] })} onOpenDetail={noop} addToast={noop} />,
|
||||||
|
).container.querySelector(".card-priority-badge--urgent");
|
||||||
|
|
||||||
|
const high = render(
|
||||||
|
<TaskCard task={makeTask({ id: "FN-103", priority: "high" as Task["priority"] })} onOpenDetail={noop} addToast={noop} />,
|
||||||
|
).container.querySelector(".card-priority-badge--high");
|
||||||
|
|
||||||
|
const low = render(
|
||||||
|
<TaskCard task={makeTask({ id: "FN-104", priority: "low" as Task["priority"] })} onOpenDetail={noop} addToast={noop} />,
|
||||||
|
).container.querySelector(".card-priority-badge--low");
|
||||||
|
|
||||||
|
expect(planning).toBeTruthy();
|
||||||
|
expect(merging).toBeTruthy();
|
||||||
|
expect(urgent).toBeTruthy();
|
||||||
|
expect(high).toBeTruthy();
|
||||||
|
expect(low).toBeTruthy();
|
||||||
|
|
||||||
|
const baseline = getComputedStyle(planning!);
|
||||||
|
|
||||||
|
for (const badge of [merging!, urgent!, high!, low!]) {
|
||||||
|
const styles = getComputedStyle(badge);
|
||||||
|
expect(styles.height).toBe(baseline.height);
|
||||||
|
expect(styles.paddingTop).toBe(baseline.paddingTop);
|
||||||
|
expect(styles.paddingBottom).toBe(baseline.paddingBottom);
|
||||||
|
expect(styles.borderTopWidth).toBe(baseline.borderTopWidth);
|
||||||
|
expect(styles.borderBottomWidth).toBe(baseline.borderBottomWidth);
|
||||||
|
expect(styles.fontSize).toBe(baseline.fontSize);
|
||||||
|
expect(styles.lineHeight).toBe(baseline.lineHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanupCss();
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user