From e204dc215cbc7399f388a2d04c0536ff7f29f227 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 27 May 2026 05:51:26 +0000 Subject: [PATCH] fix: sidebar hint as pure CSS keyed on aria-expanded MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause of all prior failures: the JS queried [data-testid="stSidebarCollapsedControl"], which does not exist in Streamlit 1.57 — so the "sidebar closed" check was never true and the arrow never showed. Both st.html and st.components.v1.html also render in an iframe whose timers die on every Streamlit re-render, and st.components.v1.html is deprecated (removed after 2026-06-01). Replace the whole thing with pure CSS injected via st.markdown (renders inline in the main document, keeps " + '
' + f'
{hint_label}
', + unsafe_allow_html=True, ) - # Plain Python string — no f-string, so { } are JS literals, no escaping. - _main_script = ( - "(function(){" - "if(window._sbRunInit)return;" - "window._sbRunInit=true;" - "if(sessionStorage.getItem('sbVisited'))return;" - "var s=document.createElement('style');" - "s.textContent='@keyframes sb-bounce{0%,100%{transform:translate(0,0);opacity:1}" - "50%{transform:translate(-9px,-9px);opacity:.75}}" - "#_sb_hint{display:none;position:fixed;top:68px;left:44px;z-index:99999;" - "flex-direction:column;align-items:flex-start;gap:3px;pointer-events:none}" - "#_sb_hint ._a{font-size:22px;color:#0088ff;" - "animation:sb-bounce 1.1s ease-in-out infinite;line-height:1}" - "#_sb_hint ._t{background:#0088ff;color:#fff;padding:3px 9px;" - "border-radius:10px;font-size:11px;white-space:nowrap;" - "font-family:sans-serif;font-weight:600;" - "box-shadow:0 2px 6px rgba(0,136,255,.4)}';" - "document.head.appendChild(s);" - "var h=document.createElement('div');" - "h.id='_sb_hint';" - f"h.innerHTML={_hint_inner};" - "document.body.appendChild(h);" - "function closed(){" - "var b=document.querySelector('[data-testid=\"stSidebarCollapsedControl\"]');" - "return !!b&&getComputedStyle(b).display!=='none';}" - "function dismiss(){" - "sessionStorage.setItem('sbVisited','1');" - "window._sbShowing=false;" - "h.style.display='none';" - "if(window._sbTimer){clearTimeout(window._sbTimer);window._sbTimer=null;}" - "if(window._sbPoll){clearInterval(window._sbPoll);window._sbPoll=null;}}" - "window._sbPoll=setInterval(function(){" - "if(sessionStorage.getItem('sbVisited')){clearInterval(window._sbPoll);return;}" - "if(window._sbShowing&&!closed())dismiss();},400);" - "window._sbTimer=setTimeout(function(){" - "if(!sessionStorage.getItem('sbVisited')&&closed()){" - "h.style.display='flex';window._sbShowing=true;}},20000);" - "})()" - ) - _main_script_json = json.dumps(_main_script) - st_components.html(f"""""", height=0) # Show documentation (needs no DB) so users aren't stranded on a blank page from finance_tracker.web.views.documentation import render as doc_render