Skip to content

refactor(sidebar): レイアウト刷新と親子ハイライト#513

Merged
miyaoka merged 3 commits into
mainfrom
refactor/sidebar-layout
May 14, 2026
Merged

refactor(sidebar): レイアウト刷新と親子ハイライト#513
miyaoka merged 3 commits into
mainfrom
refactor/sidebar-layout

Conversation

@miyaoka

@miyaoka miyaoka commented May 14, 2026

Copy link
Copy Markdown
Owner

概要

サイドバーのレイアウトを刷新し、repo / wt / task の視覚階層を整理しました。task の並び順を静的化、scrollbar によるレイアウト変動を撤去、wt と task の親子関係をブロック塗りで表現します。

背景

サイドバーには次の問題がありました。

  • 階層が逆転していた: repo header が py-1.5 text-xs に対し wt header が py-2 text-sm で、子要素のほうが視覚的に強い
  • task ソートが動的: state 優先順 + lastActivityAt を sort key にしていたため、Claude が動くたびに行位置が入れ替わり、空間記憶が壊れる (wt や repo は append 順固定なのに task だけ動的、という非対称設計)
  • scrollbar が content 上に被る: 右端の git diff バッジが macOS overlay scrollbar や scrollbar-gutter:stable のガター幅と干渉
  • highlight が二者択一だった: focus が task にあるとき wt header の active 表示が落ち、「どの wt のどの task に focus か」が一目で分からない
  • terminal count バッジが phantom gap の原因: grid-cols-[auto_1fr_auto_auto] で 4 列目が空でも track gap が予約され、status badge の右端が TaskRow の経過時刻と 8px ズレる

変更内容

視覚階層の反転

  • repo header: py-2.5 text-sm / icon size-5 / lucide--folder-open (展開時) / lucide--folder (折り畳み時) — folder-git-2 差分はやめ、collapse 状態を icon で示す
  • wt header: py-1 text-xs / icon size-3.5 (列幅は size-5 wrapper で統一) — repo よりコンパクト
  • task: p-2 line-clamp-2 break-all — 2 行表示対応。経過時刻は text-[10px]

task ソートの静的化

  • task.createdAt 昇順 (append 順) のみ
  • STATE_PRIORITY / resolveStateKey / stateKey / baseTime フィールドを削除
  • lastActivityAtTaskRow の相対時刻表示用にのみ残す (動的キーをソートで使うのを廃止し、表示用と分離)
  • <doc> ブロックに「append 順 / 状態は icon + 相対時刻で表現」の責務分担を明記

親領域ハイライト

  • <article> (wt ブロック全体) に data-[active=true]:bg-blue-500/10 の薄塗り
  • TaskRow active に bg-blue-500/30 の中濃 capsule
  • 同色相の濃度差 (10% / 30%) で親子の階層を表現
  • wt header / repo header の active 時文字色変更 (text-blue-300) を撤去 — 面塗りの濃度で active を表現済みなので文字色との二重表現は冗長
  • headerActiveprops.active 単体評価に変更 (旧: props.active && focusedTaskId === undefined の排他)

レイアウト精度の改善

  • grid 4 列構成を flex + flex-1 に変更 (phantom gap 解消で右端コンテンツ x 座標が統一)
  • メニュー ⋮ ボタンを wt 行の relative wrapper 内に absolute right-1 top-1/2 で配置 — task 行を含む article 全体を基準にすると task 追加で縦中央が下方にずれる
  • terminal count バッジを削除 (関連 prop チェーン getTerminalCount も剥がす)
  • 経過時刻バッジを content-fit 化 (固定 size-4 廃止) で右端を 21m と揃える

scrollbar 撤去

  • scrollbar-width: none + ::-webkit-scrollbar { display: none } で完全非表示
  • macOS native の trackpad / wheel / keyboard でスクロール可能なため scrollbar UI 自体が不要、content がフル幅を保てる
  • scrollbar-gutter: stable および classic 強制 (::-webkit-scrollbar { width: 10px }) は「scrollbar 列を常時予約」する点で content 幅を犠牲にするため不採用

