feat(FN-3915): move mission manager CTA to sidebar footer on desktop
Refactored the MissionManager CTA for desktop by moving it to the sidebar footer and aligning its sizing contract, with corresponding test updates and docs refresh. Fusion-Task-Id: FN-3915
This commit is contained in:
@@ -29,7 +29,7 @@ Mission: Improve Reliability
|
||||
|
||||
Use the Mission Manager UI to create missions and build hierarchy interactively.
|
||||
|
||||
On mobile, Mission Manager now surfaces the primary **Plan New Mission** CTA at the top of the mission list for faster access, while desktop keeps the split-layout sidebar CTA as the primary entry point.
|
||||
On mobile, Mission Manager surfaces the primary **Plan New Mission** CTA at the top of the mission list for faster access, while desktop keeps the split-layout sidebar CTA anchored in the bottom action region as the primary entry point.
|
||||
|
||||
### CLI
|
||||
|
||||
|
||||
@@ -204,20 +204,22 @@
|
||||
box-shadow: var(--focus-ring-strong);
|
||||
}
|
||||
|
||||
/* Desktop split-only sidebar header layout for mission quick actions. */
|
||||
.mission-manager__sidebar-header {
|
||||
/* Desktop split-only sidebar footer action bar for mission creation CTA. */
|
||||
.mission-manager__sidebar-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: var(--space-sm);
|
||||
padding: var(--space-md);
|
||||
border-bottom: var(--btn-border-width) solid var(--border);
|
||||
border-top: var(--btn-border-width) solid var(--border);
|
||||
}
|
||||
|
||||
.mission-manager__sidebar-cta {
|
||||
width: 100%;
|
||||
min-height: calc(var(--space-lg) * 2 + var(--space-xs));
|
||||
justify-content: center;
|
||||
gap: var(--space-sm);
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
/* Hide duplicate sidebar title; the shared header already labels this view. */
|
||||
|
||||
@@ -3912,17 +3912,6 @@ export function MissionManager({ isOpen, isInline = false, onClose, addToast, pr
|
||||
aria-label="Mission list"
|
||||
style={isMobile ? undefined : { width: `${sidebarWidth}px` }}
|
||||
>
|
||||
<div className="mission-manager__sidebar-header">
|
||||
<button
|
||||
className="btn btn-sm btn-primary mission-manager__sidebar-cta"
|
||||
onClick={() => setShowInterviewModal(true)}
|
||||
title="Plan New Mission"
|
||||
aria-label="Plan New Mission"
|
||||
>
|
||||
<Sparkles size={14} />
|
||||
Plan New Mission
|
||||
</button>
|
||||
</div>
|
||||
<div className="mission-manager__sidebar-list">
|
||||
{loading ? (
|
||||
<div className="mission-manager__loading">
|
||||
@@ -3933,6 +3922,17 @@ export function MissionManager({ isOpen, isInline = false, onClose, addToast, pr
|
||||
renderMissionListContent({ hideBottomButtons: true })
|
||||
)}
|
||||
</div>
|
||||
<div className="mission-manager__sidebar-footer" data-testid="mission-sidebar-footer">
|
||||
<button
|
||||
className="btn btn-primary mission-manager__sidebar-cta"
|
||||
onClick={() => setShowInterviewModal(true)}
|
||||
title="Plan New Mission"
|
||||
aria-label="Plan New Mission"
|
||||
>
|
||||
<Sparkles size={14} />
|
||||
Plan New Mission
|
||||
</button>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
{!isMobile && (
|
||||
|
||||
@@ -135,6 +135,18 @@ describe("desktop two-panel split CSS", () => {
|
||||
expect(css).toContain("overflow-y: auto;");
|
||||
});
|
||||
|
||||
it("anchors desktop Plan New Mission CTA in a sidebar footer with tokenized height", () => {
|
||||
const css = loadAllAppCss();
|
||||
|
||||
const footerRule = css.match(/\.mission-manager__sidebar-footer\s*\{[^}]*\}/)?.[0];
|
||||
expect(footerRule).toContain("border-top: var(--btn-border-width) solid var(--border);");
|
||||
|
||||
const ctaRule = css.match(/\.mission-manager__sidebar-cta\s*\{[^}]*\}/)?.[0];
|
||||
expect(ctaRule).toContain("width: 100%;");
|
||||
expect(ctaRule).toContain("min-height: calc(var(--space-lg) * 2 + var(--space-xs));");
|
||||
expect(ctaRule).toContain("justify-content: center;");
|
||||
});
|
||||
|
||||
it("defines split container as flex row", () => {
|
||||
const css = loadAllAppCss();
|
||||
expect(css).toContain(".mission-manager__split {");
|
||||
|
||||
@@ -775,14 +775,17 @@ describe("MissionManager", () => {
|
||||
expect(mobileSpan?.textContent).toBe("Build Auth System");
|
||||
});
|
||||
|
||||
it("sidebar header surfaces a centered Plan New Mission CTA", async () => {
|
||||
it("renders the desktop Plan New Mission CTA in the sidebar footer action region", async () => {
|
||||
globalThis.fetch = createFetchMock();
|
||||
render(<MissionManager isOpen={true} onClose={vi.fn()} addToast={vi.fn()} />);
|
||||
|
||||
await waitFor(() => {
|
||||
const cta = document.querySelector(".mission-manager__sidebar-cta");
|
||||
const sidebar = screen.getByTestId("mission-sidebar");
|
||||
const sidebarFooter = within(sidebar).getByTestId("mission-sidebar-footer");
|
||||
const cta = within(sidebarFooter).getByRole("button", { name: "Plan New Mission" });
|
||||
|
||||
expect(cta).toBeInTheDocument();
|
||||
expect(screen.getByRole("button", { name: "Plan New Mission" })).toBeInTheDocument();
|
||||
expect(within(sidebar).queryByText("No missions yet")).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user