@@ -28,6 +28,7 @@ import { pythonGenerator } from 'blockly/python';
2828import Header from './reactComponents/Header' ;
2929import * as Menu from './reactComponents/Menu' ;
3030import CodeDisplay from './reactComponents/CodeDisplay' ;
31+ import SiderCollapseTrigger from './reactComponents/SiderCollapseTrigger' ;
3132import BlocklyComponent , { BlocklyComponentType } from './reactComponents/BlocklyComponent' ;
3233import ToolboxSettingsModal from './reactComponents/ToolboxSettings' ;
3334import * as Tabs from './reactComponents/Tabs' ;
@@ -78,10 +79,10 @@ const FULL_VIEWPORT_HEIGHT = '100vh';
7879const FULL_HEIGHT = '100%' ;
7980
8081/** Default size for code panel. */
81- const CODE_PANEL_DEFAULT_SIZE = '25%' ;
82+ const CODE_PANEL_DEFAULT_SIZE = 400 ;
8283
8384/** Minimum size for code panel. */
84- const CODE_PANEL_MIN_SIZE = 80 ;
85+ const CODE_PANEL_MIN_SIZE = 100 ;
8586
8687/** Background color for testing layout. */
8788const LAYOUT_BACKGROUND_COLOR = '#0F0' ;
@@ -166,7 +167,10 @@ const AppContent: React.FC<AppContentProps> = ({ project, setProject }): React.J
166167 const [ shownPythonToolboxCategories , setShownPythonToolboxCategories ] = React . useState < Set < string > > ( new Set ( ) ) ;
167168 const [ triggerPythonRegeneration , setTriggerPythonRegeneration ] = React . useState ( 0 ) ;
168169 const [ leftCollapsed , setLeftCollapsed ] = React . useState ( false ) ;
169- const [ rightCollapsed , setRightCollapsed ] = React . useState ( false ) ;
170+ const [ codePanelSize , setCodePanelSize ] = React . useState < number > ( CODE_PANEL_DEFAULT_SIZE ) ;
171+ const [ codePanelCollapsed , setCodePanelCollapsed ] = React . useState ( false ) ;
172+ const [ codePanelExpandedSize , setCodePanelExpandedSize ] = React . useState < number > ( CODE_PANEL_DEFAULT_SIZE ) ;
173+ const [ codePanelAnimating , setCodePanelAnimating ] = React . useState ( false ) ;
170174 const [ theme , setTheme ] = React . useState ( 'dark' ) ;
171175 const [ languageInitialized , setLanguageInitialized ] = React . useState ( false ) ;
172176 const [ themeInitialized , setThemeInitialized ] = React . useState ( false ) ;
@@ -378,6 +382,27 @@ const AppContent: React.FC<AppContentProps> = ({ project, setProject }): React.J
378382 setToolboxSettingsModalIsOpen ( false ) ;
379383 } ;
380384
385+ /** Toggles the code panel between collapsed and expanded states. */
386+ const toggleCodePanelCollapse = ( ) : void => {
387+ setCodePanelAnimating ( true ) ;
388+
389+ if ( codePanelCollapsed ) {
390+ // Expand to previous size
391+ setCodePanelSize ( codePanelExpandedSize ) ;
392+ setCodePanelCollapsed ( false ) ;
393+ } else {
394+ // Collapse to minimum size
395+ setCodePanelExpandedSize ( codePanelSize ) ;
396+ setCodePanelSize ( CODE_PANEL_MIN_SIZE ) ;
397+ setCodePanelCollapsed ( true ) ;
398+ }
399+
400+ // Reset animation flag after transition completes
401+ setTimeout ( ( ) => {
402+ setCodePanelAnimating ( false ) ;
403+ } , 200 ) ;
404+ } ;
405+
381406 /** Handles toolbox settings modal OK with updated categories. */
382407 const handleToolboxSettingsConfirm = ( updatedShownCategories : Set < string > ) : void => {
383408 setToolboxSettingsModalIsOpen ( false ) ;
@@ -618,6 +643,8 @@ const AppContent: React.FC<AppContentProps> = ({ project, setProject }): React.J
618643 collapsible
619644 collapsed = { leftCollapsed }
620645 onCollapse = { ( collapsed : boolean ) => setLeftCollapsed ( collapsed ) }
646+ trigger = { null }
647+ style = { { position : 'relative' } }
621648 >
622649 < Menu . Component
623650 storage = { storage }
@@ -629,6 +656,10 @@ const AppContent: React.FC<AppContentProps> = ({ project, setProject }): React.J
629656 theme = { theme }
630657 setTheme = { setTheme }
631658 />
659+ < SiderCollapseTrigger
660+ collapsed = { leftCollapsed }
661+ onToggle = { ( ) => setLeftCollapsed ( ! leftCollapsed ) }
662+ />
632663 </ Sider >
633664 < Antd . Layout >
634665 < Tabs . Component
@@ -642,8 +673,8 @@ const AppContent: React.FC<AppContentProps> = ({ project, setProject }): React.J
642673 setProject = { setProject }
643674 storage = { storage }
644675 />
645- < Antd . Layout >
646- < Content >
676+ < div style = { { display : 'flex' , height : FULL_HEIGHT } } >
677+ < Content style = { { flex : 1 , height : '100%' } } >
647678 { modulePaths . current . map ( ( modulePath ) => (
648679 < BlocklyComponent
649680 key = { modulePath }
@@ -654,22 +685,65 @@ const AppContent: React.FC<AppContentProps> = ({ project, setProject }): React.J
654685 />
655686 ) ) }
656687 </ Content >
657- < Sider
658- collapsible
659- reverseArrow = { true }
660- collapsed = { rightCollapsed }
661- collapsedWidth = { CODE_PANEL_MIN_SIZE }
662- width = { CODE_PANEL_DEFAULT_SIZE }
663- onCollapse = { ( collapsed : boolean ) => setRightCollapsed ( collapsed ) }
688+ < div
689+ style = { {
690+ width : `${ codePanelSize } px` ,
691+ minWidth : CODE_PANEL_MIN_SIZE ,
692+ height : '100%' ,
693+ borderLeft : '1px solid #d9d9d9' ,
694+ position : 'relative' ,
695+ transition : codePanelAnimating ? 'width 0.2s ease' : 'none'
696+ } }
664697 >
698+ < div
699+ style = { {
700+ position : 'absolute' ,
701+ left : 0 ,
702+ top : 0 ,
703+ width : '4px' ,
704+ height : '100%' ,
705+ cursor : 'ew-resize' ,
706+ backgroundColor : 'transparent' ,
707+ zIndex : 10 ,
708+ transform : 'translateX(-2px)'
709+ } }
710+ onMouseDown = { ( e ) => {
711+ e . preventDefault ( ) ;
712+ const startX = e . clientX ;
713+ const startWidth = codePanelSize ;
714+
715+ const handleMouseMove = ( e : MouseEvent ) => {
716+ const deltaX = startX - e . clientX ;
717+ const newWidth = Math . max ( CODE_PANEL_MIN_SIZE , startWidth + deltaX ) ;
718+ setCodePanelSize ( newWidth ) ;
719+ // Update expanded size if not at minimum
720+ if ( newWidth > CODE_PANEL_MIN_SIZE ) {
721+ setCodePanelExpandedSize ( newWidth ) ;
722+ setCodePanelCollapsed ( false ) ;
723+ } else {
724+ setCodePanelCollapsed ( true ) ;
725+ }
726+ } ;
727+
728+ const handleMouseUp = ( ) => {
729+ document . removeEventListener ( 'mousemove' , handleMouseMove ) ;
730+ document . removeEventListener ( 'mouseup' , handleMouseUp ) ;
731+ } ;
732+
733+ document . addEventListener ( 'mousemove' , handleMouseMove ) ;
734+ document . addEventListener ( 'mouseup' , handleMouseUp ) ;
735+ } }
736+ />
665737 < CodeDisplay
666738 generatedCode = { generatedCode }
667739 messageApi = { messageApi }
668740 setAlertErrorMessage = { setAlertErrorMessage }
669741 theme = { theme }
742+ isCollapsed = { codePanelCollapsed }
743+ onToggleCollapse = { toggleCodePanelCollapse }
670744 />
671- </ Sider >
672- </ Antd . Layout >
745+ </ div >
746+ </ div >
673747 </ Antd . Layout >
674748 </ Antd . Layout >
675749 </ Antd . Layout >
0 commit comments