padding / gap の SSOT 化

  • サイドバー横余白の責務を RepoSectionp-2 に集約
  • repo 間: SidebarPane 外枠 flex flex-col (gap なし)
  • wt 間: RepoSectionflex flex-col (gap なし、wt ヘッダの py-1 で行高制御)
  • header / wt list 間: gap-2 (8px)
  • ラベル左端 x 座標を repo / wt / task で統一 (icon 列 20px + gap 8px = 28px)

その他

  • + New worktree ボタンを破線ボーダーのゴーストボタン化 + 中央寄せ
  • <dialog> 確認ダイアログ内の mt-2 / mb-4flex flex-col gap-4 に置換 (margin → gap)
  • useTerminalStorecollectLeafIds export を削除 (knip 自動修正)

確認事項

  • サイドバーで repo / wt / task の階層が視覚的に repo > wt > task の順で識別できる
  • task 行の並びが Claude の活動で動かない (createdAt 昇順固定)
  • active wt のブロック全体が薄い青、focus task に中濃の capsule が同時に出る
  • scrollbar が出現しても content 幅がジャンプしない
  • git diff バッジと task の経過時刻が右端で揃っている
  • folder icon が collapse 状態と連動 (折り畳み時 folder / 展開時 folder-open)
  • + New worktree の hover で border / bg / text が変化
  • メニュー ⋮ ボタンが wt 行の縦中央に固定 (task が増えても下にズレない)

miyaoka added 2 commits May 14, 2026 23:06
intent(sidebar): repo / wt / task の視覚階層を反転 (repo を強調・wt をコンパクト) し、task は 2 行表示可能に
decision(task-sort): `task.createdAt` 昇順 (append 順) — state や `lastActivityAt` のような動的キーで行位置が入れ替わる挙動を廃止し、wt / repo の append 順方針と統一
rejected(task-sort): state 優先順 (asking > working > done > idle > resumable) + `lastActivityAt` — Claude 活動ごとに行が動き空間記憶を破壊する。state は行頭アイコン、活動時刻は右端表示で既に可視化済みのため位置で二重表現する必要なし
rejected(task-sort): `createdAt` 降順 (新しい順) — 新規 task 作成のたびに既存 task が 1 行下にズレるため append 順を選択
decision(wt-row): grid `[auto_1fr_auto_auto]` → flex + `flex-1` — 4 列目が空のとき phantom gap (8px) が残り status badge の右端が TaskRow の "21m" 右端より内側にズレるため
decision(menu-button): wt 行の relative wrapper 内に absolute 配置 — task 行を含む article 全体を基準にすると task 追加で縦中央位置が下方にずれる
decision(hierarchy): icon サイズで階層を表現 — repo `size-5` / wt `size-3.5` (size-5 wrapper で列幅は統一しラベル左端 x=28px に揃える) / task `size-5`
decision(highlight): active wt header + focused task の両方を同時にハイライト — 「どの wt のどの task に focus があるか」を 2 軸で識別可能に
decision(folder-icon): collapsed → `lucide--folder` / expanded → `lucide--folder-open` — git repo か否かの差分 (`folder-git-2` vs `folder`) は wt 行の branch icon と git status badge で表現済みなので repo header で重複させない
constraint(padding-ssot): サイドバー横余白の責務は RepoSection の `p-2` に集約 — SidebarPane の `px-3` および section の旧 `p-1` を撤去
learned(grid-gap): CSS Grid の `gap` は track 間に常に予約される。`grid-cols-[auto_1fr_auto_auto]` で最後の auto 列が空でも gap-2 (8px) は維持され、右端コンテンツの x 座標が他の grid 構成 (3 列) とズレる原因になる
intent(sidebar): wt と task を親子構造として表現したい。task focus 時に wt 全体も同時にハイライトすることで「どの wt のどの task に focus があるか」を 2 軸で識別する
decision(highlight): article (= wt ブロック全体) に `bg-blue-500/10` の薄塗り + task active に `bg-blue-500/30` の中濃 capsule — 同色相の濃度差 (10% / 30%) で親子の階層を表現
decision(active-text): wt header / repo header の active 時文字色変更 (`text-blue-300`) を撤去 — 面塗りの濃度で active を表現済みなので文字色との二重表現は冗長
rejected(scrollbar): `scrollbar-gutter: stable` — gutter が常時インセットとして残る挙動を不採用
rejected(scrollbar): `::-webkit-scrollbar` で classic 強制 — scrollbar 用の列を常時予約する点で gutter:stable と効果が同じ
decision(scrollbar): `scrollbar-width: none` + `::-webkit-scrollbar { display:none }` で完全非表示 — macOS native の trackpad / wheel / keyboard でスクロール可能なため scrollbar UI 自体が不要、content がフル幅を保てる
decision(wt-row): `py-1` (4px) で行高をコンパクト維持 — task の `p-2` と差を付け wt は密に、task は読みやすくの非対称構成
constraint(platform): gozd は macOS 26 専用なので Windows / Linux のマウスユーザー向け scrollbar UX を考慮する必要なし
learned(tailwind-v4): `--alpha()` は Tailwind v4 の `@apply` 文脈専用で raw CSS では使えない。raw `<style>` 内で theme 変数 + 半透明を表現するなら `color-mix(in srgb, var(--color-zinc-XXX) N%, transparent)` を使う
@miyaoka miyaoka self-assigned this May 14, 2026
@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Rate limit exceeded

