shinychat 0.5 and bslib 0.12 offcanvas pick up the same iOS 27
defaults as the rest of a glass app: refraction, morph, press, and the
scroll edge. Pass theme = glass_theme() to
page_chat(). An embedded chat_ui() inside any
glass page uses the same CSS.
library(shiny)
library(bslib)
library(shinyglass)
library(shinychat)
ui <- page_chat(
"Glass notes",
id = "chat",
theme = glass_theme(),
placeholder = "Message",
sidebar = chat_sidebar(history = TRUE, open = "always"),
toolbar = toolbar(
toolbar_input_button("open_sources", "Sources")
)
)The header, history sidebar, and drawer are glass chrome. User
bubbles are tinted pills. The composer is a floating pill, like the iOS
27 Messages bar, and grows a fade when the transcript sits underneath
it. Thinking rows, tool cards, citation chips
(<shiny-aside>), attachment and text previews,
toolbars, and the slash-command menu use the menu surface so they stay
readable on the wallpaper.
offcanvas() panels use the same material. They still
slide with Bootstrap’s transform. A separate scale grows the panel from
the trigger when morph is on. Scrolling the panel body fades the header.
Reduced motion skips that scale. Reduced transparency, increased
contrast, and forced colors turn the lens off, as they do for other
chrome.
observeEvent(input$open_sources, {
show_offcanvas(offcanvas(
id = "sources_panel",
title = "Sources",
placement = "end",
"Citations stay in this panel."
))
})Harbor notes is a core demo, with the dusk wallpaper behind the glass. The hosted app is Harbor notes. It answers with Gemini Flash and falls back to the local script if the API errors.
With no API key the reply is a local script. It streams a thinking
panel, a short answer, a citation chip, and a tide-table tool card.
GEMINI_API_KEY (or GOOGLE_API_KEY) switches
that session to ellmer::chat_google_gemini() with
gemini-3.5-flash-lite, falling back to
gemini-3.8-flash and gemini-3.7-flash
(SHINYGLASS_CHAT_MODEL is tried first when set). Live
replies stay focused on shinyglass, Shiny, R, and ordinary conversation,
and decline only a clearly unrelated or abusive request. A small chip
reads Live (Gemini) or Demo replies. A public session allows 8 messages
of at most 400 characters. If the API errors or returns a quota response
(429), a glass notice explains the fallback and the local script
continues. The key is never written to the log or the page. The theme
choice and the conversation are kept in the browser’s local storage,
which is what “Notes stay on this machine” refers to. The shinychat
history store stays in memory, so nothing is written to the server disk
and no model is asked for a title. The sidebar starts open on desktop
and collapses into the page menu on a phone.