Streamlit reruns the whole script on any widget interaction, so the embed is torn down and rebuilt from scratch every time. maidr loses everything it holds in the browser: focus position, the current data point, open braille/text panels, and audio state. On use_cdn=False the ~1.9 MB bundle is also re-parsed each time.
For a keyboard-driven, sonification-first interface this is worse than it sounds. A reader partway through navigating a chart who touches any control on the page is returned to the start, with no announcement that it happened.
Mitigations available today (both documented in docs/examples.qmd as part of #459):
- Cache the HTML string rather than the render call —
maidr_html() exists for exactly this. Note the cached function needs an explicit hashable key alongside the underscore-prefixed figure, or the cache key is constant and the first chart is returned forever.
- Avoid frequently-rerunning
st.fragment around the chart.
Neither restores client state; they only avoid rebuilding the string.
A real fix needs a bidirectional component that updates in place instead of being replaced — and that is blocked. Streamlit's own app binds r, c and esc at the document level, exempting only form fields, and maidr binds all three. The iframe is currently what keeps maidr's keybindings working at all, so moving to an embedding that renders into the Streamlit page would trade state preservation for the keyboard interface. See the module docstring in maidr/widget/streamlit.py for why components v2 is not the target.
Filing this as a known ceiling rather than a plan. Worth revisiting if Streamlit ever offers a documented opt-out from its document-level key handling.
Follow-up from #459.
Streamlit reruns the whole script on any widget interaction, so the embed is torn down and rebuilt from scratch every time. maidr loses everything it holds in the browser: focus position, the current data point, open braille/text panels, and audio state. On
use_cdn=Falsethe ~1.9 MB bundle is also re-parsed each time.For a keyboard-driven, sonification-first interface this is worse than it sounds. A reader partway through navigating a chart who touches any control on the page is returned to the start, with no announcement that it happened.
Mitigations available today (both documented in
docs/examples.qmdas part of #459):maidr_html()exists for exactly this. Note the cached function needs an explicit hashable key alongside the underscore-prefixed figure, or the cache key is constant and the first chart is returned forever.st.fragmentaround the chart.Neither restores client state; they only avoid rebuilding the string.
A real fix needs a bidirectional component that updates in place instead of being replaced — and that is blocked. Streamlit's own app binds
r,candescat the document level, exempting only form fields, and maidr binds all three. The iframe is currently what keeps maidr's keybindings working at all, so moving to an embedding that renders into the Streamlit page would trade state preservation for the keyboard interface. See the module docstring inmaidr/widget/streamlit.pyfor why components v2 is not the target.Filing this as a known ceiling rather than a plan. Worth revisiting if Streamlit ever offers a documented opt-out from its document-level key handling.
Follow-up from #459.