From 6415eed0c113766013671b417de757a76f373273 Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Thu, 25 Jun 2026 20:28:38 -0700 Subject: [PATCH] FN-7034: Align steps dropdown trigger styling Align the optional steps dropdown trigger with shared task creation button styling. - Reuse the dashboard btn btn-sm classes for the workflow optional steps trigger. - Remove bespoke trigger button styling so shared button tokens control padding, border, radius, and states. - Extend dropdown tests to cover shared classes across empty, selected, and disabled states. - Add a patch changeset for the published Fusion package. Files changed: .changeset/fn-7034-steps-dropdown-style.md | 7 +++ .../components/WorkflowOptionalStepsDropdown.css | 14 ------ .../components/WorkflowOptionalStepsDropdown.tsx | 9 +++- .../WorkflowOptionalStepsDropdown.test.tsx | 50 ++++++++++++++++++++-- 4 files changed, 61 insertions(+), 19 deletions(-) Fusion-Task-Id: FN-7034 Fusion-Task-Lineage: 3ca2a726-2c67-44a0-9a88-467e4fc1ad6b --- .changeset/fn-7034-steps-dropdown-style.md | 7 +++ .../WorkflowOptionalStepsDropdown.css | 14 ------ .../WorkflowOptionalStepsDropdown.tsx | 9 +++- .../WorkflowOptionalStepsDropdown.test.tsx | 50 +++++++++++++++++-- 4 files changed, 61 insertions(+), 19 deletions(-) create mode 100644 .changeset/fn-7034-steps-dropdown-style.md diff --git a/.changeset/fn-7034-steps-dropdown-style.md b/.changeset/fn-7034-steps-dropdown-style.md new file mode 100644 index 0000000000..046899d2ae --- /dev/null +++ b/.changeset/fn-7034-steps-dropdown-style.md @@ -0,0 +1,7 @@ +--- +"@runfusion/fusion": patch +--- + +summary: Match the optional steps dropdown trigger to shared task creation buttons. +category: fix +dev: Reuses the dashboard `.btn .btn-sm` trigger styling for WorkflowOptionalStepsDropdown. diff --git a/packages/dashboard/app/components/WorkflowOptionalStepsDropdown.css b/packages/dashboard/app/components/WorkflowOptionalStepsDropdown.css index 2a91a9f0fb..dff10a8c26 100644 --- a/packages/dashboard/app/components/WorkflowOptionalStepsDropdown.css +++ b/packages/dashboard/app/components/WorkflowOptionalStepsDropdown.css @@ -6,20 +6,6 @@ display: inline-flex; } -.wf-optional-steps-dropdown-trigger { - display: inline-flex; - align-items: center; - justify-content: space-between; - gap: 6px; - padding: 4px 8px; - font-size: 0.8rem; - border: 1px solid var(--border); - border-radius: var(--radius-sm, 6px); - background: var(--surface, transparent); - color: inherit; - cursor: pointer; -} - .wf-optional-steps-dropdown-trigger:disabled { opacity: 0.5; cursor: default; diff --git a/packages/dashboard/app/components/WorkflowOptionalStepsDropdown.tsx b/packages/dashboard/app/components/WorkflowOptionalStepsDropdown.tsx index 80fd71c0ad..87a23c1011 100644 --- a/packages/dashboard/app/components/WorkflowOptionalStepsDropdown.tsx +++ b/packages/dashboard/app/components/WorkflowOptionalStepsDropdown.tsx @@ -16,6 +16,11 @@ * matching the quick-add card's prior no-chip-block behavior and the modal's * empty-state choice, so both surfaces look identical. * + * FNXC:TaskCreationButtons 2026-06-25-00:00: + * The optional-steps trigger must reuse shared `.btn .btn-sm` styling so it has + * the same padding, background, border, radius, and interaction affordances as + * the quick-add and New Task action buttons on every creation surface. + * * Accessibility: trigger has aria-haspopup/aria-expanded; the panel is a * role="listbox" labelled by the trigger; each option is a role="option" with * aria-checked. Escape closes and refocuses the trigger; arrow keys move the @@ -145,7 +150,7 @@ export function WorkflowOptionalStepsDropdown({ ref={triggerRef} type="button" id={labelId} - className="wf-optional-steps-dropdown-trigger" + className="btn btn-sm wf-optional-steps-dropdown-trigger" data-testid={triggerTestId} aria-haspopup="listbox" aria-expanded={isOpen} @@ -157,7 +162,7 @@ export function WorkflowOptionalStepsDropdown({ onKeyDown={onTriggerKeyDown} > {triggerLabel} - + {isOpen && diff --git a/packages/dashboard/app/components/__tests__/WorkflowOptionalStepsDropdown.test.tsx b/packages/dashboard/app/components/__tests__/WorkflowOptionalStepsDropdown.test.tsx index 4d458345b2..6ceac1ab9e 100644 --- a/packages/dashboard/app/components/__tests__/WorkflowOptionalStepsDropdown.test.tsx +++ b/packages/dashboard/app/components/__tests__/WorkflowOptionalStepsDropdown.test.tsx @@ -13,8 +13,27 @@ const STEP: ResolvedWorkflowOptionalStep = { defaultOn: false, }; +const STEP_TWO: ResolvedWorkflowOptionalStep = { + templateId: "test-review", + name: "Test Review", + description: "Review test coverage", + icon: "check-circle", + phase: "post-implementation", + defaultOn: false, +}; + // Controlled host: parent owns the enabled set, mirroring the create surfaces. -function Host({ steps, initial = [] }: { steps: ResolvedWorkflowOptionalStep[]; initial?: string[] }) { +function Host({ + steps, + initial = [], + disabled = false, + triggerTestId, +}: { + steps: ResolvedWorkflowOptionalStep[]; + initial?: string[]; + disabled?: boolean; + triggerTestId?: string; +}) { const [enabled, setEnabled] = useState(initial); return ( setEnabled((prev) => (prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id])) } + disabled={disabled} + triggerTestId={triggerTestId} /> ); } +function expectSharedButtonTrigger(trigger: HTMLElement) { + expect(trigger).toHaveClass("btn", "btn-sm", "wf-optional-steps-dropdown-trigger"); + expect(trigger).toHaveAttribute("aria-haspopup", "listbox"); + expect(trigger).toHaveAttribute("aria-expanded"); +} + afterEach(() => { cleanup(); vi.clearAllMocks(); @@ -38,9 +65,26 @@ describe("WorkflowOptionalStepsDropdown", () => { expect(container.firstChild).toBeNull(); }); - it("reflects the selected count in the trigger label", () => { - render(); + it("uses shared button classes and preserves trigger attributes when none are selected", () => { + render(); + const trigger = screen.getByTestId("custom-optional-steps-trigger"); + expectSharedButtonTrigger(trigger); + expect(trigger).toHaveTextContent("Steps: none"); + expect(trigger).toHaveAttribute("aria-expanded", "false"); + }); + + it("uses shared button classes and count label when multiple steps are selected", () => { + render(); const trigger = screen.getByTestId("wf-optional-steps-dropdown-trigger"); + expectSharedButtonTrigger(trigger); + expect(trigger).toHaveTextContent("Steps: 2 selected"); + }); + + it("uses shared button classes and disabled semantics when submitting", () => { + render(); + const trigger = screen.getByTestId("wf-optional-steps-dropdown-trigger"); + expectSharedButtonTrigger(trigger); + expect(trigger).toBeDisabled(); expect(trigger).toHaveTextContent("Steps: none"); });