mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-13 04:02:28 +02:00
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The Mine inbox combines tasks, failed runs, approvals, and access requests > - Each item needs a consistent action that removes it from the inbox > - Task rows keep the Archive action separate from the unread marker > - Other rows used one slot for both actions, so an unread marker hid Archive > - This pull request gives every Mine inbox row the same Archive action > - The benefit is consistent hover and swipe cleanup for every inbox item type ## Linked Issues or Issue Description **What happened?** Unread failed runs, approvals, and join requests showed a blue unread marker but no Archive button. The user had to mark the item as read before the old leading Archive control became available. **Expected behavior** Every Mine inbox item shows Archive on hover. Every item also keeps its swipe-to-archive behavior. **Steps to reproduce** 1. Open the Mine inbox. 2. Add an unread failed run, approval, or join request. 3. Hover the new item. 4. Observe that Archive is missing before this change. **Paperclip version or commit** Current `master` at `0e9b03832d`. **Deployment mode** Local development from source. **Additional context** PR #1860 improves the accessibility of the existing swipe gesture. PR #9704 changes server-side archive resurfacing rules. Neither PR adds the missing hover action to unread non-task rows. ## What Changed - Reused the task-row Archive action for failed runs, approvals, and join requests. - Kept the unread marker visible in its own leading slot. - Kept retry, approve, and reject actions beside the new trailing Archive action. - Added regression coverage for hover Archive and swipe wrappers on every non-task Mine row type. - Updated a test comment so the repository token gate does not treat documented color literals as UI source. ## Verification - `pnpm --filter @paperclipai/ui exec vitest run src/pages/Inbox.test.tsx src/components/IssueRow.test.tsx src/components/SwipeToArchive.test.tsx` — 46 tests passed. - `pnpm --filter @paperclipai/ui typecheck` — passed. - `pnpm check:token-gates` — passed. - `pnpm -r typecheck` — passed. - `pnpm test:run` — 4,284 tests passed. Ten unrelated runtime-exposure tests cannot claim fixed ports 42000 and 52000 because host Tailscale listeners already own them. - `pnpm build` — passed. - GitHub CI on the latest head — all required checks passed. - Greptile — 5/5 confidence with no open review threads. ## Risks - Low risk. The change only affects Mine inbox row actions and regression tests. - The server archive and dismiss APIs do not change. - Retry, approve, and reject behavior does not change. - No documentation change is required because this fix restores the expected inbox behavior. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex based on GPT-5. The runtime did not expose a dated model ID or context-window size. Reasoning, terminal tool use, code execution, and GitHub integration were enabled. ## 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 - [x] All Paperclip CI gates are green - [x] 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>
71 lines
3.1 KiB
TypeScript
71 lines
3.1 KiB
TypeScript
import { readFileSync } from "node:fs";
|
|
import { fileURLToPath } from "node:url";
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
import { codeBlockActionStyle } from "./MarkdownBody";
|
|
|
|
const stylesheet = readFileSync(fileURLToPath(new URL("../index.css", import.meta.url)), "utf8");
|
|
|
|
function cssBlock(selector: string): string {
|
|
const start = stylesheet.indexOf(`${selector} {`);
|
|
expect(start, `Missing CSS selector: ${selector}`).toBeGreaterThanOrEqual(0);
|
|
|
|
const bodyStart = stylesheet.indexOf("{", start);
|
|
const bodyEnd = stylesheet.indexOf("\n}", bodyStart);
|
|
expect(bodyStart, `Missing CSS block start: ${selector}`).toBeGreaterThanOrEqual(0);
|
|
expect(bodyEnd, `Missing CSS block end: ${selector}`).toBeGreaterThan(bodyStart);
|
|
|
|
return stylesheet.slice(bodyStart + 1, bodyEnd);
|
|
}
|
|
|
|
/* The rendered code block used to be pinned to fixed Catppuccin literals
|
|
in the normal AND the prose-invert variables. A code
|
|
block therefore stayed dark in light mode. These tests fail if any of
|
|
those surfaces is pinned to a literal again, rather than riding a token
|
|
that carries a `.dark` override. */
|
|
|
|
describe("markdown code block styles", () => {
|
|
it("rides theme tokens for the rendered code block surface", () => {
|
|
const block = cssBlock(".paperclip-markdown pre");
|
|
|
|
expect(block).toContain("background-color: var(--muted)");
|
|
expect(block).toContain("color: var(--foreground)");
|
|
expect(block).toContain("border: 1px solid var(--border)");
|
|
expect(block).toContain("border-radius: var(--radius-lg)");
|
|
});
|
|
|
|
it("rides theme tokens for the editor content code block surface", () => {
|
|
const block = cssBlock(".paperclip-mdxeditor-content pre");
|
|
|
|
expect(block).toContain("background: var(--muted)");
|
|
expect(block).toContain("color: var(--foreground)");
|
|
expect(block).toContain("border: 1px solid var(--border)");
|
|
expect(block).toContain("border-radius: var(--radius-lg)");
|
|
});
|
|
|
|
it("points the normal and inverted prose variables at the same tokens", () => {
|
|
const block = cssBlock(".paperclip-markdown");
|
|
|
|
expect(block).toContain("--tw-prose-pre-bg: var(--muted)");
|
|
expect(block).toContain("--tw-prose-pre-code: var(--foreground)");
|
|
expect(block).toContain("--tw-prose-invert-pre-bg: var(--muted)");
|
|
expect(block).toContain("--tw-prose-invert-pre-code: var(--foreground)");
|
|
});
|
|
|
|
it("keeps every themed code surface free of hardcoded colors", () => {
|
|
for (const selector of [".paperclip-markdown pre", ".paperclip-mdxeditor-content pre", ".paperclip-markdown"]) {
|
|
// Any hex literal, or an rgb()/hsl() literal, re-pins the surface to one mode.
|
|
expect(cssBlock(selector), `${selector} must not hardcode a color`).not.toMatch(
|
|
/#[0-9a-f]{3,8}\b|\brgba?\(|\bhsla?\(/i,
|
|
);
|
|
}
|
|
});
|
|
|
|
it("separates the copy and wrap controls from the code block surface", () => {
|
|
// The controls sit on top of the block. --muted is now the block's own
|
|
// fill, so the controls must not use it or they disappear against it.
|
|
expect(codeBlockActionStyle.backgroundColor).toBe("var(--background)");
|
|
expect(codeBlockActionStyle.backgroundColor).not.toContain("--muted");
|
|
});
|
|
});
|