Skip to content

fix(web): squad rail toggle disappears when collapsed — restore 48×48 hit area#72

Merged
SymbolStar merged 1 commit into
mainfrom
fix/squad-rail-toggle-clickable
Jun 11, 2026
Merged

fix(web): squad rail toggle disappears when collapsed — restore 48×48 hit area#72
SymbolStar merged 1 commit into
mainfrom
fix/squad-rail-toggle-clickable

Conversation

@SymbolStar

Copy link
Copy Markdown
Owner

TL;DR

PR #70 让 squad rail 折叠后回不来:collapsed 状态下 .brand-title.brand-settings-btnvisibility:hidden 想 fade 走,但 visibility:hidden 在 flex 容器里仍占 layout 空间,所以 .rail-collapse-btnwidth:100% 实际只解析成约 9px——«/» 按钮视觉上消失也点不到。Scott 截图里 (574×875 自动折叠态) 的「折叠后就回不来了」就是这个原因。

Root cause

/* before */
body.squad-collapsed #squad-rail .brand-title,
body.squad-collapsed #squad-rail .brand-settings-btn {
  opacity: 0; transform: translateX(-8px);
  pointer-events: none; visibility: hidden;
}
body.squad-collapsed #squad-rail .rail-collapse-btn {
  width: 100%;   /* ← 在 flex 里被两个 hidden 兄弟挤占,实测渲染 9px */
  height: 48px; border-radius: 0;
}

puppeteer 实测 (1280px viewport, body.squad-collapsed):
toggle = { x: 26.20, y: 0, w: 9.04, h: 48 } — 9 像素宽的 toggle 用户根本看不到。

Fix

把 brand 行的两个 label 在 collapsed 时真正脱离 flex 流,用 display:none 取代 visibility:hidden;toggle 改 width:48px / min-width:48px 显式撑满 rail,font-size 调到 18px 便于点击。

body.squad-collapsed #squad-rail .brand-title,
body.squad-collapsed #squad-rail .brand-settings-btn {
  display: none;
}
body.squad-collapsed #squad-rail .rail-collapse-btn {
  width: 48px; min-width: 48px;
  height: 48px; border-radius: 0;
  font-size: 18px;
}

牺牲:这两个元素在折叠瞬间的 150ms fade 没了。但它们活在 48px 宽的 brand 行里,从 « 切到 » 的瞬间 fade 用户察觉不到——优先恢复可用性。其他 label(squad-name / section-label / new-squad-btn / status-text / unread-badge)的 fade 全部保留。

Verification (puppeteer)

viewport bodyClass toggle box footer ⚙ box
1280×800 collapsed squad-collapsed (72,0) 48×48 (76,756) 40×40
1280×800 expanded (none) (90,13) 22×22 display:none
574×875 自动折叠 squad-collapsed (72,0) 48×48 (76,831) 40×40

交互:

  • « (collapsed) → bodyClass = '' (expanded) ✓
  • 再点 » (expanded) → bodyClass = 'squad-collapsed' ✓
  • ⌘\ 切换 ✓
  • localStorage openforge.sidebar.squad.collapsed 在 'collapsed' / 'expanded' 之间正确翻转 ✓

Token discipline

CSS 注释里说明了 brand 行 label 用 display:none 的取舍。其余 dark-mode 字面值纪律全部保留——没碰 --text-on-accent / color:inherit

留给设计 review

@designer:folded brand 行现在永远是 toggle 全格 (48×48 + 18px font),跟 mock-1280/1100 里 14px 圆形高亮的视觉重量略不同。如果你希望在 brand 行 toggle 也走 "icon+halo" 那种感觉,再开 follow-up;这次先把 P0 不可用堵掉。

附三张 puppeteer 截图:[[copilot/fix-collapsed-1280.png]] / [[copilot/fix-collapsed-574.png]] / [[copilot/fix-expanded-574.png]]

… hit area

In collapsed mode, .brand-title and .brand-settings-btn used
visibility:hidden + opacity:0 to fade out, but visibility:hidden still
reserves layout space inside the .brand flex row. As a result, the
rail-collapse-btn's width:100% only resolved to ~9px (after the two
hidden flex siblings claimed their share), so the « / » toggle was
effectively invisible and unclickable — folded users had no way back
short of running localStorage.removeItem('openforge.sidebar.squad.collapsed')
in DevTools.

Fix: drop both label elements with display:none in collapsed mode so
they leave flex flow entirely; pin .rail-collapse-btn to width:48px
(min-width:48px) so it fills the rail width regardless of remaining
siblings, and bump font-size to 18px for legibility. The 150ms fade
is skipped for these two elements only — they live inside a 48px-wide
brand row, so the missing fade is imperceptible. squad-name /
section-label / new-squad-btn / status-text / unread-badge etc. keep
their fade transitions.