@miyaoka has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 52 minutes and 6 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: eae440e8-386e-4dc1-bdff-421a79c7ef9d

📥 Commits

Reviewing files that changed from the base of the PR and between e6f2d6a and 5cce94f.

📒 Files selected for processing (2)
  • apps/renderer/src/features/sidebar/features/worktree/TaskRow.vue
  • apps/renderer/src/features/sidebar/features/worktree/WtCard.vue
📝 Walkthrough

Walkthrough

このプルリクエストはサイドバーのワークツリーカード実装を整理し、ターミナルカウント表示機能を削除してタスク表示ロジックを簡素化します。terminal モジュールから collectLeafIds エクスポートを削除し、SidebarPane と RepoSection から getTerminalCount 関連のコードを除去。WtCard ではタスクの並び順を従来の状態優先・時刻ベースから task.createdAt 昇順に変更し、関連するソートロジックを廃止。ヘッダハイライト判定を props.active のみに簡潔化し、CSS 制御を data 属性ベースに変更。あわせて TaskRow のレイアウトを flex ベースに更新し、テキスト表示とスタイルを調整します。

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed PR タイトルは「refactor(sidebar): レイアウト刷新と親子ハイライト」で、サイドバーのレイアウト刷新と親子ハイライト機能追加という主要な変更を明確に要約しており、PR 内容と完全に一致している。
Description check ✅ Passed PR の説明は「概要」「背景」「変更内容」の3セクションで構成されており、サイドバーのレイアウト刷新、タスク並び順の静的化、親領域ハイライト実装、レイアウト精度改善など、実装内容と完全に対応している。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/sidebar-layout

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/renderer/src/features/sidebar/features/worktree/WtCard.vue (1)

105-158: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

data 属性ベースのスタイリングに移行

Line 106-107 と Line 113-114 で data-active 属性を使用し、Tailwind の data-[active=true]: バリアントでスタイル制御しています。

Tailwind v4 では boolean data 属性バリアントがサポートされているため、この実装は正しいです。ただし、Line 106 の data-active="active" は boolean 値を渡すべきです。

🔧 data 属性に boolean 値を渡す修正案

Line 106 では active (boolean) を直接渡していますが、明示的に boolean として扱うことを推奨します:

   <article
-    :data-active="active"
+    :data-active="active || undefined"
     class="rounded-lg transition-colors data-[active=true]:bg-blue-500/10"
   >

