fix(ui): improve mobile task spacing (#13304)
## Thinking Path > - Paperclip helps people manage AI agents and their work. > - The task detail view is the main place for task conversation. > - The mobile view used too much horizontal space for gutters and controls. > - The status control and identifier also reduced the title width. > - This pull request gives the title its own mobile row and reduces mobile padding. > - The benefit is a clearer task view with more space for useful content. ## Linked Issues or Issue Description **What existing behavior does this improve?** The mobile task detail header, conversation list, and message composer. **Current behavior** The title shares one row with status and identifier controls. The conversation and composer also use larger mobile gutters than needed. **Proposed behavior** The title uses the full mobile width. Status and metadata use the next row. The conversation and composer use smaller mobile gutters. **Reason and benefit** Long titles have more readable line lengths. The reduced padding gives task content more room on small screens. **Breaking changes** None. ## What Changed - Put the task title on a full-width mobile row. - Move the mobile status and metadata below the title. - Reduce the mobile conversation and composer padding. - Update the composer dock class test. ## Verification - `pnpm --filter @paperclipai/ui typecheck` - `pnpm exec vitest run ui/src/components/TaskChatThread.test.tsx ui/src/components/task-chat/TaskChatComposer.test.tsx ui/src/pages/IssueDetail.test.tsx --reporter=dot` - `pnpm --filter @paperclipai/ui build` - `pnpm check:token-gates` - `git diff --check` ## Risks - Low risk. The layout changes apply only at the mobile breakpoint. - Desktop spacing stays unchanged. > 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, GPT-5.6, with reasoning and tool use. ## 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 --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
This commit is contained in:
parent
8f40b4ad4b
commit
586b5ec828
|
|
@ -423,9 +423,9 @@ describe("TaskChatThread draft pass-through", () => {
|
|||
const thread = container.querySelector('[data-testid="task-chat-thread"]');
|
||||
expect(thread?.classList).not.toContain("h-(--tc-thread-max-h)");
|
||||
expect(thread?.classList).toContain("flex-1");
|
||||
expect(dock?.classList).toContain("px-2");
|
||||
expect(dock?.classList).toContain("px-1");
|
||||
expect(dock?.classList).toContain("md:px-0");
|
||||
expect(dock?.classList).not.toContain("px-1");
|
||||
expect(dock?.classList).not.toContain("px-2");
|
||||
expect(dock?.classList).not.toContain("-mt-(--radius-task-composer)");
|
||||
expect(dock?.classList).not.toContain("pt-1");
|
||||
expect(dock?.classList).toContain("md:pb-0");
|
||||
|
|
|
|||
|
|
@ -2889,7 +2889,7 @@ export function TaskChatThread(props: TaskChatThreadProps) {
|
|||
isMobile
|
||||
? "bottom-(--tc-composer-bottom) z-20 transition-[bottom] duration-200 ease-out"
|
||||
: "bottom-0 z-10",
|
||||
"mx-auto flex w-full max-w-(--tc-shell-max-w) flex-col gap-2 px-2 pb-2 md:px-4",
|
||||
"mx-auto flex w-full max-w-(--tc-shell-max-w) flex-col gap-2 px-1 pb-1 md:px-4 md:pb-2",
|
||||
streamlinedUiEnabled && "md:px-0 md:pb-0",
|
||||
(!streamlinedUiEnabled || isMobile) &&
|
||||
"bg-background/80 pt-1 backdrop-blur supports-[backdrop-filter]:bg-background/60 dark:bg-transparent dark:backdrop-blur-none dark:supports-[backdrop-filter]:bg-transparent",
|
||||
|
|
|
|||
|
|
@ -1074,7 +1074,7 @@ export function TaskChatComposer({
|
|||
streamlined
|
||||
? "paperclip-task-chat-composer rounded-(--radius-task-composer) border border-border bg-card p-(--sz-18px) shadow-(--shadow-task-composer) dark:border-0 dark:bg-muted dark:shadow-none"
|
||||
: "paperclip-task-chat-composer rounded-xl bg-card p-(--sz-18px)",
|
||||
mobile && "p-3",
|
||||
mobile && "p-2",
|
||||
)}
|
||||
onKeyDownCapture={(e) => {
|
||||
// Capture mode shortcuts on the wrapper so they work while the rich
|
||||
|
|
|
|||
|
|
@ -429,7 +429,7 @@ export function TaskChatThreadView({
|
|||
const body = (
|
||||
<div
|
||||
className={cn(
|
||||
"paperclip-mobile-thread mx-auto flex w-full max-w-(--tc-shell-max-w) flex-col px-2 py-4 md:px-4",
|
||||
"paperclip-mobile-thread mx-auto flex w-full max-w-(--tc-shell-max-w) flex-col px-1 py-3 md:px-4 md:py-4",
|
||||
streamlined ? "md:px-0" : "gap-5",
|
||||
className,
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -6752,8 +6752,8 @@ export function IssueDetail({ tasksTab }: { tasksTab?: TaskSidePanelProps["tasks
|
|||
)}
|
||||
>
|
||||
{streamlinedTaskDetailEnabled ? (
|
||||
<div className="flex min-w-0 items-center gap-2 pr-8">
|
||||
{issueStatusControl}
|
||||
<div className="flex min-w-0 items-start gap-2 md:items-center md:pr-8">
|
||||
<div className="hidden md:block">{issueStatusControl}</div>
|
||||
<div
|
||||
data-slot="task-detail-title"
|
||||
className="flex min-w-0 flex-1 items-baseline gap-2"
|
||||
|
|
@ -6766,7 +6766,7 @@ export function IssueDetail({ tasksTab }: { tasksTab?: TaskSidePanelProps["tasks
|
|||
/>
|
||||
<span
|
||||
data-slot="task-title-identifier"
|
||||
className="shrink-0 font-mono text-sm text-muted-foreground"
|
||||
className="hidden shrink-0 font-mono text-sm text-muted-foreground md:inline"
|
||||
>
|
||||
{issue.identifier ?? issue.id.slice(0, 8)}
|
||||
</span>
|
||||
|
|
@ -6777,9 +6777,17 @@ export function IssueDetail({ tasksTab }: { tasksTab?: TaskSidePanelProps["tasks
|
|||
<div
|
||||
className={cn(
|
||||
"flex min-w-0 flex-wrap items-center gap-2",
|
||||
streamlinedTaskDetailEnabled && "gap-x-6 gap-y-2 pl-7",
|
||||
streamlinedTaskDetailEnabled && "gap-x-3 gap-y-2 md:gap-x-6 md:pl-7",
|
||||
)}
|
||||
>
|
||||
{streamlinedTaskDetailEnabled ? (
|
||||
<div className="md:hidden">{issueStatusControl}</div>
|
||||
) : null}
|
||||
{streamlinedTaskDetailEnabled ? (
|
||||
<span className="shrink-0 font-mono text-sm text-muted-foreground md:hidden">
|
||||
{issue.identifier ?? issue.id.slice(0, 8)}
|
||||
</span>
|
||||
) : null}
|
||||
{!streamlinedTaskDetailEnabled ? issueStatusControl : null}
|
||||
{/* PAP-411: priority UI hidden behind SHOW_TASK_PRIORITY_UI. */}
|
||||
{SHOW_TASK_PRIORITY_UI && (
|
||||
|
|
|
|||
Loading…
Reference in New Issue