fix(host): review round 12 nits — two-stage create parking documented; CSS DOM order; busy-window caveat
This commit is contained in:
@@ -52,24 +52,6 @@
|
||||
|
||||
/* 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. */
|
||||
/* A narrow viewport shrinks the dialog below two fixed panes; the row
|
||||
* scrolls horizontally (the effect pins the child pane into view) so
|
||||
* descent never hides behind the Modal's clipping. */
|
||||
.millerRow {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
flex: 1 1 0;
|
||||
min-height: 0;
|
||||
/* 12px of row gap on each side of the divider; the left side reads wider
|
||||
* by the column's trailing 8px scrollbar clearance, which is deliberate —
|
||||
* the thumb needs that room, the right pane's rows do not. */
|
||||
gap: 12px;
|
||||
overflow-x: auto;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.crumbTrail {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -151,6 +133,24 @@
|
||||
padding: 16px 16px 16px 24px;
|
||||
}
|
||||
|
||||
/* The Miller columns keep their own row so a status/error line below never
|
||||
* competes with the fixed column widths for horizontal space. */
|
||||
/* A narrow viewport shrinks the dialog below two fixed panes; the row
|
||||
* scrolls horizontally (the effect pins the child pane into view) so
|
||||
* descent never hides behind the Modal's clipping. */
|
||||
.millerRow {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
flex: 1 1 0;
|
||||
min-height: 0;
|
||||
/* 12px of row gap on each side of the divider; the left side reads wider
|
||||
* by the column's trailing 8px scrollbar clearance, which is deliberate —
|
||||
* the thumb needs that room, the right pane's rows do not. */
|
||||
gap: 12px;
|
||||
overflow-x: auto;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
/* Columns split the row evenly around the divider (a solo column takes the
|
||||
* whole row); 256px is the floor below which the row scrolls (scrollbar
|
||||
* hidden, the effect pins the child pane into view) instead of squeezing
|
||||
|
||||
@@ -262,11 +262,12 @@ export function DirectoryBrowser({ open, listDirectory, createDirectory, onOpen,
|
||||
// Focus parking (consumed by the refocus effect below): a pick — and a
|
||||
// parent-leg upgrade that displaces focused rows — parks on the
|
||||
// selection's row; every other displacing exit (Enter, Escape, a landing
|
||||
// whose new level dropped the focused row, a failed pick or relist, and
|
||||
// the nested create dialog closing) parks on the crumb edit zone, each
|
||||
// only when focus actually fell to body. Pointer-out cancels never set
|
||||
// (or clear) these — yanking focus back from wherever the user clicked
|
||||
// would be worse than the fall.
|
||||
// whose new level dropped the focused row, a failed pick, and every
|
||||
// create-dialog exit, whose close-time parking is also what a failed
|
||||
// relist inherits) parks on the crumb edit zone, each only when focus
|
||||
// actually fell to body. Pointer-out cancels never set (or clear) these
|
||||
// — yanking focus back from wherever the user clicked would be worse
|
||||
// than the fall.
|
||||
const refocusPick = useRef(false)
|
||||
const refocusEditZone = useRef(false)
|
||||
const editZoneRef = useRef<HTMLButtonElement | null>(null)
|
||||
@@ -362,8 +363,11 @@ export function DirectoryBrowser({ open, listDirectory, createDirectory, onOpen,
|
||||
/**
|
||||
* Close the nested create dialog. Its unmount drops focus to body (the
|
||||
* Modal has no focus trap), so every exit — Escape, mask, Cancel, and a
|
||||
* successful create — arms the body-guarded edit-zone parking; a create
|
||||
* landing's later select() re-parks on the created row instead.
|
||||
* successful create — arms the body-guarded edit-zone parking. A
|
||||
* successful create therefore parks in TWO stages: the edit zone on this
|
||||
* close, then the relist's select() re-parks on the created row one RTT
|
||||
* later — deliberately re-parking even focus the user moved during the
|
||||
* relist window, and doubling as the parking a failed relist inherits.
|
||||
*/
|
||||
const closeCreateDialog = useCallback(() => {
|
||||
setFolderDraft(null)
|
||||
@@ -527,8 +531,11 @@ export function DirectoryBrowser({ open, listDirectory, createDirectory, onOpen,
|
||||
// has no focus trap): a pick lands on the selection's row — aria-current
|
||||
// in the freshly rendered left pane, which survives even a right-pane
|
||||
// advance or a create landing replacing the picked button's column —
|
||||
// while Enter and an input-focused Escape land on the crumb edit zone
|
||||
// that replaces the input.
|
||||
// while the edit-zone exits enumerated at the flag declarations fall
|
||||
// back to the crumb edit zone. The one window outside this invariant is
|
||||
// the owner's adopt: busy inerts every control in the card (browsers
|
||||
// blur disabled elements to body) and no parking applies — the owner
|
||||
// closes the dialog either way.
|
||||
useEffect(() => {
|
||||
if (pathDraft !== null) return
|
||||
if (refocusPick.current) {
|
||||
|
||||
Reference in New Issue
Block a user