FN-8665: align task-card size badge heights
Align size badges with the shared task-card badge geometry across responsive layouts. - Remove fixed size-chip heights so shared badge styling determines dimensions. - Cover desktop and wrapped badge geometry for S, M, and L task sizes. - Add a patch changeset for the visual consistency fix. Files changed: .changeset/fn-8665-size-badge-height.md | 7 +++++ packages/dashboard/app/components/TaskCard.css | 14 +++------ .../__tests__/TaskCard.badge-height.test.tsx | 33 ++++++++++++++++++++-- .../__tests__/TaskCard.badge-wrap.test.tsx | 18 ++++++------ 4 files changed, 50 insertions(+), 22 deletions(-) Fusion-Task-Id: FN-8665 Fusion-Task-Lineage: e54e76d5-ba33-49d5-ac05-25c0cc4183db Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
7
.changeset/fn-8665-size-badge-height.md
Normal file
7
.changeset/fn-8665-size-badge-height.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@runfusion/fusion": patch
|
||||
---
|
||||
|
||||
summary: Align task-card size badges with adjacent status badge heights.
|
||||
category: fix
|
||||
dev: Size chips now share the task-card header badge geometry at desktop and mobile breakpoints.
|
||||
@@ -547,16 +547,13 @@ FN-6774 removes the saturated stuck-task edge stripe from board cards. Keep the
|
||||
}
|
||||
|
||||
/*
|
||||
FNXC:TaskCardLayout 2026-07-26-08:29 (FN-8599):
|
||||
As a direct header child after .card-id, the size chip must stay in the first chip-height row. Whole-header centering misaligned it when the middle badge group wrapped, so lock its tokenized height and anchor it at the header start while the shared badge rule centers its text.
|
||||
FNXC:TaskCardLayout 2026-08-01-04:48 (FN-8665):
|
||||
The size chip must derive its box from the shared header-chip padding, line-height, and border so it renders at the same height as status and metadata chips. As a direct child after .card-id, keep it anchored to the header's first row when the middle badge group wraps.
|
||||
*/
|
||||
.card-size-badge {
|
||||
align-self: flex-start;
|
||||
flex-shrink: 0;
|
||||
box-sizing: border-box;
|
||||
height: var(--card-chip-height);
|
||||
min-height: var(--card-chip-height);
|
||||
max-height: var(--card-chip-height);
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
@@ -1689,15 +1686,12 @@ The mobile/short-landscape 28px ⋯ touch target must not expand .card-header-ac
|
||||
*/
|
||||
@media (max-width: 768px), (max-height: 480px) {
|
||||
/*
|
||||
FNXC:TaskCardLayout 2026-07-26-08:29 (FN-8599):
|
||||
Narrow and short-landscape cards use the mobile chip rhythm. Keep the size chip first-row anchored instead of centering it over wrapped header badges.
|
||||
FNXC:TaskCardLayout 2026-08-01-04:48 (FN-8665):
|
||||
Narrow and short-landscape cards keep the size chip first-row anchored while its shared mobile text-chip rule supplies the same intrinsic height as neighboring badges.
|
||||
*/
|
||||
.card-size-badge {
|
||||
align-self: flex-start;
|
||||
box-sizing: border-box;
|
||||
height: var(--card-chip-height-mobile);
|
||||
min-height: var(--card-chip-height-mobile);
|
||||
max-height: var(--card-chip-height-mobile);
|
||||
}
|
||||
|
||||
.card-menu-btn {
|
||||
|
||||
@@ -169,9 +169,8 @@ describe("TaskCard badge heights (FN-4369)", () => {
|
||||
}
|
||||
|
||||
const sizeStyles = getComputedStyle(sizeBadge!);
|
||||
expect(sizeStyles.height).toBe("var(--card-chip-height)");
|
||||
expect(sizeStyles.minHeight).toBe("var(--card-chip-height)");
|
||||
expect(sizeStyles.maxHeight).toBe("var(--card-chip-height)");
|
||||
expect(sizeStyles.height).toBe(baselineStyles.height);
|
||||
expect(sizeStyles.minHeight).toBe(baselineStyles.minHeight);
|
||||
expect(sizeStyles.paddingTop).toBe(baselineStyles.paddingTop);
|
||||
expect(sizeStyles.paddingBottom).toBe(baselineStyles.paddingBottom);
|
||||
expect(sizeStyles.borderTopWidth).toBe(baselineStyles.borderTopWidth);
|
||||
@@ -180,4 +179,32 @@ describe("TaskCard badge heights (FN-4369)", () => {
|
||||
|
||||
cleanupCss();
|
||||
});
|
||||
|
||||
it.each(["S", "M", "L"] as const)("keeps size %s on the status badge box geometry", (size) => {
|
||||
const cleanupCss = mountCss();
|
||||
const { container } = render(
|
||||
<TaskCard
|
||||
task={makeTask({ id: `FN-8665-${size}`, status: "planning" as Task["status"], size })}
|
||||
onOpenDetail={noop}
|
||||
addToast={noop}
|
||||
/>,
|
||||
);
|
||||
|
||||
const statusBadge = container.querySelector(".card-status-badge");
|
||||
const sizeBadge = container.querySelector(".card-size-badge");
|
||||
expect(statusBadge).toBeTruthy();
|
||||
expect(sizeBadge).toBeTruthy();
|
||||
|
||||
const statusStyles = getComputedStyle(statusBadge!);
|
||||
const sizeStyles = getComputedStyle(sizeBadge!);
|
||||
expect(sizeStyles.height).toBe(statusStyles.height);
|
||||
expect(sizeStyles.minHeight).toBe(statusStyles.minHeight);
|
||||
expect(sizeStyles.paddingTop).toBe(statusStyles.paddingTop);
|
||||
expect(sizeStyles.paddingBottom).toBe(statusStyles.paddingBottom);
|
||||
expect(sizeStyles.borderTopWidth).toBe(statusStyles.borderTopWidth);
|
||||
expect(sizeStyles.borderBottomWidth).toBe(statusStyles.borderBottomWidth);
|
||||
expect(sizeStyles.lineHeight).toBe(statusStyles.lineHeight);
|
||||
|
||||
cleanupCss();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -193,9 +193,9 @@ function expectSizeBadgeAfterTaskId(container: HTMLElement, expected: boolean) {
|
||||
expect(sizeStyles.alignItems).toBe("center");
|
||||
expect(sizeStyles.alignSelf).toBe("flex-start");
|
||||
expect(sizeStyles.lineHeight).toBe("1");
|
||||
expect(sizeStyles.height).toMatch(resolvedChipHeightPattern);
|
||||
expect(sizeStyles.minHeight).toMatch(resolvedChipHeightPattern);
|
||||
expect(sizeStyles.maxHeight).toMatch(resolvedChipHeightPattern);
|
||||
expect(sizeStyles.height).toBe("auto");
|
||||
expect(sizeStyles.minHeight).toBe("auto");
|
||||
expect(sizeStyles.maxHeight).toBe("none");
|
||||
expect(sizeBadge!.parentElement).toBe(header);
|
||||
expect(cardId.nextElementSibling).toBe(sizeBadge);
|
||||
expect(actions?.contains(sizeBadge)).toBe(false);
|
||||
@@ -537,15 +537,15 @@ describe("TaskCard badge wrapping (FN-5162)", () => {
|
||||
|
||||
expect(sizeBadgeRule).toContain("align-self: flex-start;");
|
||||
expect(sizeBadgeRule).toContain("box-sizing: border-box;");
|
||||
expect(sizeBadgeRule).toContain("height: var(--card-chip-height);");
|
||||
expect(sizeBadgeRule).toContain("min-height: var(--card-chip-height);");
|
||||
expect(sizeBadgeRule).toContain("max-height: var(--card-chip-height);");
|
||||
expect(sizeBadgeRule).not.toContain("align-self: center;");
|
||||
for (const declaration of ["\n height:", "\n min-height:", "\n max-height:"]) {
|
||||
expectCssRuleNotToContain(loadedCss, ".card-size-badge", declaration);
|
||||
}
|
||||
for (const section of [mobileSection, shortLandscapeSection]) {
|
||||
expectCssRuleToContain(section, ".card-size-badge", "align-self: flex-start;");
|
||||
expectCssRuleToContain(section, ".card-size-badge", "height: var(--card-chip-height-mobile);");
|
||||
expectCssRuleToContain(section, ".card-size-badge", "min-height: var(--card-chip-height-mobile);");
|
||||
expectCssRuleToContain(section, ".card-size-badge", "max-height: var(--card-chip-height-mobile);");
|
||||
for (const declaration of ["\n height:", "\n min-height:", "\n max-height:"]) {
|
||||
expectCssRuleNotToContain(section, ".card-size-badge", declaration);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user