integrate train/css: panel z-index + overflow clip + mobile sidebar
This commit is contained in:
@@ -1030,18 +1030,20 @@ export function Sidebar(props: { ctx: Context; store: SidebarStore }) {
|
||||
}, [ctx, sessionId, cwd])
|
||||
|
||||
if (state === undefined || sessionId === undefined) {
|
||||
// Keep the unavailable controls focusable: touch users have no hover, so
|
||||
// focus is the only way the existing Tooltip can explain what is missing.
|
||||
return (
|
||||
<div data-dsh-panel-host {...osFileDragShield}>
|
||||
<div className={css.toggleCluster} data-dsh-toggle-cluster>
|
||||
{!narrow && (
|
||||
<Tooltip label={t('noSession')} side="bottom" delayMs={500}>
|
||||
<button type="button" className={css.toggleButton} disabled aria-label={t('noSession')}>
|
||||
<button type="button" className={css.toggleButton} aria-disabled="true" aria-label={t('noSession')}>
|
||||
<IconPanelBottomOutline16 />
|
||||
</button>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip label={t('noSession')} side="bottom" delayMs={500}>
|
||||
<button type="button" className={css.toggleButton} disabled aria-label={t('noSession')}>
|
||||
<button type="button" className={css.toggleButton} aria-disabled="true" aria-label={t('noSession')}>
|
||||
<IconPanelRightOutline16 />
|
||||
</button>
|
||||
</Tooltip>
|
||||
|
||||
@@ -24,16 +24,28 @@
|
||||
containing block for every panel element. Panels are ABSOLUTE within it
|
||||
(not fixed), so a desktop shell's intermediate wrapper transform can
|
||||
never hijack their containing block — the host itself is the only fixed
|
||||
element, appended directly to document.body. The layer sits at z-index 40
|
||||
(below the app's overlay stack at 100+); each panel re-enables pointer
|
||||
element, appended directly to document.body. The layer sits at z-index 25:
|
||||
above the app's shell overlay (AppFrame overlayLayer, 20) and in-flow
|
||||
content, below DSH's ui-cordis dynamic-plugin panel (fixed, 30 — the
|
||||
inventory/surfacing surface must never be hidden behind the workbench),
|
||||
and below the app's overlay stack at 100+; each panel re-enables pointer
|
||||
events on itself. Degraded mode ([data-dsh-panel-host-degraded]) covers
|
||||
the rare shell that transforms <html>/<body> itself: the host becomes
|
||||
absolute and the mount self-check pins it to the viewport every frame. */
|
||||
:global([data-dsh-panel-host]) {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 40;
|
||||
z-index: 25;
|
||||
pointer-events: none;
|
||||
/* Clip at the viewport edge: collapsed panels slide off-screen with
|
||||
`transform: translate(102%)`, and a transformed element still
|
||||
contributes to its ancestors' scrollable overflow — without this the
|
||||
hidden panels extended the document's scrollable area, making the whole
|
||||
page draggable left-right and up-down while any panel was collapsed.
|
||||
The host is exactly viewport-sized (inset: 0), so the clip is invisible
|
||||
until a panel slides in from the edge; internal scroll containers and
|
||||
the app's fixed overlay stack are unaffected. */
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:global([data-dsh-panel-host][data-dsh-panel-host-degraded]) {
|
||||
@@ -46,11 +58,13 @@
|
||||
controls side by side (bottom panel's glyph LEFT of the right panel's).
|
||||
Always pinned to the viewport corner — inside the right panel's top-right
|
||||
while it is open, sitting flush in the 34px tab strip (28px buttons at
|
||||
top: 3) whose right end it really squeezes. z-index 45: above the panels
|
||||
(40) but below the app's overlay stack (menus/tooltips/modals sit at
|
||||
100+), so a cordis approval popup is never hidden behind the workbench
|
||||
(issue #52). Absolute within the panel host (the host's inset: 0 makes
|
||||
viewport coordinates identical). */
|
||||
top: 3) whose right end it really squeezes. Host-internal z-index 45
|
||||
(above the panels' 40); the host's global layer is z-index 25, so the
|
||||
whole cluster stays below DSH's ui-cordis dynamic-plugin panel (30) and
|
||||
the app's overlay stack (menus/tooltips/modals sit at 100+), so a cordis
|
||||
approval popup is never hidden behind the workbench (issue #52). Absolute
|
||||
within the panel host (the host's inset: 0 makes viewport coordinates
|
||||
identical). */
|
||||
.toggleCluster {
|
||||
position: absolute;
|
||||
/* env() resolves to 0 on devices without a top inset (desktops). */
|
||||
@@ -91,27 +105,33 @@
|
||||
color var(--ds-transition-duration-slow) var(--ds-ease-in-out);
|
||||
}
|
||||
|
||||
.toggleButton:hover:not(:disabled) {
|
||||
.toggleButton:hover:not(:disabled):not([aria-disabled='true']) {
|
||||
background: var(--dsw-alias-interactive-bg-hover);
|
||||
color: var(--dsw-alias-label-primary);
|
||||
}
|
||||
|
||||
.toggleButton:disabled {
|
||||
.toggleButton:disabled,
|
||||
.toggleButton[aria-disabled='true'] {
|
||||
opacity: 0.4;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.panel {
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
/* Full height: the bottom panel squeezes only the center column, so the
|
||||
right panel never gives up any vertical position. */
|
||||
bottom: 0;
|
||||
/* z-index 40: above the app's in-flow content, below the app's overlay
|
||||
stack (100+), so menus/tooltips/modals always win over the panels
|
||||
(issue #52). The toggle cluster (45) sits above it; the corner handle
|
||||
is a child and stacks within the panel. */
|
||||
/* Host-internal z-index 40 (sibling of the bottom panel's 40; the two
|
||||
never overlap — the bottom panel's right edge is this panel's left
|
||||
edge — and both sit below the toggle cluster's 45). The absolute
|
||||
global layer comes from the host ([data-dsh-panel-host], 25) — the
|
||||
whole stack stays above the app's in-flow content and below DSH's
|
||||
ui-cordis dynamic-plugin panel (30) and the app's overlay stack (100+),
|
||||
so menus/tooltips/modals always win over the panels (issue #52). The
|
||||
corner handle is a child and stacks within the panel. */
|
||||
z-index: 40;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -178,9 +198,11 @@
|
||||
column only (the Sidebar shell writes left/right inline: from the app's
|
||||
own left sidebar to the right panel's left edge) — the sidebars never
|
||||
give up any position. Same surface as the right panel, with a top
|
||||
hairline instead of the left one. z-index 40 mirrors the right panel
|
||||
(issue #52: below the app's overlay stack so popups win over the
|
||||
workbench). */
|
||||
hairline instead of the left one. Host-internal z-index 40 mirrors the
|
||||
right panel; the absolute global layer comes from the host (25), below
|
||||
DSH's ui-cordis dynamic-plugin panel (30) so the cordis inventory
|
||||
surface floats above the workbench, and below the app's overlay stack
|
||||
(100+) so popups win over the workbench (issue #52). */
|
||||
.bottomPanel {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
|
||||
Reference in New Issue
Block a user