Files
PaperClipAI/ui
TonioandClaude Fable 5.1 c3c2a680ee fix(ui): lift a picture front on hover like the sheets in Artifacts V1 (#17263)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The Artifacts page, the panel's Artifacts tab and the task thread
show the artifacts that agents produce. Behind the experimental setting
Artifacts V1 (#17228) they use the presentation that the artifact
directions lab settled.
> - On the Artifacts page, a hovered tile turns the two backing pages of
a stack and lifts the front artwork by 6px. The lift targets the
`data-artifact-front` hook. Sheets carry the hook. A picture or
poster-less video front is a bare print and does not carry it.
> - So on a picture stack, or a single picture tile, the backings turn
but the artwork stands still. Tonio saw this on staging today.
> - This pull request puts the print inside the same lifted wrapper as
the sheets.
> - The benefit is that every front moves the same way on hover, as the
lab and the mocks do.

## Linked Issues or Issue Description

Refs #17228 (the Artifacts V1 pull request that introduced the hover
rules and the print front).

**What happened?**

With Artifacts V1 on, hover a task stack on the Artifacts page whose
newest artifact is a picture. The two backing pages turn by 5°, but the
picture does not rise. A single picture tile does not rise either. Sheet
fronts (documents, text, files) rise 6px as designed.

**Expected behavior**

Every front rises 6px while its tile is hovered, as the lab's MVP V1 kit
and the PCLP-Core mocks show, and as `index.css` already specifies for
`data-artifact-front`.

**Steps to reproduce**

1. Settings → Experimental → turn on Artifacts V1.
2. Open the Artifacts page with a task whose newest artifact is a
picture.
3. Hover the task's stack. The backings fan out; the picture stays where
it is.

**Paperclip version or commit**

master at 12bb7e197 (staging, tonio-robotics workspace) and at 989ee668e
locally. Verified on staging through the hovered tile: the stack had no
`[data-artifact-front]` element and the print's computed transform was
`none`.

**Deployment mode**

Cloud-managed staging tenant, and the local worktree instance. The
behaviour is browser-side and does not depend on the deployment.

## What Changed

- `ArtifactFront` renders the `media` treatment inside the same
`data-artifact-front` wrapper as the three sheet treatments. The
caller's placement style moves to the wrapper, and `ArtifactPrint` keeps
its own size. No change to `ArtifactPrint`, `ArtifactStack` or the hover
rules.
- `ArtifactTile.test.tsx`: the picture stack test now asserts the print
sits inside the lifted wrapper and that the wrapper, not the print,
carries the stack's absolute placement. A new test covers a single
picture tile.

## Verification

- `cd ui && npx vitest run src/components/artifacts/v1
src/pages/Artifacts` → 7 files, 42 tests pass.
- `pnpm check:token-gates` → all gates clean.
- `cd ui && pnpm typecheck` → the Storybook catalog check passes; `tsc
-b` reports only the five pre-existing `PluginOrganizationSwitcher.tsx`
TS7006 errors that master has without this change.
- Storybook, story `components-artifact-v1-primitives--stacks`, hovered
the ACM-5 picture stack: the front's computed transform is `matrix(1, 0,
0, 1, 0, -6)` and the two backings read ±5° from their resting angles,
with the 300ms transition. Before the change the same tile had no
`[data-artifact-front]` and the print's transform was `none`.
- Reduced motion is unchanged: the rules stay under
`prefers-reduced-motion: no-preference`.

## Risks

Low risk. The change adds one wrapper `div` around the print on the
Artifacts page tiles only, behind the Artifacts V1 setting, which is off
by default. The wrapper is `shrink-0` with no size of its own, so it
takes the print's size, and the placement style that the stack passed to
the print now lands on the wrapper. The thread and panel rows do not use
`ArtifactFront` and are untouched.

> 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

- Claude Fable 5.1 (Anthropic), model ID `claude-fable-5-1`, extended
thinking, running in Claude Code with tool use (file edits, shell,
in-app browser for the staging and Storybook checks).

## 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

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 18:17:47 -08:00
..

@paperclipai/ui

Published static assets for the Paperclip board UI.

What gets published

The npm package contains the production build under dist/. It does not ship the UI source tree or workspace-only dependencies.

Storybook

Storybook config, stories, and fixtures live under ui/storybook/.

pnpm --filter @paperclipai/ui storybook
pnpm --filter @paperclipai/ui build-storybook

Typical use

Install the package, then serve or copy the built files from node_modules/@paperclipai/ui/dist.

Editor dependency identity

Keep the root and workspace overrides for @codemirror/state, @codemirror/view, and @lezer/common aligned. CodeMirror requires shared extension identity, while Lezer parsers and syntax highlighters require shared NodeProp IDs. Multiple Lezer copies can crash code-block highlighting with tags is not iterable. src/lib/codemirror-single-instance.test.ts checks the installed dependency graph and highlights sample code through the editor's real language dependencies. GitHub Actions owns regeneration of pnpm-lock.yaml.