diff options
Diffstat (limited to 'public/bluebey-studio/src/main.js')
| -rw-r--r-- | public/bluebey-studio/src/main.js | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/public/bluebey-studio/src/main.js b/public/bluebey-studio/src/main.js index e282e9d..49494a4 100644 --- a/public/bluebey-studio/src/main.js +++ b/public/bluebey-studio/src/main.js @@ -1356,6 +1356,56 @@ async function init() { const panel = buildPanel(app, document.getElementById('panel')); app.panel = panel; + // On a phone the panel is a bottom sheet. Its grab handle drags the sheet's top + // edge up and down, so the menu can be pulled out of the way of the character. + const panelEl = document.getElementById('panel'); + const panelGrip = document.createElement('div'); + panelGrip.className = 'panel-grip'; + panelGrip.setAttribute('aria-hidden', 'true'); + panelEl.prepend(panelGrip); + installSheetDrag(panelEl, panelGrip); + + /** Drag on the phone sheet's handle; a no-op anywhere else. */ + function installSheetDrag(sheet, grip) { + const phone = window.matchMedia('(max-width: 768px), (max-height: 500px) and (pointer: coarse)'); + let drag = null; + const minHeight = () => Math.round(window.innerHeight * 0.16); + const maxHeight = () => Math.round(window.innerHeight * 0.94); + + grip.addEventListener('pointerdown', (event) => { + if (!phone.matches) return; + const rect = sheet.getBoundingClientRect(); + // Start from the height the sheet has now, so the first move does not jump. + drag = { id: event.pointerId, fromY: event.clientY, startH: rect.height }; + sheet.style.maxHeight = 'none'; + sheet.style.height = `${rect.height}px`; + try { grip.setPointerCapture(event.pointerId); } catch { /* capture is optional */ } + event.preventDefault(); + }); + grip.addEventListener('pointermove', (event) => { + if (!drag || event.pointerId !== drag.id) return; + // Dragging up grows the sheet (its top edge climbs); dragging down shrinks it. + const next = drag.startH + (drag.fromY - event.clientY); + sheet.style.height = `${Math.min(maxHeight(), Math.max(minHeight(), next))}px`; + event.preventDefault(); + }); + const end = (event) => { + if (!drag || (event && event.pointerId !== drag.id)) return; + drag = null; + }; + grip.addEventListener('pointerup', end); + grip.addEventListener('pointercancel', end); + + // A window grown to the desktop layout keeps the side column: drop the height + // the drag had fixed, so the panel goes back to filling the screen. + const clearOnDesktop = () => { + if (phone.matches) return; + sheet.style.height = ''; + sheet.style.maxHeight = ''; + }; + window.addEventListener('resize', clearOnDesktop); + } + Object.assign(app.actions, { capturePose, applyState, |
