@@ -158,18 +158,87 @@ removeBtn.addEventListener('click', () => {
158158 }
159159} ) ;
160160
161- // --- Mobile UI Toggles ---
161+ // --- Mobile UI Drawer Logic ---
162162const controlPanel = document . getElementById ( 'control-panel' ) ;
163- const panelToggle = document . getElementById ( 'panel-toggle' ) ;
164- const closePanel = document . getElementById ( 'close-panel' ) ;
163+ const dragHandle = document . querySelector ( '.drag-handle' ) ;
165164
166- panelToggle . addEventListener ( 'click' , ( ) => {
167- controlPanel . classList . add ( 'open' ) ;
168- } ) ;
165+ let startY = 0 ;
166+ let currentY = 0 ;
167+ let isDragging = false ;
168+ let panelHeight = 0 ;
169169
170- closePanel . addEventListener ( 'click' , ( ) => {
171- controlPanel . classList . remove ( 'open' ) ;
172- } ) ;
170+ function setPanelTranslate ( y ) {
171+ controlPanel . style . transform = `translateY(${ y } px)` ;
172+ }
173+
174+ function updatePanelState ( isOpen ) {
175+ controlPanel . classList . toggle ( 'open' , isOpen ) ;
176+ controlPanel . style . transform = '' ; // Clear inline styles to let CSS take over
177+ }
178+
179+ // Gesture Handling
180+ function onTouchStart ( e ) {
181+ if ( window . innerWidth > 768 ) return ;
182+
183+ // Only allow dragging from handle or header area to avoid conflict with content scroll
184+ const touchY = e . touches [ 0 ] . clientY ;
185+ const panelRect = controlPanel . getBoundingClientRect ( ) ;
186+
187+ // Check if touch is in the top portion of the panel
188+ if ( touchY - panelRect . top > 80 ) return ;
189+
190+ startY = touchY ;
191+ panelHeight = panelRect . height ;
192+ isDragging = true ;
193+ controlPanel . style . transition = 'none' ; // Instant feedback
194+ }
195+
196+ function onTouchMove ( e ) {
197+ if ( ! isDragging ) return ;
198+
199+ const touchY = e . touches [ 0 ] . clientY ;
200+ const deltaY = touchY - startY ;
201+
202+ // Calculate new position
203+ // If open (translateY = 0), deltaY > 0 moves down (closing)
204+ // If closed (translateY = height - 60), deltaY < 0 moves up (opening)
205+ const isCurrentlyOpen = controlPanel . classList . contains ( 'open' ) ;
206+ const baseTranslate = isCurrentlyOpen ? 0 : ( panelHeight - 60 ) ;
207+ let newTranslate = baseTranslate + deltaY ;
208+
209+ // Bounds: don't push too high or too low
210+ newTranslate = Math . max ( 0 , Math . min ( newTranslate , panelHeight - 60 ) ) ;
211+
212+ setPanelTranslate ( newTranslate ) ;
213+ currentY = newTranslate ;
214+
215+ // Prevent background scrolling
216+ if ( e . cancelable ) e . preventDefault ( ) ;
217+ }
218+
219+ function onTouchEnd ( ) {
220+ if ( ! isDragging ) return ;
221+ isDragging = false ;
222+ controlPanel . style . transition = '' ; // Restore smooth CSS transition
223+
224+ const isCurrentlyOpen = controlPanel . classList . contains ( 'open' ) ;
225+ const threshold = panelHeight * 0.3 ; // 30% of height needed to toggle
226+
227+ if ( isCurrentlyOpen ) {
228+ // Closing: if moved more than 30% down, close it
229+ updatePanelState ( currentY < threshold ) ;
230+ } else {
231+ // Opening: if moved more than 30% up from closed state
232+ const closedPos = panelHeight - 60 ;
233+ updatePanelState ( currentY < closedPos - threshold ) ;
234+ }
235+ }
236+
237+ // Attach listeners to the panel itself for broad hit area,
238+ // filtered by onTouchStart's position check
239+ controlPanel . addEventListener ( 'touchstart' , onTouchStart , { passive : false } ) ;
240+ window . addEventListener ( 'touchmove' , onTouchMove , { passive : false } ) ;
241+ window . addEventListener ( 'touchend' , onTouchEnd ) ;
173242
174243// --- Drag and Drop ---
175244
0 commit comments