@@ -42,45 +42,45 @@ export function ChatArtifactContainer({
4242 children : React . ReactNode
4343} ) {
4444 const { state } = useArtifact ( )
45- const containerRef = useRef < HTMLDivElement > ( null )
45+ const [ containerElement , setContainerElement ] =
46+ useState < HTMLDivElement | null > ( null )
47+ const hasAppliedSavedWidthRef = useRef ( false )
4648 const [ width , setWidth ] = useState ( DEFAULT_WIDTH )
4749 const [ isResizing , setIsResizing ] = useState ( false )
4850 const hasUser = useHasUser ( )
4951 const { open, isMobile : isMobileSidebar } = useSidebar ( )
5052
51- // Load saved width after hydration
52- useEffect ( ( ) => {
53+ const setContainerRef = useCallback ( ( node : HTMLDivElement | null ) => {
54+ setContainerElement ( node )
55+
56+ if ( ! node || hasAppliedSavedWidthRef . current ) {
57+ return
58+ }
59+
60+ hasAppliedSavedWidthRef . current = true
61+
5362 const savedWidth = localStorage . getItem ( 'artifactPanelWidth' )
54- if ( savedWidth ) {
55- const parsedWidth = parseInt ( savedWidth , 10 )
56- // Ensure parsedWidth is at least MIN_WIDTH to prevent invalid panel states
57- if (
58- ! isNaN ( parsedWidth ) &&
59- parsedWidth >= MIN_WIDTH &&
60- parsedWidth <= MAX_WIDTH
61- ) {
62- // Clamp against available space considering chat minimum width
63- const containerRect = containerRef . current ?. getBoundingClientRect ( )
64- if ( containerRect ) {
65- const { allowedMin, allowedMax } = getAllowedWidthBounds (
66- containerRect . width
67- )
68- const clamped = Math . min (
69- Math . max ( parsedWidth , allowedMin ) ,
70- allowedMax
71- )
72- setWidth ( clamped )
73- } else {
74- setWidth ( parsedWidth )
75- }
76- }
63+ if ( ! savedWidth ) {
64+ return
65+ }
66+
67+ const parsedWidth = parseInt ( savedWidth , 10 )
68+ if (
69+ isNaN ( parsedWidth ) ||
70+ parsedWidth < MIN_WIDTH ||
71+ parsedWidth > MAX_WIDTH
72+ ) {
73+ return
7774 }
75+
76+ const { allowedMin, allowedMax } = getAllowedWidthBounds ( node . clientWidth )
77+ const clampedWidth = Math . min ( Math . max ( parsedWidth , allowedMin ) , allowedMax )
78+ setWidth ( clampedWidth )
7879 } , [ ] )
7980
8081 // Keep width in bounds when container resizes (e.g., window resize)
8182 useEffect ( ( ) => {
82- const el = containerRef . current
83- if ( ! el ) return
83+ if ( ! containerElement ) return
8484 const ro = new ResizeObserver ( entries => {
8585 for ( const entry of entries ) {
8686 const { allowedMin, allowedMax } = getAllowedWidthBounds (
@@ -89,9 +89,9 @@ export function ChatArtifactContainer({
8989 setWidth ( prev => Math . min ( Math . max ( prev , allowedMin ) , allowedMax ) )
9090 }
9191 } )
92- ro . observe ( el )
92+ ro . observe ( containerElement )
9393 return ( ) => ro . disconnect ( )
94- } , [ ] )
94+ } , [ containerElement ] )
9595
9696 const startResize = useCallback ( ( e : React . MouseEvent ) => {
9797 e . preventDefault ( )
@@ -102,7 +102,7 @@ export function ChatArtifactContainer({
102102 if ( ! isResizing ) return
103103
104104 const handleMouseMove = ( e : MouseEvent ) => {
105- const containerRect = containerRef . current ?. getBoundingClientRect ( )
105+ const containerRect = containerElement ?. getBoundingClientRect ( )
106106 if ( containerRect ) {
107107 const newWidth = containerRect . right - e . clientX
108108 const { allowedMin, allowedMax } = getAllowedWidthBounds (
@@ -128,7 +128,7 @@ export function ChatArtifactContainer({
128128 document . removeEventListener ( 'mousemove' , handleMouseMove )
129129 document . removeEventListener ( 'mouseup' , handleMouseUp )
130130 }
131- } , [ isResizing ] )
131+ } , [ containerElement , isResizing ] )
132132
133133 return (
134134 < div className = "flex-1 min-h-0 min-w-0 h-screen flex" >
@@ -140,7 +140,7 @@ export function ChatArtifactContainer({
140140
141141 { /* Desktop: Independent panels like morphic-studio */ }
142142 < div
143- ref = { containerRef }
143+ ref = { setContainerRef }
144144 className = "hidden md:flex flex-1 min-w-0 overflow-hidden"
145145 >
146146 { /* Chat Panel - Independent container */ }
0 commit comments