mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-09 08:59:40 +02:00
fix(tiles): no tile onto an empty slot, header focus on click, arrow chords skip text fields
The owner's answers on moving tiles: - "dont move the tile": an empty slot no longer takes a tile. A slot is always the last cell, so a move there shifted every tile after it. Each drop target now says what it accepts (_acceptTabDrops' `accepts`): a tile takes any session but its own, an empty slot only a session not tiled yet. A refused drag is still held (dropEffect none, no highlight), and dropSessionOnSlot refuses a tiled session too, its tab included. A session not tiled yet still joins on a slot. - A cancelled drag changes nothing, focus included (best practice): the header focuses its tile on click, never on press, so a drag that ends with Escape or outside leaves focus and the idle alert alone. The body keeps press-to-focus, so focus still moves before a press reaches xterm. The rename input stops its own clicks. - A tiled tab dropped on the zoomed tile stays refused (confirmed). - The Alt+Shift+Arrow focus chords skip a text field too (best practice), as the move chords already did: shifted arrows select there. Toggle and zoom are not text-editing keys and are unchanged. Docs: the wiki, the spec's as-built bullet (with the owner's answers), the invariants and CLAUDE.md say so. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -116,6 +116,28 @@ describe('when a chord applies', () => {
|
||||
expect(app.tileShortcutFor(chord(RIGHT))).toBe('focus-tile-right');
|
||||
});
|
||||
|
||||
it('the focus chords leave a text field its keys (shifted arrows select there); a terminal still gets them', () => {
|
||||
const app = makeGridApp(IDS);
|
||||
app.openTileGrid(IDS);
|
||||
for (const tagName of ['INPUT', 'TEXTAREA']) {
|
||||
const target = { tagName, closest: () => null, classList: { contains: () => false } };
|
||||
expect(app.tileShortcutFor(chord({ ...RIGHT, target }))).toBeNull();
|
||||
}
|
||||
expect(
|
||||
app.tileShortcutFor(chord({ ...RIGHT, target: { isContentEditable: true, closest: () => null } }))
|
||||
).toBeNull();
|
||||
// xterm's own input is a textarea too, and the chord is the grid's there.
|
||||
const xterm = {
|
||||
tagName: 'TEXTAREA',
|
||||
closest: () => null,
|
||||
classList: { contains: (c: string) => c === 'xterm-helper-textarea' },
|
||||
};
|
||||
expect(app.tileShortcutFor(chord({ ...RIGHT, target: xterm }))).toBe('focus-tile-right');
|
||||
// Not an arrow chord: the toggle and zoom still apply from a field.
|
||||
const input = { tagName: 'INPUT', closest: () => null, classList: { contains: () => false } };
|
||||
expect(app.tileShortcutFor(chord({ ...TOGGLE, target: input }))).toBe('toggle-tile-grid');
|
||||
});
|
||||
|
||||
it('plain typing and unrelated chords never match', () => {
|
||||
const app = makeGridApp(IDS);
|
||||
app.openTileGrid(IDS);
|
||||
|
||||
Reference in New Issue
Block a user