From f8cd2bf749561ba6ac317652c2d9611055dca207 Mon Sep 17 00:00:00 2001 From: creatixchu Date: Wed, 29 Jul 2026 00:15:30 +0800 Subject: [PATCH] =?UTF-8?q?fix(host):=20review=20round=205=20=E2=80=94=20d?= =?UTF-8?q?raft-pending=20action=20gating,=20in-flow=20errors,=20IME=20gua?= =?UTF-8?q?rds?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Open and New folder disable while a path draft is uncommitted: targetPath still names the previous selection/listing, and committing against it while a different path shows in the header adopts the wrong directory. - The Miller columns keep their own row so a status/error line renders below them inside the card instead of competing as a third flex item the dialog clips off-screen. - Both text inputs (path editor, folder name) carry the IME composition guard the workspace-name inputs already had: a composing Enter confirms the candidate, never submits. --- .../src/client/DirectoryBrowser.module.css | 13 +++- .../src/client/DirectoryBrowser.tsx | 59 +++++++++++-------- .../tests/directory-browser.spec.tsx | 53 +++++++++++++++++ 3 files changed, 100 insertions(+), 25 deletions(-) diff --git a/packages/host/directory-picker-browse/src/client/DirectoryBrowser.module.css b/packages/host/directory-picker-browse/src/client/DirectoryBrowser.module.css index d9c72ec55b..47564236fe 100644 --- a/packages/host/directory-picker-browse/src/client/DirectoryBrowser.module.css +++ b/packages/host/directory-picker-browse/src/client/DirectoryBrowser.module.css @@ -41,6 +41,16 @@ /* Deep chains scroll inside the trail (the effect pins the tail into view) * so the edit zone to the right never leaves the bar. */ +/* The Miller columns keep their own row so a status/error line below never + * competes with the fixed column widths for horizontal space. */ +.millerRow { + display: flex; + align-items: stretch; + flex: 1 1 0; + min-height: 0; + gap: 20px; +} + .crumbTrail { display: flex; align-items: center; @@ -113,10 +123,9 @@ * the hairline divider centered between them; each column scrolls alone. */ .content { display: flex; - align-items: stretch; + flex-direction: column; flex: 1 1 0; min-height: 0; - gap: 20px; padding: 16px 24px 0; } diff --git a/packages/host/directory-picker-browse/src/client/DirectoryBrowser.tsx b/packages/host/directory-picker-browse/src/client/DirectoryBrowser.tsx index 5318ad0ea0..c809ea43b6 100644 --- a/packages/host/directory-picker-browse/src/client/DirectoryBrowser.tsx +++ b/packages/host/directory-picker-browse/src/client/DirectoryBrowser.tsx @@ -120,6 +120,9 @@ export function DirectoryBrowser({ open, listDirectory, createDirectory, onOpen, // Deep ancestry overflows the trail; keep its tail (the current directory // and the edit zone beside it) in view whenever the chain changes. const crumbTrailRef = useRef(null) + // IME confirmation (Enter selecting a candidate) must not submit either + // text input; the same guard the workspace-name inputs carry. + const composingRef = useRef(false) /** Replace the whole view with one freshly listed level (no selection). */ const navigate = useCallback((path?: string) => { @@ -242,6 +245,10 @@ export function DirectoryBrowser({ open, listDirectory, createDirectory, onOpen, // focus trap, so every parent control goes inert (Shift-Tab or AT must not // close, adopt, or retarget underneath the child). const parentInert = busy || folderDraft !== null + // An uncommitted path draft makes targetPath stale relative to the header: + // committing actions must not act on the previous selection/listing while + // a different path is displayed. + const draftPending = pathDraft !== null return ( { setPathDraft(event.target.value) }} + onCompositionStart={() => { composingRef.current = true }} + onCompositionEnd={() => { composingRef.current = false }} onKeyDown={(event) => { - if (event.key === 'Enter') { + if (event.key === 'Enter' && !composingRef.current) { event.preventDefault() const target = pathDraft.trim() if (target !== '') navigate(target) @@ -315,25 +324,27 @@ export function DirectoryBrowser({ open, listDirectory, createDirectory, onOpen,
- {parent !== null && ( - - )} - {twoPane && } - {twoPane && child !== null && ( - - )} +
+ {parent !== null && ( + + )} + {twoPane && } + {twoPane && child !== null && ( + + )} +
{loading &&
{t('browser.loading')}
} {error !== null &&
{error}
}
@@ -341,7 +352,7 @@ export function DirectoryBrowser({ open, listDirectory, createDirectory, onOpen,