@@ -142,6 +142,8 @@ export interface ChatSource {
142142 similarity : number
143143 flow_slug ?: string
144144 flow_id ?: string
145+ /** Source type - determines routing behavior */
146+ type ?: 'help_article' | 'blog_post'
145147}
146148
147149interface ChatMessage {
@@ -357,10 +359,17 @@ export function ChatWidget({
357359 const [ inputValue , setInputValue ] = useState ( '' )
358360 const [ messages , setMessages ] = useState < ChatMessage [ ] > ( [ ] )
359361 const [ isLoading , setIsLoading ] = useState ( false )
360- const messagesEndRef = useRef < HTMLDivElement > ( null )
362+ const chatContainerRef = useRef < HTMLDivElement > ( null )
361363
362364 const scrollToBottom = ( ) => {
363- messagesEndRef . current ?. scrollIntoView ( { behavior : 'smooth' } )
365+ if ( chatContainerRef . current ) {
366+ // Use requestAnimationFrame for smoother scroll after content renders
367+ requestAnimationFrame ( ( ) => {
368+ if ( chatContainerRef . current ) {
369+ chatContainerRef . current . scrollTop = chatContainerRef . current . scrollHeight
370+ }
371+ } )
372+ }
364373 }
365374
366375 useEffect ( ( ) => {
@@ -528,18 +537,24 @@ export function ChatWidget({
528537 { /* Chat Panel */ }
529538 < div
530539 className = { cn (
531- "w-[calc(100vw-2rem)] sm:w-[380px] md:w-[400px] rounded-2xl shadow-2xl flex flex-col overflow-hidden" ,
540+ "rounded-2xl shadow-2xl flex flex-col overflow-hidden" ,
532541 "transition-all duration-300 ease-out origin-bottom-right" ,
533542 isOpen ? "opacity-100 scale-100" : "h-0 opacity-0 scale-95 pointer-events-none"
534543 ) }
535544 style = { {
536545 backgroundColor : resolvedColors . chatBackground ,
537546 border : `1px solid ${ resolvedColors . border } ` ,
538- // Use dvh (dynamic viewport height) for mobile keyboard support, with vh fallback
547+ // Fixed width on mobile, responsive on larger screens
548+ width : 'min(calc(100vw - 2rem), 400px)' ,
549+ maxWidth : '400px' ,
550+ // Use dvh (dynamic viewport height) for mobile keyboard support
539551 height : isOpen ? 'min(560px, calc(100dvh - 6rem))' : '0' ,
540552 fontSize : resolvedFontSize ,
541553 // Prevent touch-based zooming/panning on the widget itself
542554 touchAction : 'manipulation' ,
555+ // Prevent content from causing overflow
556+ wordBreak : 'break-word' ,
557+ overflowWrap : 'break-word' ,
543558 } }
544559 >
545560 { /* Header */ }
@@ -591,8 +606,13 @@ export function ChatWidget({
591606
592607 { /* Chat Area */ }
593608 < div
594- className = "flex-1 overflow-y-auto p-4 space-y-5"
595- style = { { backgroundColor : resolvedColors . chatBackground } }
609+ ref = { chatContainerRef }
610+ className = "flex-1 overflow-y-auto overflow-x-hidden p-4 space-y-5"
611+ style = { {
612+ backgroundColor : resolvedColors . chatBackground ,
613+ // Contain content to prevent horizontal overflow
614+ overscrollBehavior : 'contain' ,
615+ } }
596616 >
597617 { ! showChat ? (
598618 < >
@@ -685,13 +705,99 @@ export function ChatWidget({
685705 ) : (
686706 < div className = "max-w-[95%]" >
687707 < div
688- className = "prose prose-sm max-w-none "
708+ className = "appgram-chat-markdown "
689709 style = { {
690710 color : resolvedColors . foreground ,
691- '--tw-prose-links' : accentColor ,
692- } as React . CSSProperties }
711+ fontSize : 'inherit' ,
712+ lineHeight : '1.6' ,
713+ } }
693714 >
694- < ReactMarkdown > { message . content } </ ReactMarkdown >
715+ < ReactMarkdown
716+ components = { {
717+ p : ( { children } ) => (
718+ < p style = { { margin : '0 0 0.75em 0' } } > { children } </ p >
719+ ) ,
720+ a : ( { href, children } ) => (
721+ < a
722+ href = { href }
723+ target = "_blank"
724+ rel = "noopener noreferrer"
725+ style = { { color : accentColor , textDecoration : 'underline' } }
726+ >
727+ { children }
728+ </ a >
729+ ) ,
730+ strong : ( { children } ) => (
731+ < strong style = { { fontWeight : 600 } } > { children } </ strong >
732+ ) ,
733+ em : ( { children } ) => (
734+ < em style = { { fontStyle : 'italic' } } > { children } </ em >
735+ ) ,
736+ ul : ( { children } ) => (
737+ < ul style = { { margin : '0.5em 0' , paddingLeft : '1.25em' , listStyleType : 'disc' } } >
738+ { children }
739+ </ ul >
740+ ) ,
741+ ol : ( { children } ) => (
742+ < ol style = { { margin : '0.5em 0' , paddingLeft : '1.25em' , listStyleType : 'decimal' } } >
743+ { children }
744+ </ ol >
745+ ) ,
746+ li : ( { children } ) => (
747+ < li style = { { margin : '0.25em 0' } } > { children } </ li >
748+ ) ,
749+ code : ( { children } ) => (
750+ < code
751+ style = { {
752+ backgroundColor : resolvedColors . border ,
753+ padding : '0.125em 0.375em' ,
754+ borderRadius : '4px' ,
755+ fontSize : '0.875em' ,
756+ fontFamily : 'monospace' ,
757+ } }
758+ >
759+ { children }
760+ </ code >
761+ ) ,
762+ pre : ( { children } ) => (
763+ < pre
764+ style = { {
765+ backgroundColor : resolvedColors . border ,
766+ padding : '0.75em' ,
767+ borderRadius : '8px' ,
768+ overflow : 'auto' ,
769+ margin : '0.5em 0' ,
770+ fontSize : '0.875em' ,
771+ } }
772+ >
773+ { children }
774+ </ pre >
775+ ) ,
776+ blockquote : ( { children } ) => (
777+ < blockquote
778+ style = { {
779+ borderLeft : `3px solid ${ accentColor } ` ,
780+ paddingLeft : '1em' ,
781+ margin : '0.5em 0' ,
782+ color : resolvedColors . mutedForeground ,
783+ } }
784+ >
785+ { children }
786+ </ blockquote >
787+ ) ,
788+ h1 : ( { children } ) => (
789+ < h1 style = { { fontSize : '1.25em' , fontWeight : 600 , margin : '0.5em 0' } } > { children } </ h1 >
790+ ) ,
791+ h2 : ( { children } ) => (
792+ < h2 style = { { fontSize : '1.125em' , fontWeight : 600 , margin : '0.5em 0' } } > { children } </ h2 >
793+ ) ,
794+ h3 : ( { children } ) => (
795+ < h3 style = { { fontSize : '1em' , fontWeight : 600 , margin : '0.5em 0' } } > { children } </ h3 >
796+ ) ,
797+ } }
798+ >
799+ { message . content }
800+ </ ReactMarkdown >
695801 </ div >
696802 { message . sources && message . sources . length > 0 && (
697803 < div
@@ -804,7 +910,6 @@ export function ChatWidget({
804910 </ div >
805911 </ div >
806912 ) }
807- < div ref = { messagesEndRef } />
808913 </ >
809914 ) }
810915 </ div >
0 commit comments