FN-7695: fix padding on Cursor CLI auth card
Fixes cramped padding on the Cursor CLI provider auth card in the dashboard. - Adjusted CSS spacing/padding rules in CursorCliProviderCard.css - Updated CursorCliProviderCard.tsx to apply the corrected layout - Added regression tests covering the card's rendering/padding behavior - Added a changeset documenting the patch-level fix Files changed: .changeset/fn-7695-cursor-cli-padding.md | 7 ++ .../app/components/CursorCliProviderCard.css | 19 +++++ .../app/components/CursorCliProviderCard.tsx | 14 +++- .../__tests__/CursorCliProviderCard.test.tsx | 96 ++++++++++++++++++++++ 4 files changed, 134 insertions(+), 2 deletions(-) Fusion-Task-Id: FN-7695 Fusion-Task-Lineage: 565a7e70-347c-4cbf-8ba1-a672b57c0021 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
7
.changeset/fn-7695-cursor-cli-padding.md
Normal file
7
.changeset/fn-7695-cursor-cli-padding.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@runfusion/fusion": patch
|
||||
---
|
||||
|
||||
summary: Fix misaligned padding on the Cursor CLI authentication card.
|
||||
category: fix
|
||||
dev: Wraps `CursorCliProviderCard`'s compact status line + binary-path control in a padded `.cursor-cli-provider-card__body` to match the header inset, mirroring the Claude CLI card's `.auth-provider-cli-details-body`.
|
||||
@@ -5,6 +5,20 @@
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/*
|
||||
FNXC:CursorCli 2026-07-08-00:00:
|
||||
Compact card body must be inset to match `.auth-provider-header`'s horizontal padding
|
||||
(`var(--space-sm) var(--space-md)`), mirroring `.auth-provider-cli-details-body` used by the
|
||||
Claude CLI card (`0 16px 12px` desktop / `0 14px 12px` mobile). Without this, the status line and
|
||||
binary-path control render flush against the card's left/right/bottom edges. See FN-7695.
|
||||
*/
|
||||
.cursor-cli-provider-card__body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-sm);
|
||||
padding: 0 var(--space-md) var(--space-sm);
|
||||
}
|
||||
|
||||
.cursor-cli-binary-path-control {
|
||||
display: grid;
|
||||
gap: var(--space-xs);
|
||||
@@ -45,4 +59,9 @@
|
||||
.cursor-cli-binary-path-input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* FNXC:CursorCli 2026-07-08-00:00: mirror `.auth-provider-cli-details-body`'s 14px mobile inset. */
|
||||
.cursor-cli-provider-card__body {
|
||||
padding: 0 var(--space-sm) var(--space-sm);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,8 +167,18 @@ export function CursorCliProviderCard({ authenticated, compact = false, onToggle
|
||||
</div>
|
||||
<div className="auth-provider-cli-actions">{actions}</div>
|
||||
</div>
|
||||
<small className="settings-muted">{statusText}</small>
|
||||
{binaryPathControl}
|
||||
{/*
|
||||
FNXC:CursorCli 2026-07-08-00:00:
|
||||
`.auth-provider-card` has no padding of its own (padding:0; overflow:hidden) — only
|
||||
`.auth-provider-header` supplies the horizontal inset via `padding: var(--space-sm) var(--space-md)`.
|
||||
The status line and binary-path control below the header must be wrapped in a padded body
|
||||
so they line up with the header instead of rendering flush against the card edges,
|
||||
mirroring `.auth-provider-cli-details-body` on the Claude CLI card. See FN-7695.
|
||||
*/}
|
||||
<div className="cursor-cli-provider-card__body" data-testid="cursor-cli-provider-card-body">
|
||||
<small className="settings-muted">{statusText}</small>
|
||||
{binaryPathControl}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
import { describe, expect, it, vi, beforeEach } from "vitest";
|
||||
import { render, screen, waitFor } from "@testing-library/react";
|
||||
import { CursorCliProviderCard } from "../CursorCliProviderCard";
|
||||
|
||||
const fetchCursorCliStatus = vi.fn();
|
||||
const setCursorCliBinaryPath = vi.fn();
|
||||
const setCursorCliEnabled = vi.fn();
|
||||
|
||||
vi.mock("../../api", () => ({
|
||||
fetchCursorCliStatus: (...args: unknown[]) => fetchCursorCliStatus(...args),
|
||||
setCursorCliBinaryPath: (...args: unknown[]) => setCursorCliBinaryPath(...args),
|
||||
setCursorCliEnabled: (...args: unknown[]) => setCursorCliEnabled(...args),
|
||||
}));
|
||||
|
||||
const baseStatus = {
|
||||
binary: { available: true, version: "1.0.0", binaryPath: "/usr/local/bin/cursor-agent", probeDurationMs: 5 },
|
||||
enabled: true,
|
||||
binaryPath: "/usr/local/bin/cursor-agent",
|
||||
extension: null,
|
||||
ready: true,
|
||||
};
|
||||
|
||||
/*
|
||||
FNXC:CursorCli 2026-07-08-00:00:
|
||||
Regression coverage for FN-7695: the compact card's below-header content (status line +
|
||||
binary-path control) must be nested inside `.cursor-cli-provider-card__body`
|
||||
(data-testid="cursor-cli-provider-card-body") rather than being a bare direct child of
|
||||
`.auth-provider-card`, so it inherits the same horizontal/bottom inset as the header. The
|
||||
non-compact onboarding layout must NOT render this wrapper (its content already lives in the
|
||||
padded `.onboarding-provider-card__body`).
|
||||
*/
|
||||
describe("CursorCliProviderCard", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
fetchCursorCliStatus.mockResolvedValue(baseStatus);
|
||||
setCursorCliEnabled.mockResolvedValue({ enabled: true, binaryPath: baseStatus.binaryPath, restartRequired: true });
|
||||
setCursorCliBinaryPath.mockResolvedValue({ enabled: true, binaryPath: baseStatus.binaryPath, restartRequired: true });
|
||||
});
|
||||
|
||||
it("wraps compact status line + binary-path control in the padded body wrapper", async () => {
|
||||
render(<CursorCliProviderCard authenticated compact />);
|
||||
|
||||
const body = await screen.findByTestId("cursor-cli-provider-card-body");
|
||||
expect(body).toHaveClass("cursor-cli-provider-card__body");
|
||||
|
||||
// Status line must be inside the body wrapper.
|
||||
const status = await screen.findByText(/Connected/i);
|
||||
expect(body).toContainElement(status);
|
||||
|
||||
// Binary-path control (label + input) must be inside the body wrapper too.
|
||||
const label = screen.getByText("Cursor CLI binary path");
|
||||
expect(body).toContainElement(label);
|
||||
const input = screen.getByLabelText("Cursor CLI binary path");
|
||||
expect(body).toContainElement(input);
|
||||
|
||||
// The wrapper must be a child of the card root, not a sibling bare child alongside it.
|
||||
const card = screen.getByTestId("cursor-cli-provider-card");
|
||||
expect(card).toContainElement(body);
|
||||
});
|
||||
|
||||
it("keeps the body wrapper present before the status probe resolves (Probing…)", async () => {
|
||||
fetchCursorCliStatus.mockReturnValue(new Promise(() => {}));
|
||||
render(<CursorCliProviderCard authenticated={false} compact />);
|
||||
|
||||
const body = await screen.findByTestId("cursor-cli-provider-card-body");
|
||||
const status = await screen.findByText(/Probing local CLI/i);
|
||||
expect(body).toContainElement(status);
|
||||
});
|
||||
|
||||
it("keeps the body wrapper present when a pathMessage is shown after a failed save", async () => {
|
||||
setCursorCliBinaryPath.mockRejectedValueOnce(new Error("binary not found"));
|
||||
const { default: userEvent } = await import("@testing-library/user-event");
|
||||
const user = userEvent.setup();
|
||||
|
||||
render(<CursorCliProviderCard authenticated compact />);
|
||||
const input = await screen.findByLabelText("Cursor CLI binary path");
|
||||
await user.clear(input);
|
||||
await user.type(input, "/tmp/does-not-exist");
|
||||
|
||||
const saveButton = screen.getByRole("button", { name: /Save & Test/i });
|
||||
await user.click(saveButton);
|
||||
|
||||
const errorText = await screen.findByText("binary not found");
|
||||
const body = screen.getByTestId("cursor-cli-provider-card-body");
|
||||
expect(body).toContainElement(errorText);
|
||||
});
|
||||
|
||||
it("does not render the body wrapper in the non-compact onboarding layout", async () => {
|
||||
render(<CursorCliProviderCard authenticated />);
|
||||
|
||||
const card = await screen.findByTestId("cursor-cli-provider-card");
|
||||
expect(card).toHaveClass("onboarding-provider-card");
|
||||
await waitFor(() => expect(fetchCursorCliStatus).toHaveBeenCalled());
|
||||
expect(screen.queryByTestId("cursor-cli-provider-card-body")).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user