← Whispering

feat: Change AI & TTS panel to expand from left side

d66ef19d0242443b7be6180dc939899a5ca4d843 · Claude · Jan 26, 2026 06:45

Convert the AI & TTS collapsible panel from a vertical expanding
column to a left-side drawer. The panel now slides out from the
left of the window when the toggle button is clicked, using a
dialog with position=left. Includes a header with close button.

+27 −14 · 1 file changed

  • src/whispering_ui/components/sidebar.py +27 −14
diff --git a/src/whispering_ui/components/sidebar.py b/src/whispering_ui/components/sidebar.py
index 75d08ce..5e428ee 100644
--- a/src/whispering_ui/components/sidebar.py
+++ b/src/whispering_ui/components/sidebar.py
@@ -330,25 +330,38 @@ def create_sidebar(state: AppState, bridge: ProcessingBridge, output_container=N
 
         ui.separator().classes('my-1')
 
-        # === AI & TTS COLLAPSIBLE PANEL ===
-        # Toggle button for AI & TTS settings
-        ai_tts_panel_visible = [False]  # Track panel visibility
+        # === AI & TTS LEFT DRAWER PANEL ===
+        # Create a dialog positioned on the left side that acts as a drawer
+        ai_tts_drawer = ui.dialog().props('position=left full-height seamless')
+        ai_tts_drawer_visible = [False]
+
+        def toggle_ai_tts_drawer():
+            ai_tts_drawer_visible[0] = not ai_tts_drawer_visible[0]
+            if ai_tts_drawer_visible[0]:
+                ai_tts_drawer.open()
+                ai_tts_toggle_btn.text = 'AI & TTS ◀'
+            else:
+                ai_tts_drawer.close()
+                ai_tts_toggle_btn.text = 'AI & TTS ▶'
+
+        # Handle drawer close via clicking outside
+        def on_drawer_hide():
+            ai_tts_drawer_visible[0] = False
+            ai_tts_toggle_btn.text = 'AI & TTS ▶'
 
-        def toggle_ai_tts_panel():
-            ai_tts_panel_visible[0] = not ai_tts_panel_visible[0]
-            ai_tts_panel.set_visibility(ai_tts_panel_visible[0])
-            ai_tts_toggle_btn.text = 'AI & TTS ▲' if ai_tts_panel_visible[0] else 'AI & TTS ▼'
+        ai_tts_drawer.on('hide', on_drawer_hide)
 
         ai_tts_toggle_btn = ui.button(
-            'AI & TTS ▼',
-            on_click=toggle_ai_tts_panel
+            'AI & TTS ▶',
+            on_click=toggle_ai_tts_drawer
         ).classes('w-full').props('dense flat')
 
-        # Collapsible panel container
-        ai_tts_panel = ui.column().classes('w-full gap-1 pl-2 border-l-2 border-gray-600')
-        ai_tts_panel.set_visibility(False)
-
-        with ai_tts_panel:
+        # Drawer content
+        with ai_tts_drawer, ui.card().classes('h-full w-80 p-3 gap-1').style('overflow-y: auto;'):
+            # Close button at top
+            with ui.row().classes('items-center justify-between w-full mb-2'):
+                ui.label('AI & TTS Settings').classes('font-bold text-sm')
+                ui.button(icon='close', on_click=lambda: (ai_tts_drawer.close(), setattr(ai_tts_toggle_btn, 'text', 'AI & TTS ▶'))).props('flat dense round size=sm')
             # === AI SECTION ===
             with ui.row().classes('items-center justify-between w-full'):
                 ui.label('AI Processing').classes('font-bold text-sm')