FN-7193: theme quick-add workflow controls
Theme quick-add optional step controls and workflow phase badges with shared dashboard tokens. - Apply the dashboard accent token to optional-step checkboxes in the workflow quick-add dropdown. - Co-locate workflow phase badge styles with the shared badge helper so all badge surfaces inherit themed colors. - Add CSS regression coverage for themed checkboxes, phase badges, and duplicate badge-style removal. - Add a patch changeset for the published Fusion package. Files changed: ...fn-7193-quick-add-steps-badge-checkbox-theme.md | 7 ++++ .../components/WorkflowOptionalStepsDropdown.css | 6 ++++ .../app/components/WorkflowResultsTab.css | 18 ---------- .../WorkflowOptionalStepsDropdown.test.tsx | 10 ++++++ .../__tests__/workflow-phase-badge.test.tsx | 41 ++++++++++++++++++++++ .../app/components/workflow-phase-badge.css | 17 +++++++++ .../app/components/workflow-phase-badge.tsx | 2 ++ 7 files changed, 83 insertions(+), 18 deletions(-) Fusion-Task-Id: FN-7193 Fusion-Task-Lineage: e1db3949-a493-4949-945d-26f567eace89 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@runfusion/fusion": patch
|
||||
---
|
||||
|
||||
summary: Theme quick-add optional-step checkboxes and phase badges consistently.
|
||||
category: fix
|
||||
dev: Co-locates workflow phase badge CSS with the shared helper and applies the dashboard checkbox accent token.
|
||||
@@ -36,6 +36,12 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* FNXC:DashboardThemeTokens 2026-06-28-00:00: Optional-step option checkboxes must use the themed --todo accent so Quick Entry, Task Form, and Inline Create match every dashboard checkbox across dark, light, and shadcn themes. */
|
||||
.wf-optional-steps-dropdown-option input[type="checkbox"] {
|
||||
accent-color: var(--todo);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.wf-optional-steps-dropdown-option:hover,
|
||||
.wf-optional-steps-dropdown-option.is-active {
|
||||
background: var(--card-hover);
|
||||
|
||||
@@ -482,24 +482,6 @@
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
/* Phase badge base and modifier classes */
|
||||
.phase-badge {
|
||||
margin-inline-start: var(--space-xs);
|
||||
font-size: calc(var(--space-sm) + var(--space-xs) * 0.75);
|
||||
padding: var(--space-xs) var(--space-sm);
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
.phase-badge--pre-merge {
|
||||
background-color: color-mix(in srgb, var(--ws-pre-merge) 15%, transparent);
|
||||
color: var(--ws-pre-merge);
|
||||
}
|
||||
|
||||
.phase-badge--post-merge {
|
||||
background-color: color-mix(in srgb, var(--ws-post-merge) 15%, transparent);
|
||||
color: var(--ws-post-merge);
|
||||
}
|
||||
|
||||
.workflow-result-meta {
|
||||
display: flex;
|
||||
gap: var(--space-sm);
|
||||
|
||||
@@ -78,6 +78,16 @@ describe("WorkflowOptionalStepsDropdown CSS", () => {
|
||||
expect(DROPDOWN_CSS).toContain("box-shadow: var(--shadow-lg);");
|
||||
});
|
||||
|
||||
it("uses the dashboard accent token for option checkboxes", () => {
|
||||
const checkboxRule = DROPDOWN_CSS.match(
|
||||
/\.wf-optional-steps-dropdown-option input\[type="checkbox"\]\s*\{([^}]*)\}/,
|
||||
)?.[1] ?? "";
|
||||
|
||||
expect(checkboxRule).toContain("accent-color: var(--todo);");
|
||||
expect(checkboxRule).not.toMatch(/#[0-9a-f]{3,8}\b/i);
|
||||
expect(checkboxRule).not.toMatch(/\brgba?\(/i);
|
||||
});
|
||||
|
||||
it("does not keep hardcoded color or px fallbacks in tokenized rules", () => {
|
||||
expect(DROPDOWN_CSS).not.toMatch(/var\(--[^,]+,\s*#/);
|
||||
expect(DROPDOWN_CSS).not.toMatch(/var\(--[^,]+,\s*\d+px/);
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { existsSync, readFileSync } from "node:fs";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
const BADGE_CSS_PATH = "app/components/workflow-phase-badge.css";
|
||||
const BADGE_HELPER_PATH = "app/components/workflow-phase-badge.tsx";
|
||||
const WORKFLOW_RESULTS_CSS_PATH = "app/components/WorkflowResultsTab.css";
|
||||
|
||||
const BADGE_CSS = readFileSync(BADGE_CSS_PATH, "utf8");
|
||||
const BADGE_HELPER = readFileSync(BADGE_HELPER_PATH, "utf8");
|
||||
const WORKFLOW_RESULTS_CSS = readFileSync(WORKFLOW_RESULTS_CSS_PATH, "utf8");
|
||||
|
||||
function cssRule(selector: string): string {
|
||||
const escapedSelector = selector.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
return BADGE_CSS.match(new RegExp(`${escapedSelector}\\s*\\{([^}]*)\\}`))?.[1] ?? "";
|
||||
}
|
||||
|
||||
describe("workflow phase badge CSS", () => {
|
||||
it("co-locates the shared phase badge styles with the helper", () => {
|
||||
expect(existsSync(BADGE_CSS_PATH)).toBe(true);
|
||||
expect(BADGE_HELPER).toContain('import "./workflow-phase-badge.css";');
|
||||
});
|
||||
|
||||
it("themes pre-merge and post-merge badges with workflow phase tokens only", () => {
|
||||
const preMergeRule = cssRule(".phase-badge--pre-merge");
|
||||
const postMergeRule = cssRule(".phase-badge--post-merge");
|
||||
|
||||
expect(preMergeRule).toContain("background-color: color-mix(in srgb, var(--ws-pre-merge) 15%, transparent);");
|
||||
expect(preMergeRule).toContain("color: var(--ws-pre-merge);");
|
||||
expect(postMergeRule).toContain("background-color: color-mix(in srgb, var(--ws-post-merge) 15%, transparent);");
|
||||
expect(postMergeRule).toContain("color: var(--ws-post-merge);");
|
||||
|
||||
for (const rule of [preMergeRule, postMergeRule]) {
|
||||
expect(rule).not.toMatch(/#[0-9a-f]{3,8}\b/i);
|
||||
expect(rule).not.toMatch(/\brgba?\(/i);
|
||||
}
|
||||
});
|
||||
|
||||
it("removes phase badge styling from WorkflowResultsTab to avoid duplicate sources", () => {
|
||||
expect(WORKFLOW_RESULTS_CSS).not.toMatch(/\.phase-badge(?:--pre-merge|--post-merge)?\s*\{/);
|
||||
});
|
||||
});
|
||||
17
packages/dashboard/app/components/workflow-phase-badge.css
Normal file
17
packages/dashboard/app/components/workflow-phase-badge.css
Normal file
@@ -0,0 +1,17 @@
|
||||
/* FNXC:WorkflowPhaseBadge 2026-06-28-00:00: Phase badge CSS is co-located with the shared phaseBadge() helper so every surface that renders the badge stays themed, including the quick-add drop-down, New Task dialog, inline create, and workflow results instead of only the lazy WorkflowResultsTab. */
|
||||
.phase-badge {
|
||||
margin-inline-start: var(--space-xs);
|
||||
font-size: calc(var(--space-sm) + var(--space-xs) * 0.75);
|
||||
padding: var(--space-xs) var(--space-sm);
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
.phase-badge--pre-merge {
|
||||
background-color: color-mix(in srgb, var(--ws-pre-merge) 15%, transparent);
|
||||
color: var(--ws-pre-merge);
|
||||
}
|
||||
|
||||
.phase-badge--post-merge {
|
||||
background-color: color-mix(in srgb, var(--ws-post-merge) 15%, transparent);
|
||||
color: var(--ws-post-merge);
|
||||
}
|
||||
@@ -10,6 +10,8 @@
|
||||
import type { ReactNode } from "react";
|
||||
import type { useTranslation } from "react-i18next";
|
||||
|
||||
import "./workflow-phase-badge.css";
|
||||
|
||||
export function phaseBadge(
|
||||
phase: "pre-merge" | "post-merge",
|
||||
id: string,
|
||||
|
||||
Reference in New Issue
Block a user