-
Notifications
You must be signed in to change notification settings - Fork 114
Description
In #1782 we added MarkdownStream with an instance method for creating UI in Shiny Express (md.ui()) and a functional method in Core (ui.output_markdown_stream()). Carson and I discussed this at length and have decided to merge MarkdownStream in this state, but come back to the design consideration soon. This issue summarizes that discussion:
-
Unified Syntax: We should aim to create components that can be used identically in both Core and Express, minimizing complexity for future support.
-
Automatic UI Generation: In Express, we can simplify by allowing automatic creation of UI elements (e.g., eliminating
ui.output_plot()in favor of@render.plot). In general, I feel this should be the only allowed difference between usages.As written in Add
ui.MarkdownStream#1782, forMarkdownStream, users must still manually insert UI but in a way that differs between Express and Core. -
Class-Based vs. Shiny Paradigms: While the class-based approach is natural in Python, it conflicts with Shiny's existing patterns. I think we should either fully lean into a class-based component across all contexts or adhere to a common interface.
-
Implementation with Modules: One option would be to leverage Shiny Modules for the
MarkdownStreamcomponent. This has the advantage of using existing syntax. The implementation for Core would look like this:ui = ui.page_fluid( ui.markdown_stream_ui("readme") ) def server(input, output, session): md_readme = ui.markdown_stream_server("readme") @reactive.effect async def _(): await md_readme.stream(chunk_generator())
-
Express Version: We could modify the Express version of
markdown_stream_server()to directly emit UI, potentially renaming it tomarkdown_stream()for consistency:from shiny.express import ui md_readme = ui.markdown_stream_server("readme") @reactive.effect async def _(): await md_readme.stream(chunk_generator())