fix: remove console composer click shell

This commit is contained in:
Keisuke Hirata 2026-07-22 16:55:28 +09:00
parent 1ff02151b8
commit a8c27f5752
No known key found for this signature in database
4 changed files with 55 additions and 20 deletions

View File

@ -2,7 +2,7 @@
title: 'Backend runtime経由の操作をprotocol transportへ統一しTUI同等にする' title: 'Backend runtime経由の操作をprotocol transportへ統一しTUI同等にする'
state: 'planning' state: 'planning'
created_at: '2026-07-21T09:20:07Z' created_at: '2026-07-21T09:20:07Z'
updated_at: '2026-07-22T07:23:32Z' updated_at: '2026-07-22T07:55:21Z'
assignee: null assignee: null
readiness: 'draft' readiness: 'draft'
--- ---

View File

@ -463,3 +463,42 @@ Verification:
- `git diff --check` - `git diff --check`
--- ---
<!-- event: comment author: assistant at: 2026-07-22T07:53:01Z -->
## Comment
Requested Web Console composer a11y/focus refactor before implementation:
- Requirement: clicking anywhere in the composer input surface except the button should focus the textarea.
- Preferred structure: do not add `role="button"` to a layout `<div>` and do not wrap the send button in a `<label>`.
- Instead, make the textarea itself occupy the input surface and use padding/overlay layout for the footer and send button.
- The send button remains structurally outside/above the textarea surface and handles submit normally.
- Expected result: remove the clickable `<div>` a11y warning while preserving the composer click-to-focus behavior.
---
<!-- event: implementation_report author: assistant at: 2026-07-22T07:55:21Z -->
## Implementation report
Implementation report for Web Console composer focus/a11y refactor:
- Removed the `onclick={handleComposerShellClick}` layout-div focus handler and deleted `handleComposerShellClick`.
- Kept the composer shell as non-interactive layout.
- Made the textarea itself occupy the input surface:
- larger min-height
- right/bottom padding reserved for the overlaid footer and send button
- `cursor: text`
- Changed the footer to an absolute overlay with `pointer-events: none`, so clicks on non-button footer/composer area pass through to the textarea.
- Kept the send button as a normal submit button with `pointer-events: auto`.
- Updated the Web UI fixture test to assert the shell no longer has the click handler and the overlay pointer-event layout is present.
Verification:
- `cd web/workspace && deno test --allow-read=src --allow-env=VSCODE_TEXTMATE_DEBUG src/lib/workspace/console/worker-console.ui.test.ts`
- `cd web/workspace && deno task check`
- `git diff --check`
Result: `svelte-check found 0 errors and 0 warnings`.
---

View File

@ -152,14 +152,16 @@ Deno.test("Worker Console composer fits to content without manual resize", async
); );
assert( assert(
consolePage.includes("use:fitTextarea={{ value: draft, maxRows: 10 }}") && consolePage.includes("use:fitTextarea={{ value: draft, maxRows: 10 }}") &&
consolePage.includes("class=\"composer-input-shell\" onclick={handleComposerShellClick}") && consolePage.includes("<div class=\"composer-input-shell\">") &&
!consolePage.includes("handleComposerShellClick") &&
consolePage.includes("bind:this={composerTextareaElement}") && consolePage.includes("bind:this={composerTextareaElement}") &&
consolePage.includes("composerTextareaElement?.focus()") &&
consolePage.includes('event.key === "PageUp" || event.key === "PageDown"') && consolePage.includes('event.key === "PageUp" || event.key === "PageDown"') &&
consolePage.includes("scrollConsoleByPage") && consolePage.includes("scrollConsoleByPage") &&
consolePage.includes("class=\"composer-input-footer\"") && consolePage.includes("class=\"composer-input-footer\"") &&
consolePage.includes("pointer-events: none") &&
consolePage.includes("class=\"composer-footer-slot\"") && consolePage.includes("class=\"composer-footer-slot\"") &&
consolePage.includes("class=\"composer-send-button\"") && consolePage.includes("class=\"composer-send-button\"") &&
consolePage.includes("pointer-events: auto") &&
consolePage.includes("class=\"composer-send-icon\"") && consolePage.includes("class=\"composer-send-icon\"") &&
consolePage.includes('d="M8 6L12 2L16 6"') && consolePage.includes('d="M8 6L12 2L16 6"') &&
consolePage.includes(".console-composer textarea") && consolePage.includes(".console-composer textarea") &&

View File

@ -376,17 +376,6 @@
window.requestAnimationFrame(updateConsoleScrollMetrics); window.requestAnimationFrame(updateConsoleScrollMetrics);
} }
function handleComposerShellClick(event: MouseEvent) {
const target = event.target;
if (
target instanceof Element &&
target.closest("button, textarea, a")
) {
return;
}
composerTextareaElement?.focus();
}
function sendControl(method: ProtocolMethod, label: string) { function sendControl(method: ProtocolMethod, label: string) {
try { try {
sendProtocolMethod(method); sendProtocolMethod(method);
@ -1317,7 +1306,7 @@
{/if} {/if}
<form class="console-composer card" onsubmit={sendMessage}> <form class="console-composer card" onsubmit={sendMessage}>
<div class="composer-input-shell" onclick={handleComposerShellClick}> <div class="composer-input-shell">
<textarea <textarea
id="worker-console-message" id="worker-console-message"
aria-label="Console input" aria-label="Console input"
@ -1603,8 +1592,7 @@
} }
.composer-input-shell { .composer-input-shell {
display: grid; position: relative;
gap: var(--space-2);
border: 1px solid var(--line); border: 1px solid var(--line);
border-radius: 18px; border-radius: 18px;
background: var(--bg-raised); background: var(--bg-raised);
@ -1618,12 +1606,16 @@
} }
.composer-input-footer { .composer-input-footer {
position: absolute;
right: 0.7rem;
bottom: 0.7rem;
left: 1rem;
display: grid; display: grid;
grid-template-columns: minmax(0, 1fr) auto; grid-template-columns: minmax(0, 1fr) auto;
gap: var(--space-2); gap: var(--space-2);
align-items: end; align-items: end;
min-height: 2.35rem; min-height: 2.35rem;
padding-left: 0.65rem; pointer-events: none;
} }
.composer-footer-slot { .composer-footer-slot {
@ -1633,17 +1625,18 @@
.console-composer textarea { .console-composer textarea {
box-sizing: border-box; box-sizing: border-box;
width: 100%; width: 100%;
min-height: 0; min-height: 5.35rem;
resize: none; resize: none;
overflow-y: hidden; overflow-y: hidden;
border: 0; border: 0;
border-radius: 14px; border-radius: 14px;
background: transparent; background: transparent;
padding: 0.55rem 0.65rem; padding: 0.55rem 3.4rem 3rem 0.65rem;
font: inherit; font: inherit;
line-height: 1.45; line-height: 1.45;
color: var(--text-strong); color: var(--text-strong);
outline: none; outline: none;
cursor: text;
} }
.console-composer textarea:disabled { .console-composer textarea:disabled {
@ -1661,6 +1654,7 @@
color: var(--bg); color: var(--bg);
cursor: pointer; cursor: pointer;
padding: 0; padding: 0;
pointer-events: auto;
} }
.composer-send-button:disabled { .composer-send-button:disabled {