Skip to content

feat: add .page()/$page() methods wrapping shinychat's page_chat() - #291

Draft
cpsievert wants to merge 9 commits into
mainfrom
page-method
Draft

feat: add .page()/$page() methods wrapping shinychat's page_chat()#291
cpsievert wants to merge 9 commits into
mainfrom
page-method

Conversation

@cpsievert

Copy link
Copy Markdown
Contributor

Summary

Adds a .page() method (Python, Core + Express) and $page() method (R) to QueryChat, wrapping shinychat's new page_chat() for full-window, chat-first apps. It complements .sidebar()/.ui() and is now presented as the happy path in the Shiny build guides.

Design notes:

  • Python Core: new mod_page() module UI; page_chat() resolves the chat id against the module namespace, so .server() works unchanged.
  • Python Express: wraps shinychat.express.page_chat(), which owns the entire page — querychat's dependencies are injected via footer= (merged with any user footer), and the pre-namespaced chat id is passed as a ResolvedId to survive page_chat()'s internal resolve_id().
  • R: $page() factors querychat_dependency() out of mod_ui(); on both sides a user-supplied class is merged with the required querychat class.
  • Examples: new 03-page-core-app.py / 03-page-express-app.py put the reactive data view on a secondary chat_nav_panel() (Express uses ui.hold()).
  • Docs: "Chat-first page" sections in build.qmd and build.Rmd; changelog entries in both packages.

Verification

  • New unit tests: pkg-py/tests/test_page.py (8 tests) and a QueryChat$page() block in pkg-r/tests/testthat/test-QueryChat.R (7 tests).
  • New playwright smoke tests (test_03_page_apps.py, 6 tests) run both new example apps in a real browser — no API key needed.
  • Try it: shiny run pkg-py/examples/03-page-express-app.py, or in R: qc <- QueryChat$new(palmerpenguins::penguins); shinyApp(qc$page("Penguins"), \(...) qc$server()).

Adds a chat-first, full-window page option alongside .sidebar()/.ui():

- Python: QueryChat.page() (Core) and express QueryChat.page(), via new
  mod_page()/mod_page_extras() module UI functions. Express injects
  querychat's dependencies through page_chat(footer=) since
  shinychat.express.page_chat() owns the entire page, and passes a
  ResolvedId so the pre-namespaced chat ID survives page_chat()'s
  internal resolve_id().
- R: QueryChat$page(), factoring querychat_dependency() out of mod_ui().
- Examples: 03-page-core-app.py and 03-page-express-app.py with the
  reactive data view on a secondary chat_nav_panel().
- Docs: build.qmd and build.Rmd gain a 'chat-first page' section and
  present .page() as the happy path alongside .sidebar()/.ui().
- Tests: unit tests for both packages (rendered IDs, class merging,
  page-owned arg rejection, Express footer merge) and playwright smoke
  tests for the new examples.
- _chat_ui_defaults() centralizes the enable_cancel/allow_attachments
  defaults previously repeated in mod_ui, mod_page, and the Express page()
- QueryChatExpress.page() now reuses _merge_querychat_class() instead of
  inlining the class merge
- _page_extras() centralizes the head-content + viz-preload TagList shared
  by mod_page and mod_page_extras
- Clarify Express page() return-value docs (don't assign or wrap it)
…chat

mod_server() always constructs its shinychat.Chat with a client=, and
shinychat auto-enables cancel and attachments at session start in that
case (as long as the attributes aren't explicitly set on the chat UI).
Dropping the setdefault() calls removes the duplication across mod_ui,
mod_page, and the Express page() and keeps shinychat as the single
source of truth for these defaults. User-supplied values are still
forwarded verbatim and take precedence over the auto-enable.
The Express page_chat() returns the chat root itself, so the class can
go on it directly (matching the mod_ui() idiom) instead of being merged
into kwargs. Core page_chat() returns the page shell, so _merge_querychat_class()
remains necessary there to reach the chat root through kwargs.
All three UI entry points (mod_ui, mod_page, Express page()) now use
_merge_querychat_class() instead of a mix of add_class() and kwargs
merging. The kwargs channel is the only one that works everywhere, since
core page_chat() never exposes the chat root for post-hoc add_class().
This also brings Python into parity with the R package, which merges the
class into dots in both mod_ui() and $page().
Main module functions (mod_ui, mod_page, mod_page_extras, mod_server,
restore_viz_widgets) now appear first, followed by public data types
(ServerValues, TableState, VizWidgetEntry, GreetWarning), then private
helpers in descending level of abstraction. Pure move; no content
changes.
Within the section of _shiny_module.py touched by this PR, the main
module functions now appear before the private helpers they call,
with helpers ordered high- to low-level (_page_extras ->
_querychat_head_content -> _merge_querychat_class).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant