FN-7597: style task-detail Priority dropdown to match Oversight dropdown

Aligns the task-detail Priority dropdown's size, border, and typography with the Oversight dropdown so both controls read as one consistent style.

- Give the untinted `normal` priority level a neutral, token-based chip background (scoped to `.detail-priority-chip.card-priority-badge--normal`) instead of an empty bordered shell, matching the Oversight `--off` chip treatment.
- Remove the Priority-only forced uppercase text-transform on the select/option so it relies on the ancestor label's uppercase transform like the Oversight select does.
- Add regression coverage asserting shared box-size/border tokens across the Priority chip, Oversight chip, and mobile Oversight overflow trigger, no duplicated text-transform overrides, preserved low/high/urgent semantic tints, and unaffected --saving state.
- Add a patch changeset documenting the fix.

Files changed:
 .changeset/fn-7597-priority-dropdown-matches-oversight.md          |  7 +++
 packages/dashboard/app/components/TaskDetailModal.css              | 27 ++++++++++--
 packages/dashboard/app/components/__tests__/TaskDetailModal.responsive-and-dependencies.test.tsx | 51 ++++++++++++++++++++++
 3 files changed, 82 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-7597

Fusion-Task-Lineage: d703e59a-35d8-4788-9ad2-1462d6f3c588

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
gsxdsm
2026-07-05 16:56:22 -07:00
parent c0abca90d8
commit 20379e81c5
3 changed files with 82 additions and 3 deletions

View File

@@ -0,0 +1,7 @@
---
"@runfusion/fusion": patch
---
summary: Task-detail Priority dropdown now matches the Oversight dropdown's size, border, and typography.
category: fix
dev: Removed the Priority-only forced select/option uppercase, added a neutral chip background scoped to `.detail-priority-chip.card-priority-badge--normal` for the untinted `normal` level, and reused the FN-7585 shared `--btn-border-width`/`--border`/`--detail-control-border-radius`/`--detail-priority-control-min-height` tokens so both dropdowns render as one control style across desktop and the mobile oversight-overflow surface.

View File

@@ -415,13 +415,27 @@ The task-detail modal metadata must keep priority, execution mode, provenance, P
opacity: 0.75;
}
/*
FNXC:TaskDetail 2026-07-05-12:00:
FN-7597 — the untinted `normal` priority level has no `--low/--high/--urgent`
tint, so without this rule it renders as a bordered-but-empty shell while the
Oversight chip's `--off` level always gets a neutral, token-based background
(`.card-oversight-badge--off` in TaskCard.css). Give `.detail-priority-chip`'s
`normal` state the SAME neutral `color-mix(... var(--text-muted) ...)`
treatment so the two dropdowns read as one consistent control style. Scoped
to the detail chip (not a global `.card-priority-badge--normal` rule) so the
read-only TaskCard priority badge (out of scope) is untouched.
*/
.detail-priority-chip.card-priority-badge--normal {
background: color-mix(in srgb, var(--text-muted) 12%, transparent);
color: var(--text-muted);
}
.detail-priority-select {
border: 0;
background: transparent;
color: inherit;
font: inherit;
text-transform: uppercase;
letter-spacing: inherit;
cursor: pointer;
padding: 0;
min-height: inherit;
@@ -437,10 +451,17 @@ The task-detail modal metadata must keep priority, execution mode, provenance, P
cursor: wait;
}
/*
FNXC:TaskDetail 2026-07-05-12:00:
FN-7597 — drop the Priority-only forced uppercase on the select/option so its
typography matches `.detail-oversight-select` exactly (which relies on the
ancestor `.card-*-badge` label's own `text-transform: uppercase` instead of
redeclaring it here). Visual case is unchanged since the label already
uppercases its content; this only removes a duplicated, drift-prone override.
*/
.detail-priority-select option {
color: var(--text);
background: var(--surface);
text-transform: uppercase;
}
.detail-execution-mode-toggle {

View File

@@ -253,6 +253,57 @@ describe("TaskDetailModal", () => {
expect(oversightChipBlock).not.toMatch(/border-radius:\s*var\(--radius-pill\)/);
});
it("renders the Priority dropdown chip like the Oversight dropdown chip, on every surface (FN-7597)", () => {
const css = readDashboardStylesSource();
const priorityChipBlock = getExactCssRuleBlock(css, ".detail-priority-chip");
const oversightChipBlock = getExactCssRuleBlock(css, ".detail-oversight-chip");
const oversightTriggerBlock = getExactCssRuleBlock(css, ".detail-oversight-menu-trigger");
const prioritySelectBlock = getExactCssRuleBlock(css, ".detail-priority-select");
const oversightSelectBlock = getExactCssRuleBlock(css, ".detail-oversight-select");
const prioritySelectOptionBlock = getExactCssRuleBlock(css, ".detail-priority-select option");
const oversightSelectOptionBlock = getExactCssRuleBlock(css, ".detail-oversight-select option");
// Same box size AND same border source for the desktop Priority chip vs.
// BOTH oversight surfaces (desktop chip and the mobile overflow trigger).
for (const block of [priorityChipBlock, oversightChipBlock, oversightTriggerBlock]) {
expect(block).toContain("min-height: var(--detail-priority-control-min-height);");
expect(block).toContain("border-width: var(--btn-border-width);");
expect(block).toContain("border-color: var(--border);");
expect(block).toContain("border-radius: var(--detail-control-border-radius);");
expect(block).toContain("box-sizing: border-box;");
}
// Same select typography: neither select force-uppercases its own text
// or options; both rely on the ancestor chip label's uppercase transform,
// so a regression re-adding a Priority-only override fails this.
expect(prioritySelectBlock).not.toMatch(/text-transform\s*:/);
expect(oversightSelectBlock).not.toMatch(/text-transform\s*:/);
expect(prioritySelectOptionBlock).not.toMatch(/text-transform\s*:/);
expect(oversightSelectOptionBlock).not.toMatch(/text-transform\s*:/);
expect(prioritySelectBlock).toContain("font: inherit;");
expect(oversightSelectBlock).toContain("font: inherit;");
// The untinted `normal` priority level must resolve a real, non-transparent
// neutral chip background (not a borderless/background-less shell), just
// like the Oversight chip's neutral `--off` background.
const priorityNormalBlock = getExactCssRuleBlock(css, ".detail-priority-chip.card-priority-badge--normal");
const oversightOffBlock = getExactCssRuleBlock(css, ".card-oversight-badge--off");
expect(priorityNormalBlock).toMatch(/background:\s*color-mix\(in srgb, var\(--text-muted\)/);
expect(oversightOffBlock).toMatch(/background:\s*color-mix\(in srgb, var\(--text-muted\)/);
// The semantic priority tints (info/warning/error family) must survive —
// this task must not flatten low/high/urgent to the same neutral tone.
expect(css).toMatch(/\.card-priority-badge--low\s*\{[^}]*background:\s*color-mix\(in srgb, var\(--color-info\)/);
expect(css).toMatch(/\.card-priority-badge--high\s*\{[^}]*background:\s*color-mix\(in srgb, var\(--color-warning\)/);
expect(css).toMatch(/\.card-priority-badge--urgent\s*\{[^}]*background:\s*color-mix\(in srgb, var\(--color-error\)/);
// `--saving` only dims opacity; it must never change box size/border.
const prioritySavingBlock = getExactCssRuleBlock(css, ".detail-priority-chip--saving");
expect(prioritySavingBlock.replace(/\s+/g, "")).toBe("opacity:0.75;");
expect(prioritySavingBlock).not.toMatch(/border|min-height|padding/);
});
it("keeps grouped timestamp metadata inline on desktop and mobile", () => {
const css = readDashboardStylesSource();