On desktop, the floating scroll-to-bottom button now shifts left
to stay clear of the properties panel when it's open (320px + margin).
Mobile positioning is unchanged.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The DialogContent base class applies sm:max-w-lg which was overriding
the wider max-w setting. Use \!important to ensure the modal takes up
90% of viewport width.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Long branch/folder paths now wrap with break-all instead of truncating
and overflowing. Copy icon is always visible instead of hover-only,
since the sidebar is narrow and hover-reveal was hiding it behind overflow.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Make modal much wider (90vw) to show full document content
- Use monospace font in diff area for better readability
- Enable word-wrap with pre-wrap so long lines wrap cleanly
without breaking line number gutters
- Move revision selectors into a single row with colored
Old/New badges instead of stacked Left:/Right: labels
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Add a "View diff" option to the document three-dot menu (visible when
revision > 1) that opens a modal showing side-by-side changes between
revisions using react-diff-viewer-continued. Defaults to comparing the
current revision with its predecessor, with dropdowns to select any two
revisions.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Adds a new workspace section to the IssueProperties sidebar that
displays branch name and folder path (cwd) from the execution
workspace. Both values have copy-to-clipboard buttons and truncated
display with full path on hover.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
When dragging files like .zip onto the issue description editor, non-image
files are now uploaded as attachments instead of being silently ignored.
Images continue to be handled inline by MDXEditor's image plugin.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
fixes https://github.com/paperclipai/paperclip/issues/2336
## Thinking Path
<!--
Required. Trace your reasoning from the top of the project down to this
specific change. Start with what Paperclip is, then narrow through the
subsystem, the problem, and why this PR exists. Use blockquote style.
Aim for 5–8 steps. See CONTRIBUTING.md for full examples.
-->
- Paperclip allows to manage projects
- During the project creation you can optionally enter a description
- In the project overview or configuration you can edit the description
- However, you cannot remove the description
- The user should be able to remove the project description because it's
an optional property
- This pull request fixes the frontend bug that prevented the user to
remove/clear the project description
## What Changed
<!-- Bullet list of concrete changes. One bullet per logical unit. -->
- project description can be cleared in "project configuration" and
"project overview"
## Verification
<!--
How can a reviewer confirm this works? Include test commands, manual
steps, or both. For UI changes, include before/after screenshots.
-->
In project configuration or project overview:
- In the description field remove/clear the text
## Risks
<!--
What could go wrong? Mention migration safety, breaking changes,
behavioral shifts, or "Low risk" if genuinely minor.
-->
- none
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
Address two Greptile review comments:
1. Collapsed parent badge now shows total descendant count at all depths
rather than direct-child count only. Add `countDescendants` utility to
issue-tree.ts (recursive, uses existing childMap) and replace
`children.length` with it in the titleSuffix badge.
2. Add a useEffect that prunes stale IDs from `collapsedParents` whenever
the issues prop changes. Deleted or reassigned issues previously left
orphan IDs in localStorage indefinitely; the effect filters to only IDs
that appear as a parentId in the current issue list and persists the
cleaned array via updateView.
Add four unit tests for countDescendants: leaf node, single-level,
multi-level, and unknown ID.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Extract the inline tree-building logic from IssuesList into a pure
`buildIssueTree` function in lib/issue-tree.ts so it can be unit tested.
Add six tests covering: flat lists, parent-child grouping, multi-level
nesting, orphaned sub-tasks promoted to root, empty input, and list
order preservation.
Add two tests to IssueRow.test.tsx covering the new titleSuffix prop:
renders inline after the title when provided, and renders cleanly when
omitted.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Move parent-task link out of the 2-column PropertyRow layout and into
a dedicated full-width section at the bottom of the panel, separated
by a Separator. Sub-tasks are listed in the same section when present.
Each item shows a StatusIcon aligned with the first line of wrapped
title text (items-start + mt-0.5 on the icon wrapper).
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Move collapsedParents from ephemeral useState into IssueViewState,
which is already serialised to localStorage under the scoped key.
Navigating away and back now restores the exact collapsed/expanded
state the user left the list in.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Replace the boolean isChild flag with a numeric depth counter.
Each depth level adds 16px left padding via inline style on the
wrapper div, so sub-tasks of sub-tasks (and deeper) are indented
proportionally rather than all aligning at the same level.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
When a parent issue is collapsed, its title is suffixed with
"(N sub-tasks)" so the count remains visible at a glance.
The suffix disappears when the parent is expanded.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The base IssueRow has sm:pl-1 which overrides pl-6 at sm+ breakpoints.
Adding sm:pl-7 ensures the indent is visible at all screen sizes.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Sub-tasks are now grouped under their parent issue in the list view.
Parent issues with children show a chevron to collapse/expand their subtasks.
Child issues are visually indented to indicate hierarchy.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Keep issue search local to the loaded list, defer heavy result updates, and memoize the rendered list body so typing stays responsive.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Root cause: CSS Grid items default to min-width:auto, allowing content
to push the dialog wider than the viewport on mobile.
- Add [&>*]:min-w-0 on DialogContent to prevent grid children from
expanding beyond the container width
- Keep overflow-x-hidden as safety net
- Remove negative-margin sticky footer that extended beyond bounds
- Revert to standard DialogFooter without negative margins
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add overflow-x-hidden on DialogContent to prevent horizontal scroll
- Truncate long monospace text (branch names, base refs) in git status grid
- Add min-w-0 on grid cells to allow truncation within CSS grid
- Add overflow-hidden on git status card and repo root section
- Add max-w-full + overflow-x-auto on pre blocks for long commands
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Replaces 12+ inline toggle button implementations across the app with a
shared ToggleSwitch component that scales up on mobile for better touch
targets. Default size is h-6/w-10 on mobile, h-5/w-9 on desktop; "lg"
variant is h-7/w-12 on mobile, h-6/w-11 on desktop.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Reduce padding and text sizes on small screens (p-4/text-xs -> sm:p-6/sm:text-sm)
- Tighter spacing between sections on mobile (space-y-3 -> sm:space-y-4)
- Sticky footer so action buttons stay visible while scrolling
- Grid layout stays 2-col on all sizes for git status
- Add shrink-0 to loading spinner
Co-Authored-By: Paperclip <noreply@paperclip.ing>
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - The inline markdown editor (MarkdownEditor / MDXEditor) is used to
edit agent instructions, issue descriptions, and other content
> - When users paste agent instructions copied from terminals or
consoles, extra leading whitespace is uniformly added to every line
> - PR #2572 fixed markdown structure preservation on paste but did not
address the leading whitespace (dedent) problem
> - This pull request adds a Lexical paste normalization plugin that
strips common leading whitespace and normalizes line endings before
MDXEditor processes pasted content
> - The benefit is that pasted content from terminals/consoles renders
correctly without manual cleanup
## What Changed
- **`ui/src/lib/normalize-markdown.ts`** — Pure utility that computes
minimum common indentation across non-empty lines and strips it
(dedent), plus CRLF → LF normalization
- **`ui/src/lib/paste-normalization.ts`** — Lexical `PASTE_COMMAND`
plugin at `CRITICAL` priority that intercepts plain-text pastes,
normalizes the markdown, and re-dispatches cleaned content for MDXEditor
to process. Skips HTML-rich pastes.
- **`ui/src/components/MarkdownEditor.tsx`** — Registers the new plugin;
updates PR #2572's `handlePasteCapture` to use `normalizeMarkdown()`
(dedent + CRLF) instead of `normalizePastedMarkdown()` (CRLF only) for
the markdown-routing path
- **`ui/src/lib/paste-normalization.test.ts`** — 9 unit tests covering
dedent, CRLF normalization, mixed indent, empty lines, single-line
passthrough, and edge cases
## Verification
- `pnpm --dir ui exec vitest run src/lib/paste-normalization.test.ts` —
9 tests pass
- Manual: paste indented agent instructions from a terminal into any
inline markdown editor and confirm leading whitespace is stripped
## Risks
- Low risk. The plugin only activates for plain-text pastes (no HTML
clipboard data). HTML/rich pastes pass through unchanged. Single-line
pastes are not modified. The dedent logic is conservative — it only
strips whitespace common to all non-empty lines.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
Batch consecutive system events into a single collapsible group
instead of rendering each as a separate warn-toned block. Shows
count in header, expands on click.
- Fix external adapters (hermes, droid) not auto-selected when
navigating with ?adapterType= param — was using a stale
module-level Set built before async adapter registration
- Move SchemaConfigFields to render after thinking effort (same
visual area as Claude's chrome toggle) instead of bottom of
config section
- Extract SelectField into its own component to fix React hooks
order violation when schema fields change between renders
- Add onAdapterChange() subscription in registry.ts so
registerUIAdapter() notifies components when dynamic parsers
load, fixing stale parser for old runs
- Add parserTick to both RunTranscriptView and
useLiveRunTranscripts to force recomputation on parser change
- Plugin loader: install/reload/remove/reinstall external adapters
from npm packages or local directories
- Plugin store persisted at ~/.paperclip/adapter-plugins.json
- Self-healing UI parser resolution with version caching
- UI: Adapter Manager page, dynamic loader, display registry
with humanized names for unknown adapter types
- Dev watch: exclude adapter-plugins dir from tsx watcher
to prevent mid-request server restarts during reinstall
- All consumer fallbacks use getAdapterLabel() for consistent display
- AdapterTypeDropdown uses controlled open state for proper close behavior
- Remove hermes-local from built-in UI (externalized to plugin)
- Add docs for external adapters and UI parser contract