@@ -66,23 +66,35 @@ function wrapMessageElement(messageElement, role) {
6666 const wrapper = document . createElement ( "div" ) ;
6767 wrapper . appendChild ( messageElement ) ;
6868 if ( role == "assistant" ) {
69- const controlContainer = document . createElement ( "div" ) ;
69+ const controlContainer = wrapper . appendChild ( document . createElement ( "div" ) ) ;
7070 controlContainer . appendChild ( createCopyButton ( ( ) => messageElement . textContent , ( ) => messageElement . innerHTML ) ) ;
71- controlContainer . appendChild ( infoButton ( ) ) ;
71+ controlContainer . appendChild ( infoButton ( wrapper ) ) ;
7272 controlContainer . classList . add ( "message-controls" ) ;
73- wrapper . appendChild ( controlContainer ) ;
7473 }
7574 wrapper . classList . add ( "message-wrapper" , role ) ;
7675 return wrapper ;
7776}
7877
7978function infoButton ( container , stats ) {
8079 let button = container ?. querySelector ( "#stats" ) ;
80+ let statsElement = container ?. querySelector ( "#info-container" ) ;
8181 if ( ! button ) {
8282 button = document . createElement ( "button" ) ;
8383 button . id = "stats" ;
8484 button . innerText = "i" ;
8585 button . style . fontFamily = "monospace" ;
86+
87+ statsElement = document . createElement ( "div" ) ;
88+ statsElement . id = "info-container" ;
89+ statsElement . className = "hidden" ;
90+ container . append ( statsElement ) ;
91+ button . addEventListener ( "click" , ( ) => {
92+ const show = ! button . classList . contains ( "toggled" ) ;
93+ statsElement . classList . toggle ( "hidden" , ! show ) ;
94+ button . classList . toggle ( "toggled" , show ) ;
95+ if ( show )
96+ requestAnimationFrame ( ( ) => scrollIntoViewIfNeeded ( statsElement , container . parentElement ) ) ;
97+ } ) ;
8698 }
8799 button . style . display = stats ? "" : "none" ;
88100 if ( stats ) {
@@ -102,10 +114,24 @@ function infoButton(container, stats) {
102114 parts . push ( "Incomplete" ) ;
103115 }
104116 button . title = parts . join ( "\n" ) ;
117+ statsElement . innerHTML = "" ;
118+ parts . forEach ( part => statsElement . appendChild ( wrapInSpan ( part + " " ) ) ) ;
105119 }
106120 return button ;
107121}
108122
123+ function scrollIntoViewIfNeeded ( elem , container ) {
124+ let rectElem = elem . getBoundingClientRect ( ) , rectContainer = container . getBoundingClientRect ( ) ;
125+ if ( rectElem . bottom > rectContainer . bottom ) elem . scrollIntoView ( false ) ;
126+ if ( rectElem . top < rectContainer . top ) elem . scrollIntoView ( ) ;
127+ }
128+
129+ function wrapInSpan ( innerText ) {
130+ const span = document . createElement ( "span" ) ;
131+ span . innerText = innerText ;
132+ return span ;
133+ }
134+
109135function createMessageElement ( content ) {
110136 const messageDiv = document . createElement ( "div" ) ;
111137 messageDiv . classList . add ( "message" ) ;
0 commit comments