Verified with puppeteer at 1280×800 and 574×875:
- collapsed: toggle = 48×48 at (72,0); footer ⚙ = 40×40 at (76,756)
- expanded: toggle = 22×22 at (90,13); brand-title visible; brand-settings ⚙ = 28×20 at (294,10)
- click toggle in collapsed → expanded → click again → collapsed; ⌘\ also works
- localStorage flips correctly between 'collapsed' and 'expanded'
@github-actions

Copy link
Copy Markdown

🤖 bot-review (comment-only · phase 1)

Diff: 1 file changed, 13 insertions(+), 3 deletions(-) @ dd46714

Red-line checks:

  • ✅ A-7.5: no new 'forbidden' code in xiaof

Phase 1: this bot leaves comments only. Auto-approve will be enabled per-path after 1–2 weeks of clean runs. Promotion plan: judy PR #42 follow-up.

@SymbolStar SymbolStar merged commit 46f83e2 into main Jun 11, 2026
6 of 7 checks passed
SymbolStar added a commit that referenced this pull request Jun 11, 2026
…el (#73)

PR #72 fixed the toggle hit-box but designer's regression flagged a
320px gray ghost panel hugging the squad rail in collapsed mode at
1100/1280/1920. Root cause: source-order grid mis-mapping.

#home-view has 5 grid items: squad-rail, squad-gutter, thread-rail,
thread-gutter, thread-pane. PR #70 set
  body.squad-collapsed .col-gutter[data-gutter="squad"] { display:none; }
which removes the squad-gutter from grid layout, but the collapsed
template was still 5-track (48px / 0 / w-thread / 5px / 1fr). With only
4 items left, source order packed them into tracks 1\u20134:
  squad-rail \u2192 48px
  thread-rail \u2192 0px  (squashed)
  thread-gutter \u2192 320px (renders as a fat empty gutter \u2014 the "ghost")
  thread-pane \u2192 5px (squashed)
  track 5 (1fr) \u2192 empty
That left, mid-empty, mid-empty layout is exactly the screenshots.

Fix: collapsed template becomes a 4-track grid that matches the 4
visible items (48px / w-thread / 5px / 1fr). Also pin
#squad-rail { width:48px } in collapsed mode so any stale inline
--w-squad from earlier user drags can't bleed through.

Verified DOM mentally against designer's three crops; no JS change
needed.
SymbolStar added a commit that referenced this pull request Jun 11, 2026
…el (#74)

PR #72 fixed the toggle hit-box but designer's regression flagged a
320px gray ghost panel hugging the squad rail in collapsed mode at
1100/1280/1920. Root cause: source-order grid mis-mapping.

#home-view has 5 grid items: squad-rail, squad-gutter, thread-rail,
thread-gutter, thread-pane. PR #70 set
  body.squad-collapsed .col-gutter[data-gutter="squad"] { display:none; }
which removes the squad-gutter from grid layout, but the collapsed
template was still 5-track (48px / 0 / w-thread / 5px / 1fr). With only
4 items left, source order packed them into tracks 1\u20134:
  squad-rail \u2192 48px
  thread-rail \u2192 0px  (squashed)
  thread-gutter \u2192 320px (renders as a fat empty gutter \u2014 the "ghost")
  thread-pane \u2192 5px (squashed)
  track 5 (1fr) \u2192 empty
That left, mid-empty, mid-empty layout is exactly the screenshots.

Fix: collapsed template becomes a 4-track grid that matches the 4
visible items (48px / w-thread / 5px / 1fr). Also pin
#squad-rail { width:48px } in collapsed mode so any stale inline
--w-squad from earlier user drags can't bleed through.

Verified DOM mentally against designer's three crops; no JS change
needed.
SymbolStar added a commit that referenced this pull request Jun 11, 2026
…w-up) (#75)

PR #72 fixed the toggle hit area (48\u00d748 cell), but designer noted the
bare 18px \u00ab/\u00bb glyph inside it carried far less visual weight than the
28px circular squad emojis below \u2014 readable but visually 'absent'.

This adds a 28px circular halo centered in the cell via radial-gradient
(rgba(255,255,255,0.10) \u2192 0.20 on hover). The button itself stays a
48\u00d748 transparent hit target so the P0 click area is preserved; only
the painted disc shrinks to match the icon-rail rhythm. Focus ring
re-anchors to the visible disc edge (outline-offset:-8px, border-radius:50%).

No JS / DOM change; pure CSS.
SymbolStar added a commit that referenced this pull request Jun 11, 2026
…w-up) (#76)

PR #72 fixed the toggle hit area (48\u00d748 cell), but designer noted the
bare 18px \u00ab/\u00bb glyph inside it carried far less visual weight than the
28px circular squad emojis below \u2014 readable but visually 'absent'.

This adds a 28px circular halo centered in the cell via radial-gradient
(rgba(255,255,255,0.10) \u2192 0.20 on hover). The button itself stays a
48\u00d748 transparent hit target so the P0 click area is preserved; only
the painted disc shrinks to match the icon-rail rhythm. Focus ring
re-anchors to the visible disc edge (outline-offset:-8px, border-radius:50%).

No JS / DOM change; pure CSS.
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