feat(FN-4159): shrink and keep visible the github tracking enable button in

Adds a compact GitHub tracking enable button in the task detail modal header, with a fix to keep it visible during save operations and further shrinking the inline CTA styling.

Fusion-Task-Id: FN-4159
This commit is contained in:
Fusion
2026-05-12 11:47:07 -07:00
committed by gsxdsm
parent fd16a5d2c5
commit 69e072e9ba
4 changed files with 58 additions and 4 deletions

View File

@@ -439,6 +439,9 @@
.detail-github-tracking-enable {
margin-left: auto;
align-self: center;
padding-block: calc(var(--space-xs) / 2);
padding-inline: var(--space-sm);
line-height: 1.2;
}
.detail-source-toggle {

View File

@@ -790,6 +790,8 @@ export function TaskDetailContent({
const canEditGithubTracking = GITHUB_TRACKING_EDITABLE_COLUMNS.has(task.column) && !isSaving;
const githubTrackingEnabled = githubTrackingEnabledDraft ?? (task.githubTracking?.enabled === true);
const githubTrackedIssue = task.githubTracking?.issue;
const showInlineGithubTrackingEnableButton =
canEditGithubTracking && !githubTrackedIssue && (!githubTrackingEnabled || (isSavingGithubTracking && task.githubTracking?.enabled !== true));
const showGithubTrackingSection = canEditGithubTracking || githubTrackingEnabled || Boolean(githubTrackedIssue);
const githubTrackingStatus = githubTrackedIssue ? "Linked" : githubTrackingEnabled ? "Enabled" : "Disabled";
const effectiveGithubRepoDefault = resolveEffectiveGithubRepoDefault(settings ?? null, globalSettings);
@@ -2391,15 +2393,15 @@ export function TaskDetailContent({
</span>
)}
</div>
{canEditGithubTracking && !githubTrackingEnabled && !githubTrackedIssue && !isSavingGithubTracking && (
{showInlineGithubTrackingEnableButton && (
<button
type="button"
className="btn btn-sm btn-primary touch-target detail-github-tracking-enable"
className="btn btn-sm btn-primary detail-github-tracking-enable"
aria-label="Enable GitHub tracking"
onClick={() => void handleToggleGithubTracking()}
disabled={isSavingGithubTracking}
>
Enable GitHub tracking
{isSavingGithubTracking ? "Saving…" : "Enable"}
</button>
)}
<button

View File

@@ -2203,7 +2203,7 @@ describe("TaskDetailModal", () => {
expect(screen.getByText("GitHub tracking")).toBeTruthy();
expect(screen.getByText("Tracking is currently disabled")).toBeTruthy();
expect(screen.getByRole("button", { name: "Enable GitHub tracking" })).toBeInTheDocument();
expect(screen.getByRole("button", { name: "Enable GitHub tracking" })).toHaveTextContent("Enable");
});
it("enables GitHub tracking via the inline header button without expanding the disclosure", async () => {
@@ -2243,6 +2243,50 @@ describe("TaskDetailModal", () => {
expect(screen.queryByRole("button", { name: "Collapse GitHub tracking details" })).toBeNull();
});
it("keeps the inline enable button mounted and disabled while saving", async () => {
const { updateTask } = await import("../../api");
const mockUpdate = vi.mocked(updateTask);
let resolveUpdate: ((task: Task) => void) | undefined;
mockUpdate.mockImplementationOnce(
() =>
new Promise((resolve) => {
resolveUpdate = resolve;
}),
);
render(
<TaskDetailModal
task={makeTask({
id: "FN-001",
column: "todo",
githubTracking: {
enabled: false,
},
})}
onClose={noop}
onOpenDetail={noopOpenDetail}
onMoveTask={noopMove}
onDeleteTask={noopDelete}
onMergeTask={noopMerge}
addToast={noop}
/>,
);
fireEvent.click(screen.getByRole("button", { name: "Enable GitHub tracking" }));
await waitFor(() => {
expect(screen.getByRole("button", { name: "Enable GitHub tracking" })).toBeDisabled();
});
expect(screen.getByRole("button", { name: "Enable GitHub tracking" })).toHaveTextContent("Saving…");
expect(screen.getByRole("button", { name: "Expand GitHub tracking details" })).toHaveAttribute("aria-expanded", "false");
resolveUpdate?.({ id: "FN-001" } as Task);
await waitFor(() => {
expect(screen.queryByRole("button", { name: "Enable GitHub tracking" })).toBeNull();
});
});
it("hides the inline enable button when tracking is already enabled", () => {
render(
<TaskDetailModal