Vue では false の場合に属性自体が削除されるため、|| undefined を追加することで意図が明確になります。ただし、現在の実装でも動作上の問題はありません。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/renderer/src/features/sidebar/features/worktree/WtCard.vue` around lines
105 - 158, The data-active attributes should be passed as boolean/explicit so
Vue doesn't remove them when false; update both occurrences
(:data-active="active" on the <article> and :data-active="headerActive" on the
header div in WtCard.vue) to explicitly yield undefined when false (e.g. use
active || undefined and headerActive || undefined) so the data attribute is
present only when truthy and works with Tailwind's data-[active=true] variant.
🧹 Nitpick comments (1)
apps/renderer/src/features/sidebar/features/worktree/TaskRow.vue (1)

108-108: ⚡ Quick win

テキストの読みやすさのため break-words を検討してください。

break-all は単語の途中でも強制的に改行するため、タイトルテキストが読みづらくなる可能性があります。break-words を使用すると、まず単語境界で改行を試み、必要な場合のみ単語内で改行するため、より自然な表示になります。

♻️ 提案する修正
-    <span class="line-clamp-2 flex-1 text-sm break-all" :title="title">{{ title }}</span>
+    <span class="line-clamp-2 flex-1 text-sm break-words" :title="title">{{ title }}</span>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/renderer/src/features/sidebar/features/worktree/TaskRow.vue` at line
108, Replace the hard break behavior on the title span in TaskRow.vue: the span
with class "line-clamp-2 flex-1 text-sm break-all" (the element rendering
:title="title" and {{ title }}) should use "break-words" instead of "break-all"
so words are preferred break points and only broken when necessary; update that
class list accordingly and run a quick visual check for multi-word titles to
confirm improved readability.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/renderer/src/features/sidebar/features/worktree/TaskRow.vue`:
- Line 109: The timestamp span uses an extremely small fixed font class
`text-[10px]` which harms accessibility; replace that class with a slightly
larger size such as `text-[11px]` (or a Tailwind semantic size like `text-xs` /
`text-sm` if you prefer consistent design tokens) while keeping the
`tabular-nums` and `opacity-70` classes intact so the `relativeTime` rendering
remains visually subordinate but more readable.
- Line 99: Replace the use of the focus-visible:outline-none utility in the root
element's class string of TaskRow.vue with focus-visible:outline-hidden so that
the custom focus ring remains visually but accessibility in forced-colors mode
is preserved; locate the class containing "focus-visible:ring-2
focus-visible:ring-blue-500 focus-visible:outline-none" and change that token to
"focus-visible:outline-hidden".

---

Outside diff comments:
In `@apps/renderer/src/features/sidebar/features/worktree/WtCard.vue`:
- Around line 105-158: The data-active attributes should be passed as
boolean/explicit so Vue doesn't remove them when false; update both occurrences
(:data-active="active" on the <article> and :data-active="headerActive" on the
header div in WtCard.vue) to explicitly yield undefined when false (e.g. use
active || undefined and headerActive || undefined) so the data attribute is
present only when truthy and works with Tailwind's data-[active=true] variant.

---

Nitpick comments:
In `@apps/renderer/src/features/sidebar/features/worktree/TaskRow.vue`:
- Line 108: Replace the hard break behavior on the title span in TaskRow.vue:
the span with class "line-clamp-2 flex-1 text-sm break-all" (the element
rendering :title="title" and {{ title }}) should use "break-words" instead of
"break-all" so words are preferred break points and only broken when necessary;
update that class list accordingly and run a quick visual check for multi-word
titles to confirm improved readability.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: acd1aa72-93c6-4319-87f8-e4afa7c0985a

📥 Commits

Reviewing files that changed from the base of the PR and between 730e7c4 and e6f2d6a.

📒 Files selected for processing (5)
  • apps/renderer/src/features/sidebar/SidebarPane.vue
  • apps/renderer/src/features/sidebar/features/repo/RepoSection.vue
  • apps/renderer/src/features/sidebar/features/worktree/TaskRow.vue
  • apps/renderer/src/features/sidebar/features/worktree/WtCard.vue
  • apps/renderer/src/features/terminal/index.ts
💤 Files with no reviewable changes (1)
  • apps/renderer/src/features/terminal/index.ts

Comment thread apps/renderer/src/features/sidebar/features/worktree/TaskRow.vue Outdated
Comment thread apps/renderer/src/features/sidebar/features/worktree/TaskRow.vue
decision(focus-ring): Tailwind v4 では `outline-none` が outline 完全削除に変わったため、forced-colors mode でフォーカス枠が消える。`outline-hidden` は視覚的に隠しつつ forced-colors 用のアウトラインを維持する v4 専用ユーティリティで、こちらに統一
@miyaoka miyaoka merged commit e5fa426 into main May 14, 2026
7 checks passed
@miyaoka miyaoka deleted the refactor/sidebar-layout branch May 14, 2026 14:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant