diff --git a/.changeset/fn-7193-quick-add-steps-badge-checkbox-theme.md b/.changeset/fn-7193-quick-add-steps-badge-checkbox-theme.md new file mode 100644 index 0000000000..4d4cae063f --- /dev/null +++ b/.changeset/fn-7193-quick-add-steps-badge-checkbox-theme.md @@ -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. diff --git a/packages/dashboard/app/components/WorkflowOptionalStepsDropdown.css b/packages/dashboard/app/components/WorkflowOptionalStepsDropdown.css index 6cfb8b6f1e..dc665d7686 100644 --- a/packages/dashboard/app/components/WorkflowOptionalStepsDropdown.css +++ b/packages/dashboard/app/components/WorkflowOptionalStepsDropdown.css @@ -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); diff --git a/packages/dashboard/app/components/WorkflowResultsTab.css b/packages/dashboard/app/components/WorkflowResultsTab.css index 58a729dfb4..ea3eaa94b6 100644 --- a/packages/dashboard/app/components/WorkflowResultsTab.css +++ b/packages/dashboard/app/components/WorkflowResultsTab.css @@ -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); diff --git a/packages/dashboard/app/components/__tests__/WorkflowOptionalStepsDropdown.test.tsx b/packages/dashboard/app/components/__tests__/WorkflowOptionalStepsDropdown.test.tsx index 02e6663c4d..e601e43758 100644 --- a/packages/dashboard/app/components/__tests__/WorkflowOptionalStepsDropdown.test.tsx +++ b/packages/dashboard/app/components/__tests__/WorkflowOptionalStepsDropdown.test.tsx @@ -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/); diff --git a/packages/dashboard/app/components/__tests__/workflow-phase-badge.test.tsx b/packages/dashboard/app/components/__tests__/workflow-phase-badge.test.tsx new file mode 100644 index 0000000000..f1a2427d81 --- /dev/null +++ b/packages/dashboard/app/components/__tests__/workflow-phase-badge.test.tsx @@ -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*\{/); + }); +}); diff --git a/packages/dashboard/app/components/workflow-phase-badge.css b/packages/dashboard/app/components/workflow-phase-badge.css new file mode 100644 index 0000000000..bf4f220bdb --- /dev/null +++ b/packages/dashboard/app/components/workflow-phase-badge.css @@ -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); +} diff --git a/packages/dashboard/app/components/workflow-phase-badge.tsx b/packages/dashboard/app/components/workflow-phase-badge.tsx index fe5a171a97..7463ca6e70 100644 --- a/packages/dashboard/app/components/workflow-phase-badge.tsx +++ b/packages/dashboard/app/components/workflow-phase-badge.tsx @@ -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,