FN-9009: align Quick Add merger model row

Make the Quick Add merger model row consistent with the other role selectors.

- Label the top-level merger selector as Merger
- Align the merger icon spacing with other model menu rows
- Cover role labels, spacing, and override navigation

Files changed:
 .changeset/fn-9009-quick-add-merger-label.md       |  7 ++++
 .../dashboard/app/components/QuickEntryBox.tsx     | 25 ++++++++++---
 .../components/__tests__/QuickEntryBox.test.tsx    | 41 +++++++++++++++++++---
 3 files changed, 65 insertions(+), 8 deletions(-)

Fusion-Task-Id: FN-9009

Fusion-Task-Lineage: bfc915d6-7a8d-4f08-86e8-c270b5783458

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
gsxdsm
2026-08-12 15:19:49 -07:00
parent b0f623b100
commit e144e8c195
3 changed files with 65 additions and 8 deletions

View File

@@ -0,0 +1,7 @@
---
"@runfusion/fusion": patch
---
summary: Quick Add model menu now labels the merger row “Merger” with spacing matching other roles.
category: fix
dev: Adds the tasks.modelMerger translation key for the top-level Quick Add menu row.

View File

@@ -2427,7 +2427,11 @@ export function QuickEntryBox({ onCreate, onMoveTask, addToast, tasks = [], avai
}} }}
> >
{activeModelSubmenu === null ? ( {activeModelSubmenu === null ? (
// Top-level menu with Plan/Executor/Reviewer choices /*
* FNXC:QuickAddModelMenu 2026-08-12-22:04:
* Top-level model rows use bare role names and matching icon alignment because
* .model-menu-item-label has no gap. Submenu headers retain the "<Role> Model" form.
*/
<div className="model-menu-items"> <div className="model-menu-items">
<button <button
type="button" type="button"
@@ -2480,9 +2484,22 @@ export function QuickEntryBox({ onCreate, onMoveTask, addToast, tasks = [], avai
</span> </span>
<ChevronRight size={12} style={{ marginLeft: "auto", color: "var(--text-dim)" }} /> <ChevronRight size={12} style={{ marginLeft: "auto", color: "var(--text-dim)" }} />
</button> </button>
<button type="button" className={`model-menu-item ${hasMergerOverride ? "model-menu-item--active" : ""}`} onClick={() => setActiveModelSubmenu("merger")} data-testid="model-menu-merger"> <button
<span className="model-menu-item-label"><Brain size={12} /> {t("tasks.mergerModel", "Merger Model")}</span> type="button"
<span className="model-menu-item-value">{hasMergerOverride ? getModelBadgeLabel(mergerProvider, mergerModelId) : t("tasks.usingDefault", "Using default")}</span><ChevronRight size={12} style={{ marginLeft: "auto", color: "var(--text-dim)" }} /> className={`model-menu-item ${hasMergerOverride ? "model-menu-item--active" : ""}`}
onClick={() => setActiveModelSubmenu("merger")}
data-testid="model-menu-merger"
>
<span className="model-menu-item-label">
<Brain size={12} style={{ verticalAlign: "middle", marginRight: 6 }} />
{t("tasks.modelMerger", "Merger")}
</span>
<span className="model-menu-item-value">
{hasMergerOverride
? getModelBadgeLabel(mergerProvider, mergerModelId)
: t("tasks.usingDefault", "Using default")}
</span>
<ChevronRight size={12} style={{ marginLeft: "auto", color: "var(--text-dim)" }} />
</button> </button>
</div> </div>
) : ( ) : (

View File

@@ -2863,7 +2863,7 @@ describe("QuickEntryBox", () => {
expect(screen.getByTestId("model-nested-menu")).toBeTruthy(); expect(screen.getByTestId("model-nested-menu")).toBeTruthy();
}); });
it("shows Plan, Executor, and Reviewer options in model menu", () => { it("uses bare role labels and uniform icon spacing for every model-menu row", () => {
renderQuickEntryBox({}); renderQuickEntryBox({});
expandQuickEntry(); expandQuickEntry();
const textarea = screen.getByTestId("quick-entry-input"); const textarea = screen.getByTestId("quick-entry-input");
@@ -2871,9 +2871,42 @@ describe("QuickEntryBox", () => {
fireEvent.change(textarea, { target: { value: "Task with models" } }); fireEvent.change(textarea, { target: { value: "Task with models" } });
openModelMenu(); openModelMenu();
expect(screen.getByTestId("model-menu-plan")).toBeTruthy(); for (const [testId, role] of [
expect(screen.getByTestId("model-menu-executor")).toBeTruthy(); ["model-menu-plan", "Plan"],
expect(screen.getByTestId("model-menu-validator")).toBeTruthy(); ["model-menu-executor", "Executor"],
["model-menu-validator", "Reviewer"],
["model-menu-merger", "Merger"],
]) {
const row = screen.getByTestId(testId);
const label = row.querySelector(".model-menu-item-label");
const icon = label?.querySelector("svg") as SVGSVGElement | null;
expect(label?.textContent).toBe(role);
expect(icon).not.toBeNull();
expect(icon?.style.verticalAlign).toBe("middle");
expect(icon?.style.marginRight).toBe("6px");
}
expect(screen.getByTestId("model-menu-merger").textContent).not.toContain("Model");
});
it("keeps the Merger label after an override and opens its Model submenu", () => {
renderQuickEntryBox({});
expandQuickEntry();
const textarea = screen.getByTestId("quick-entry-input");
fireEvent.change(textarea, { target: { value: "Task with models" } });
openModelMenu();
fireEvent.click(screen.getByTestId("model-menu-merger"));
fireEvent.click(screen.getByTestId("dropdown-select-merger model"));
fireEvent.click(screen.getByTestId("model-submenu-back"));
const mergerRow = screen.getByTestId("model-menu-merger");
expect(mergerRow.querySelector(".model-menu-item-label")?.textContent).toBe("Merger");
expect(mergerRow.classList.contains("model-menu-item--active")).toBe(true);
fireEvent.click(mergerRow);
expect(screen.getByText("Merger Model")).toBeTruthy();
}); });
it("does not render a separate Thinking option in the model menu", () => { it("does not render a separate Thinking option in the model menu", () => {