fix(ui): make feed cards fully clickable (#13294)
## Thinking Path > - Paperclip helps people manage AI agents and their work. > - The activity feed shows cards for recent work. > - A feed card showed a linked entity, but only some card content behaved as one clear click target. > - Users expect the image, title, and blank card space to open the entity. > - This pull request makes the full visible card use the entity link. > - It also adds a regression test for the full-card click target. > - The benefit is a larger and consistent navigation target. ## Linked Issues or Issue Description **What happened?** Clicks on some feed card content or blank card space did not reliably open the linked entity. **Expected behavior** A click anywhere in a linked feed card opens its entity quick view. **Steps to reproduce** 1. Open the activity feed. 2. Find a card that links to an entity. 3. Click its image, title, or blank space. 4. Observe that only part of the card acts as the link before this change. **Paperclip version or commit** Current `master` before this pull request. ## What Changed - Made each linked feed card anchor use the full available width. - Made the visible card width account for its existing page margins. - Added a component test that clicks the card and confirms link navigation. ## Verification - `pnpm --filter @paperclipai/ui exec vitest run src/components/FeedCard.test.tsx` - `pnpm check:token-gates` - `pnpm --filter @paperclipai/ui typecheck` ## Risks - Low risk. The change only expands the existing link click target. - The width calculation can affect feed card layout. The regression test checks the expected width classes. > This bug fix does not add a roadmap feature. ## Model Used - OpenAI GPT-5.6, Codex agent, with reasoning and code execution tools. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
This commit is contained in:
parent
09e208c54f
commit
30aa3740ba
|
|
@ -0,0 +1,73 @@
|
|||
// @vitest-environment jsdom
|
||||
|
||||
import { act } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import type { ActivityEvent } from "@paperclipai/shared";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { FeedCard } from "./FeedCard";
|
||||
|
||||
const navigate = vi.fn();
|
||||
|
||||
vi.mock("@/lib/router", () => ({
|
||||
Link: ({ children, issueQuicklookSide: _, to, ...props }: React.ComponentProps<"a"> & { issueQuicklookSide?: string; to: string }) => (
|
||||
<a {...props} href={to} onClick={navigate}>
|
||||
{children}
|
||||
</a>
|
||||
),
|
||||
}));
|
||||
|
||||
const event: ActivityEvent = {
|
||||
id: "event-1",
|
||||
companyId: "company-1",
|
||||
actorType: "user",
|
||||
actorId: "user-1",
|
||||
action: "issue.updated",
|
||||
entityType: "issue",
|
||||
entityId: "issue-1",
|
||||
agentId: null,
|
||||
runId: null,
|
||||
details: null,
|
||||
createdAt: new Date("2026-09-11T12:00:00.000Z"),
|
||||
};
|
||||
|
||||
describe("FeedCard", () => {
|
||||
let container: HTMLDivElement;
|
||||
|
||||
beforeEach(() => {
|
||||
container = document.createElement("div");
|
||||
document.body.appendChild(container);
|
||||
navigate.mockClear();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
container.remove();
|
||||
});
|
||||
|
||||
it("uses the whole visible card as the entity link", () => {
|
||||
const root = createRoot(container);
|
||||
act(() => {
|
||||
root.render(
|
||||
<FeedCard
|
||||
event={event}
|
||||
agentMap={new Map()}
|
||||
entityNameMap={new Map([["issue:issue-1", "PAP-1"]])}
|
||||
entityTitleMap={new Map([["issue:issue-1", "Clickable card"]])}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
|
||||
const link = container.querySelector<HTMLAnchorElement>('[data-fc="link"]');
|
||||
const card = container.querySelector<HTMLElement>('[data-fc="card"]');
|
||||
|
||||
expect(link).not.toBeNull();
|
||||
expect(link?.className).toContain("w-full");
|
||||
expect(card?.className).toContain("w-(--sz-calc-1)");
|
||||
expect(card?.className).toContain("md:w-(--sz-calc-2)");
|
||||
expect(link?.contains(card ?? null)).toBe(true);
|
||||
|
||||
card?.click();
|
||||
expect(navigate).toHaveBeenCalledOnce();
|
||||
|
||||
act(() => root.unmount());
|
||||
});
|
||||
});
|
||||
|
|
@ -437,7 +437,7 @@ export function FeedCard({
|
|||
<Card
|
||||
data-fc="card"
|
||||
className={cn(
|
||||
"flex-row group ml-3 mr-3 md:ml-0 my-2 items-center gap-2 p-(--sz-18px) text-xs",
|
||||
"flex-row group ml-3 mr-3 md:ml-0 my-2 w-(--sz-calc-1) md:w-(--sz-calc-2) items-center gap-2 p-(--sz-18px) text-xs",
|
||||
"transition-(--tp-background-color-border-color) duration-150",
|
||||
content.link && "cursor-pointer hover:bg-accent hover:border-muted-foreground/30",
|
||||
className,
|
||||
|
|
@ -480,7 +480,8 @@ export function FeedCard({
|
|||
return (
|
||||
<Link
|
||||
to={content.link}
|
||||
className="block no-underline text-inherit"
|
||||
data-fc="link"
|
||||
className="block w-full no-underline text-inherit"
|
||||
issueQuicklookSide="left"
|
||||
>
|
||||
{card}
|
||||
|
|
|
|||
Loading…
Reference in New Issue