spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic · github.com/anthropics

diff: the docked pane starts at its header, under the engine's own head row (#99206)Browse files
Docked, the pane no longer pads a blank row of its own above its header: the engine keeps a docked pane's first row for its close mark, and that row is the blank one.
Alice T'Poteat authored 16 days ago · GitHub committed 16 days ago parent fbe20e0 · commit 765f236fe1bf
13 changed files+90 -32compared with fbe20e0
Mmods/diff/hooks/limits/sizes/pane/index.ts
Dmods/diff/hooks/limits/sizes/pane/pane-top-pad-rows.ts
Mmods/diff/hooks/views/body/plan/body-layout-of.ts
Mmods/diff/hooks/views/inset-of/inset-of.ts
Mmods/diff/hooks/views/pane-view.tsx
Mmods/diff/tests/fixtures/index.ts
Mmods/diff/tests/fixtures/pane-view/body-rows.ts
Amods/diff/tests/fixtures/pane-view/engine-head-rows.ts
Mmods/diff/tests/fixtures/pane-view/index.ts
Amods/diff/tests/fixtures/wheel-over-list-margin.ts
Amods/diff/tests/fixtures/wheel-over-list-top.ts
Mmods/diff/tests/fixtures/wheel-over-list.ts
Mmods/diff/tests/views/pane-view.test.ts
@@ -1,6 +1,5 @@
11 export * from './gutter-chrome.js'
22 export * from './max-summary-rows.js'
3-export * from './pane-top-pad-rows.js'
43 export * from './pre-session-body-cap.js'
54 export * from './scroll-margin-rows.js'
65 export * from './wheel-rows.js'
Dmods/diff/hooks/limits/sizes/pane/pane-top-pad-rows.ts+0 -5
@@ -1,5 +1,0 @@
1-/**
2- * The blank row the docked pane keeps above its header, as the built-in
3- * sidebar's header does (its `paddingY`).
4- */
5-export const PANE_TOP_PAD_ROWS = 1
@@ -1,4 +1,3 @@
1-import Limits from '../../../limits'
21 import type PaneState from '../../../pane-state'
32 import type { BodyLayout, DockPlan } from '../types'
43 import Segments from './segments'
@@ -39,10 +38,7 @@
3938
4039 const tops = new Map<string, number>()
4140
42- const visibleRows = Math.max(
43- 0,
44- model.place.rows - Limits.PANE_TOP_PAD_ROWS - headRows - listRows,
45- )
41+ const visibleRows = Math.max(0, model.place.rows - headRows - listRows)
4642
4743 let extent = 0
4844
@@ -54,7 +50,7 @@
5450 extent += Segments.segmentRowsOf(segment)
5551 }
5652
57- const listTop = Limits.PANE_TOP_PAD_ROWS + headRows + 1
53+ const listTop = headRows + 1
5854
5955 return {
6056 segments,
@@ -3,13 +3,15 @@
33
44 /**
55 * A drawing's kit inside the docked pane's padding: the built-in's blank
6- * last column and its blank row above the header taken off.
6+ * last column taken off.
77 *
8+ * No row comes off: the blank row above the header is the engine's own,
9+ * the one it keeps over a docked pane's body for its close mark.
10+ *
811 * @param kit the drawing's kit at the pane's full size
912 * @returns the kit its body draws with
1013 */
1114 export const insetOf = (kit: Kit): Kit => ({
1215 ...kit,
1316 columns: Math.max(1, kit.columns - Limits.PANE_RIGHT_PAD_COLUMNS),
14- rows: Math.max(0, kit.rows - Limits.PANE_TOP_PAD_ROWS),
1517 })
@@ -40,11 +40,7 @@
4040 seat.terminalColumns < Limits.OPEN_MIN_COLUMNS
4141
4242 return isDocked ? (
43- <Box
44- flexDirection="column"
45- paddingTop={Limits.PANE_TOP_PAD_ROWS}
46- paddingRight={Limits.PANE_RIGHT_PAD_COLUMNS}
47- >
43+ <Box flexDirection="column" paddingRight={Limits.PANE_RIGHT_PAD_COLUMNS}>
4844 {sidebarPane(insetOf(kit), model)}
4945 </Box>
5046 ) : isNarrow ? (
@@ -60,6 +60,8 @@
6060 export * from './usage-at.js'
6161 export * from './vs-main.js'
6262 export * from './wheel-over-list.js'
63+export * from './wheel-over-list-margin.js'
64+export * from './wheel-over-list-top.js'
6365 export * from './wheel-tick.js'
6466 export * from './with-lockfile.js'
6567 export * from './worktree'
@@ -1,4 +1,5 @@
11 /**
2- * The pane's body rows in the ordinary cases: docked in a 40-row terminal.
2+ * The pane's body rows in the ordinary cases: docked in a 40-row terminal,
3+ * under the row the engine keeps for its close mark.
34 */
4-export const BODY_ROWS = 35
5+export const BODY_ROWS = 34
@@ -1,0 +1,5 @@
1+/**
2+ * The rows the engine keeps over a docked pane's body: one, blank but for
3+ * its close mark.
4+ */
5+export const ENGINE_HEAD_ROWS = 1
@@ -9,6 +9,7 @@
99 export * from './docked-pane.js'
1010 export * from './docks-pane.js'
1111 export * from './draws-pane.js'
12+export * from './engine-head-rows.js'
1213 export * from './long-line-chars.js'
1314 export * from './long-path-segments.js'
1415 export * from './narrow-seat.js'
@@ -1,0 +1,12 @@
1+import type { UiScrollInput } from 'claude-code'
2+
3+import { WHEEL_TICK } from './wheel-tick.js'
4+
5+/**
6+ * The same wheel tick with the pointer over the blank row between the
7+ * docked header and its list.
8+ */
9+export const WHEEL_OVER_LIST_MARGIN: UiScrollInput = {
10+ ...WHEEL_TICK,
11+ pointer: { column: 10, row: 1 },
12+}
@@ -1,0 +1,12 @@
1+import type { UiScrollInput } from 'claude-code'
2+
3+import { WHEEL_TICK } from './wheel-tick.js'
4+
5+/**
6+ * The same wheel tick with the pointer over the docked list's first row
7+ * (header, the list's margin, then the rows).
8+ */
9+export const WHEEL_OVER_LIST_TOP: UiScrollInput = {
10+ ...WHEEL_TICK,
11+ pointer: { column: 10, row: 2 },
12+}
@@ -4,9 +4,9 @@
44
55 /**
66 * The same wheel tick with the pointer over the docked list's third row
7- * (top pad, header, the list's margin, then the rows).
7+ * (header, the list's margin, then the rows).
88 */
99 export const WHEEL_OVER_LIST: UiScrollInput = {
1010 ...WHEEL_TICK,
11- pointer: { column: 10, row: 5 },
11+ pointer: { column: 10, row: 4 },
1212 }
@@ -365,7 +365,7 @@
365365 expect(Fixtures.jsonOf(reversed)).not.toContain('‮')
366366 })
367367
368- test("docked: the built-in's blank top row, last column", async ($, on) => {
368+ test("docked: no top pad, the built-in's last column", async ($, on) => {
369369 const tree = await Fixtures.dockedPane(
370370 $,
371371 on,
@@ -381,16 +381,55 @@
381381
382382 expect(tree).toMatchObject({
383383 type: 'Box',
384- props: {
385- paddingTop: Limits.PANE_TOP_PAD_ROWS,
386- paddingRight: Limits.PANE_RIGHT_PAD_COLUMNS,
387- },
384+ props: { paddingRight: Limits.PANE_RIGHT_PAD_COLUMNS },
388385 })
389386
387+ expect(Fixtures.jsonOf(tree)).not.toContain('"paddingTop"')
390388 expect(Fixtures.stringsOf(tree)).toContain(rule)
391389 expect(Fixtures.stringsOf(tree)).not.toContain(`${rule}─`)
392390 })
393391
392+ test('docked: the window takes every row under the list', () => {
393+ const files = [Fixtures.rowOf('src/a.ts'), Fixtures.rowOf('b.ts')]
394+ const headerRows = 1
395+ const listMarginRows = 1
396+
397+ const model = modelOf({
398+ data: dataOf(files),
399+ place: { ...Fixtures.WHOLE_PLACE, rows: Fixtures.BODY_ROWS },
400+ })
401+
402+ const listTop = headerRows + listMarginRows
403+ const listEnd = listTop + files.length
404+
405+ expect(Views.bodyLayoutOf(model, Views.dockPlanOf(model))).toMatchObject({
406+ listTop,
407+ listEnd,
408+ visibleRows: Fixtures.BODY_ROWS - listEnd - listMarginRows,
409+ })
410+ })
411+
412+ test('docked: the list takes the wheel from its first row', () => {
413+ const model = modelOf({
414+ data: dataOf(
415+ Array.from({ length: Limits.MAX_SUMMARY_ROWS + 1 }, (_, index) =>
416+ Fixtures.rowOf(`file${index}.ts`),
417+ ),
418+ ),
419+ place: { ...Fixtures.WHOLE_PLACE, rows: Fixtures.BODY_ROWS },
420+ })
421+
422+ expect(
423+ Views.isWheelOverList(model, Fixtures.WHEEL_OVER_LIST_MARGIN),
424+ 'the blank row under the header',
425+ ).toBe(false)
426+
427+ expect(
428+ Views.isWheelOverList(model, Fixtures.WHEEL_OVER_LIST_TOP),
429+ "the list's first row",
430+ ).toBe(true)
431+ })
432+
394433 test("docked rows follow the built-in's, its hunks after", async ($, on) => {
395434 expect(
396435 Fixtures.rowShapesOf(
@@ -428,11 +467,9 @@
428467
429468 const [header, pad, middle, foot, ...more] = Fixtures.childrenOf(body)
430469 const [spacer, headline, ...under] = Fixtures.childrenOf(middle)
431- const aboveMiddle = Limits.PANE_TOP_PAD_ROWS + 2
470+ const aboveMiddle = Fixtures.ENGINE_HEAD_ROWS + 2
432471
433- expect(body).toMatchObject({
434- props: { height: Fixtures.BODY_ROWS - Limits.PANE_TOP_PAD_ROWS },
435- })
472+ expect(body).toMatchObject({ props: { height: Fixtures.BODY_ROWS } })
436473
437474 expect(Fixtures.stringsOf(header)).toEqual([])
438475 expect(Fixtures.jsonOf(header)).not.toContain('✕')