Files
PaperClipAI/ui
842efe0181 fix(ui): stack project field save indicator below its label (#14765)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The web UI has a project detail page. A properties panel on that
page lets a user edit the project name, description, and other fields.
> - Each field shows a "Saving...", "Saved", or "Failed" indicator while
an edit is in progress.
> - The indicator was rendered next to the label text in a fixed 80px
label column. The "Description" label almost fills that column, so the
indicator spilled into the value column and covered the description
text.
> - A user cannot read the description while the indicator is visible.
This looks broken and it hides content.
> - This pull request stacks the indicator directly below the label
text, so it stays inside the label column.
> - The benefit is that the indicator never covers the field value, for
the description and for every other labelled field.

## Linked Issues or Issue Description

No public GitHub issue exists for this bug. The issue is described here.

**What happened?**

When a user edits a project description in the project properties panel,
the "Saving..." and "Saved" indicator appears next to the "Description"
label. The label column is 80px wide. The indicator does not fit, so it
overflows into the value column and overlaps the description text.

**Expected behavior**

The "Saving..." / "Saved" / "Failed" indicator must appear directly
below the "Description" label. It must not overlap the description text
or any other field value.

**Steps to reproduce**

1. Open a project in the Paperclip web UI.
2. Click the Description field in the properties panel and change the
text.
3. Click outside the field to save.
4. Look at the "Description" label while the "Saving..." and then
"Saved" indicator is visible. The indicator overlaps the description
text.

**Paperclip version or commit**

master at `5edf55d7350c7f08c9dd132c7e0f1421fa0bf2fb`.

**Deployment mode**

Local development (`pnpm dev`). The bug is in the UI layout, so it
applies to every deployment mode.

## What Changed

- `ui/src/components/ProjectProperties.tsx`: `FieldLabel` now renders
the label text and the `SaveIndicator` in a vertical flex column
(`flex-col`) instead of a horizontal row. The indicator sits directly
below the label and stays inside the 80px label column. This applies to
every labelled property row (Name, Description, Env, and so on), so no
label can overflow.
- `ui/src/components/ProjectProperties.save-indicator.test.tsx`: new
regression test. It asserts that the indicator is a stacked sibling
under the Description label for the `saving` and `saved` states, and
that no indicator renders for the `idle` state.

## Verification

- Run `pnpm --filter @paperclipai/ui exec vitest run
src/components/ProjectProperties` from the repo root. All
ProjectProperties tests pass, including the new save-indicator test.
- The new test fails against the previous inline layout (2 of 3 cases
fail) and passes with this change (3 of 3 cases pass).
- The existing `ProjectProperties.concurrency`,
`ProjectProperties.managed-sandbox`, and `ProjectDetail` tests pass (18
tests).
- `tsc -b` in `ui/` reports no errors in the changed files.
- Manual check: open a project, edit the description, and save. The
"Saving..." and "Saved" indicator now appears below the "Description"
label and does not cover the description text.

## Risks

- Low risk. The change is a single flex-direction swap on the label
wrapper in one component.
- Every labelled row in the project properties panel gets a slightly
taller label cell while an indicator is visible. This is intentional and
it matches the requested layout.
- No data, API, or migration changes.

## Model Used

- Claude Fable 5.1 (Anthropic), model id `claude-fable-5-1`, with
extended thinking and tool use, run through Claude Code inside a
Paperclip agent session. A human reviewed the change and the pull
request text.

## 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)
- [ ] 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

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

Co-authored-by: Bender (Fable) <bender@paperclip.local>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-30 18:34:41 -07: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.