mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
fix(web): use dedicated split breakpoint for compact tablets (#1141)
* fix(web): use dedicated split breakpoint for compact tablets Some compact Android tablets (e.g. OPPO Pad mini) report a landscape CSS viewport below Tailwind's `lg` (1024px) despite having enough physical screen space, so the sessions layout fell back to a single column. Add a dedicated `split` breakpoint at 920px and use it for the sessions split layout and the sidebar width/resize CSS, leaving the global `lg` breakpoint (and all other pages) untouched. * fix(web): cap sidebar width against viewport on compact split A persisted sidebar width (up to 600px from resizing on desktop) could shrink the detail pane to 316px at the new 920px split breakpoint, below the previous 1024px worst case of 420px. Cap the sidebar width at min(var(--sidebar-w), calc(100vw - 424px)) so the detail pane keeps at least 420px down to 920px, with no effect on desktop. * fix(web): seed sidebar drag from rendered width When the compact-split viewport cap renders the sidebar narrower than the persisted width, dragging the handle to shrink it had a dead zone until the stored width fell below the rendered width. Seed the drag from the sidebar's rendered width so it responds immediately; unchanged on desktop where rendered and stored widths match.
This commit is contained in:
@@ -27,9 +27,16 @@ export function useSidebarResize() {
|
|||||||
|
|
||||||
const onPointerDown = useCallback((e: React.PointerEvent) => {
|
const onPointerDown = useCallback((e: React.PointerEvent) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
// The sidebar (the handle's previous sibling) can render narrower than the
|
||||||
|
// stored width when the viewport cap in index.css kicks in on a compact
|
||||||
|
// split. Seed the drag from the actual rendered width so there's no dead
|
||||||
|
// zone before the sidebar responds. Falls back to the stored width when the
|
||||||
|
// element or its measured width is unavailable (e.g. non-DOM test env).
|
||||||
|
const sidebarEl = e.currentTarget.previousElementSibling as HTMLElement | null
|
||||||
|
const renderedWidth = sidebarEl?.getBoundingClientRect().width
|
||||||
activePointerIdRef.current = e.pointerId
|
activePointerIdRef.current = e.pointerId
|
||||||
startXRef.current = e.clientX
|
startXRef.current = e.clientX
|
||||||
startWidthRef.current = width
|
startWidthRef.current = renderedWidth || width
|
||||||
setIsDragging(true)
|
setIsDragging(true)
|
||||||
}, [width])
|
}, [width])
|
||||||
|
|
||||||
|
|||||||
+12
-4
@@ -352,8 +352,11 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Desktop sidebar: use custom width from CSS variable */
|
/* Desktop sidebar: use custom width from CSS variable.
|
||||||
@media (min-width: 1024px) {
|
Kept in sync with the Tailwind `split` breakpoint (see tailwind.config.ts)
|
||||||
|
so the sidebar width/resize applies as soon as the split view appears on
|
||||||
|
compact tablets. */
|
||||||
|
@media (min-width: 920px) {
|
||||||
.desktop-scrollbar-left {
|
.desktop-scrollbar-left {
|
||||||
direction: rtl;
|
direction: rtl;
|
||||||
}
|
}
|
||||||
@@ -362,9 +365,14 @@ body {
|
|||||||
direction: ltr;
|
direction: ltr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Apply resizable width to sidebar */
|
/* Apply resizable width to sidebar.
|
||||||
|
Cap it against the viewport so a wide persisted width (up to 600px, from
|
||||||
|
resizing on desktop) can't crush the detail pane on a compact split.
|
||||||
|
424px = 420px min detail pane + 4px resize handle, which preserves the
|
||||||
|
previous 1024px worst case (1024 - 600 - 4 = 420) down to 920px. The cap
|
||||||
|
is a no-op on desktop where 100vw - 424px exceeds the stored width. */
|
||||||
div[style*="--sidebar-w"] {
|
div[style*="--sidebar-w"] {
|
||||||
width: var(--sidebar-w) !important;
|
width: min(var(--sidebar-w), calc(100vw - 424px)) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -546,7 +546,7 @@ function SessionsPage() {
|
|||||||
<>
|
<>
|
||||||
<div className="flex h-full min-h-0">
|
<div className="flex h-full min-h-0">
|
||||||
<div
|
<div
|
||||||
className={`${isSessionsIndex ? 'flex' : 'hidden lg:flex'} w-full shrink-0 flex-col bg-[var(--app-bg)]`}
|
className={`${isSessionsIndex ? 'flex' : 'hidden split:flex'} w-full shrink-0 flex-col bg-[var(--app-bg)]`}
|
||||||
style={{ '--sidebar-w': `${sidebar.width}px` } as React.CSSProperties}
|
style={{ '--sidebar-w': `${sidebar.width}px` } as React.CSSProperties}
|
||||||
>
|
>
|
||||||
<div className="bg-[var(--app-bg)] pt-[env(safe-area-inset-top)]">
|
<div className="bg-[var(--app-bg)] pt-[env(safe-area-inset-top)]">
|
||||||
@@ -633,12 +633,12 @@ function SessionsPage() {
|
|||||||
|
|
||||||
{/* Resize handle - desktop only */}
|
{/* Resize handle - desktop only */}
|
||||||
<div
|
<div
|
||||||
className="sidebar-resize-handle hidden lg:block shrink-0"
|
className="sidebar-resize-handle hidden split:block shrink-0"
|
||||||
data-dragging={sidebar.isDragging || undefined}
|
data-dragging={sidebar.isDragging || undefined}
|
||||||
onPointerDown={sidebar.onPointerDown}
|
onPointerDown={sidebar.onPointerDown}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className={`${isSessionsIndex ? 'hidden lg:flex' : 'flex'} min-w-0 flex-1 flex-col bg-[var(--app-bg)]`}>
|
<div className={`${isSessionsIndex ? 'hidden split:flex' : 'flex'} min-w-0 flex-1 flex-col bg-[var(--app-bg)]`}>
|
||||||
<div className="flex-1 min-h-0">
|
<div className="flex-1 min-h-0">
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,6 +4,15 @@ export default {
|
|||||||
content: ['./index.html', './src/**/*.{ts,tsx}'],
|
content: ['./index.html', './src/**/*.{ts,tsx}'],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
|
screens: {
|
||||||
|
// Dedicated split breakpoint for the sessions layout. Some compact
|
||||||
|
// Android tablets (e.g. OPPO Pad mini) report a landscape CSS
|
||||||
|
// viewport below Tailwind's `lg` (1024px) despite having enough
|
||||||
|
// physical space, so they fall back to single-column. 920px lets
|
||||||
|
// those tablets show the split view while staying clear of phone
|
||||||
|
// landscape widths.
|
||||||
|
split: '920px'
|
||||||
|
},
|
||||||
maxWidth: {
|
maxWidth: {
|
||||||
content: 'var(--content-max-w, 960px)'
|
content: 'var(--content-max-w, 960px)'
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user