fix(FN-2714): restore task timer chip to footer metadata row
- Move TaskCard time indicator rendering from the header back into the footer metadata row - Render timer and files-changed metadata together in the shared footer row layout - Update timer chip CSS to stay right-aligned with margin-left:auto and prevent shrinking - Update TaskCard and mobile board tests to assert footer placement and alignment behavior
This commit is contained in:
@@ -482,6 +482,8 @@
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--space-xs);
|
||||
margin-left: auto;
|
||||
flex-shrink: 0;
|
||||
padding: var(--space-xs) var(--space-sm);
|
||||
border: 1px solid color-mix(in srgb, var(--text-muted) 30%, transparent);
|
||||
border-radius: var(--radius-pill);
|
||||
|
||||
@@ -1208,16 +1208,6 @@ function TaskCardComponent({
|
||||
{abbreviateMissionTitle(missionTitle ?? task.missionId)}
|
||||
</span>
|
||||
)}
|
||||
{timeIndicator && (
|
||||
<span
|
||||
className="card-time-indicator"
|
||||
title={timeIndicator.title}
|
||||
aria-label={timeIndicator.ariaLabel}
|
||||
>
|
||||
<Clock size={12} />
|
||||
<span>{timeIndicator.label}</span>
|
||||
</span>
|
||||
)}
|
||||
<div className="card-header-actions">
|
||||
{canEdit && (
|
||||
<button
|
||||
@@ -1394,9 +1384,19 @@ function TaskCardComponent({
|
||||
</>
|
||||
);
|
||||
})()}
|
||||
{filesChangedButton && (
|
||||
{(filesChangedButton || timeIndicator) && (
|
||||
<div className="card-footer-row">
|
||||
{filesChangedButton}
|
||||
{timeIndicator && (
|
||||
<span
|
||||
className="card-time-indicator"
|
||||
title={timeIndicator.title}
|
||||
aria-label={timeIndicator.ariaLabel}
|
||||
>
|
||||
<Clock size={12} />
|
||||
<span>{timeIndicator.label}</span>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{((task.dependencies && task.dependencies.length > 0) || queued || task.status === "queued" || task.blockedBy) && (
|
||||
|
||||
@@ -503,7 +503,7 @@ describe("TaskCard", () => {
|
||||
expect(timer?.getAttribute("aria-label")).toContain("Completed processing duration 2h");
|
||||
});
|
||||
|
||||
it("renders files-changed metadata in footer row and timer chip in header", () => {
|
||||
it("renders files-changed metadata and timer chip in footer row", () => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date("2026-04-25T18:00:00.000Z"));
|
||||
|
||||
@@ -539,9 +539,9 @@ describe("TaskCard", () => {
|
||||
expect(filesChanged).not.toBeNull();
|
||||
expect(timer).not.toBeNull();
|
||||
expect(footerRow?.contains(filesChanged)).toBe(true);
|
||||
expect(footerRow?.contains(timer)).toBe(false);
|
||||
expect(header?.contains(timer)).toBe(true);
|
||||
expect(Array.from(footerRow?.children ?? [])).toEqual([filesChanged]);
|
||||
expect(footerRow?.contains(timer)).toBe(true);
|
||||
expect(header?.contains(timer)).toBe(false);
|
||||
expect(Array.from(footerRow?.children ?? [])).toEqual([filesChanged, timer]);
|
||||
});
|
||||
it.each(["triage", "todo", "in-review", "archived"] as const)(
|
||||
"does not render timer chip for %s cards",
|
||||
|
||||
@@ -274,9 +274,9 @@ describe("TaskCard mobile", () => {
|
||||
expectRuleToContain(css, ".card-footer-row", "flex-wrap: nowrap;");
|
||||
});
|
||||
|
||||
it("keeps TaskCard timer chip in-flow and reserves right alignment for header actions", () => {
|
||||
it("keeps TaskCard timer chip in-flow and right-aligned in footer metadata row", () => {
|
||||
const css = loadAllAppCss();
|
||||
expectRuleNotToContain(css, ".card-time-indicator", "margin-left: auto;");
|
||||
expectRuleToContain(css, ".card-time-indicator", "margin-left: auto;");
|
||||
expectRuleToContain(css, ".card-header-actions", "margin-left: auto;");
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user