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");
});