% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/chat.R
\name{chat_ui}
\alias{chat_ui}
\title{Create a chat UI element}
\usage{
chat_ui(
  id,
  ...,
  messages = NULL,
  greeting = NULL,
  placeholder = "Enter a message...",
  width = "min(680px, 100\%)",
  height = "auto",
  fill = TRUE,
  icon_assistant = NULL,
  enable_cancel = FALSE,
  footer = NULL
)
}
\arguments{
\item{id}{The ID of the chat element}

\item{...}{Extra HTML attributes to include on the chat element}

\item{messages}{A list of messages to prepopulate the chat with. Each
message can be one of the following:
\itemize{
\item A string, which is interpreted as markdown and rendered to HTML on
the client.
\itemize{
\item To prevent interpreting as markdown, mark the string as
\code{\link[htmltools:HTML]{htmltools::HTML()}}.
}
\item A UI element.
\itemize{
\item This includes \code{\link[htmltools:tagList]{htmltools::tagList()}}, which take UI elements
(including strings) as children. In this case, strings are still
interpreted as markdown as long as they're not inside HTML.
}
\item A named list of \code{content} and \code{role}. The \code{content} can contain content
as described above, and the \code{role} can be "assistant" or "user".
}}

\item{greeting}{An optional greeting to display when the chat first loads.
Can be a \code{\link[=chat_greeting]{chat_greeting()}} object, or a plain string (which is
auto-wrapped with default options). The greeting is dismissed when the
user sends their first message. For example:
\code{greeting = chat_greeting("## Hello!\\n\\nHow can I help you today?")}}

\item{placeholder}{The placeholder text for the chat's user input field}

\item{width}{The CSS width of the chat element}

\item{height}{The CSS height of the chat element}

\item{fill}{Whether the chat element should try to vertically fill its
container, if the container is
\href{https://rstudio.github.io/bslib/articles/filling/index.html}{fillable}}

\item{icon_assistant}{The icon to use for the assistant chat messages.
Can be HTML or a tag in the form of \code{\link[htmltools:HTML]{htmltools::HTML()}} or
\code{\link[htmltools:tags]{htmltools::tags()}}. If \code{None}, a default robot icon is used.}

\item{enable_cancel}{If \code{TRUE}, show a stop button during streaming that
allows the user to cancel the in-progress response. When using
\code{\link[=chat_mod_server]{chat_mod_server()}}, cancellation is wired up automatically. For manual
usage with \code{chat_ui()}, observe \verb{input$<id>_cancel} to handle cancellation
(e.g., by calling \code{ctrl$cancel()} on an ellmer \code{stream_controller()}).
Defaults to \code{FALSE}.}

\item{footer}{Optional HTML content to display below the chat input.
This can be any HTML content (tags, tag lists, or character strings).
Useful for adding disclaimers, attribution, or other information.
The footer text is styled slightly smaller and lighter than body text
by default. Customize with CSS properties \code{--shiny-chat-footer-font-size}
and \code{--shiny-chat-footer-color} on the chat container or footer element.}
}
\value{
A Shiny tag object, suitable for inclusion in a Shiny UI
}
\description{
Inserts a chat UI element into a Shiny UI, which includes a scrollable
section for displaying chat messages, and an input field for the user to
enter new messages.

To respond to user input, listen for \code{input$ID_user_input} (for example, if
\code{id="my_chat"}, user input will be at \code{input$my_chat_user_input}), and use
\code{\link[=chat_append]{chat_append()}} to append messages to the chat.
}
\section{Greeting}{


A greeting is an optional welcome message shown before any conversation
messages. It is automatically dismissed when the user sends their first
message (unless created with \code{dismissible = FALSE}).

\strong{Static greeting.} Pass a string or \code{\link[=chat_greeting]{chat_greeting()}} to the \code{greeting}
parameter:

\if{html}{\out{<div class="sourceCode r">}}\preformatted{chat_ui("chat", greeting = "## Hello!\\n\\nHow can I help you today?")
}\if{html}{\out{</div>}}

\strong{Dynamic greeting from the server.} Leave \code{greeting} unset and use
\code{\link[=chat_set_greeting]{chat_set_greeting()}} from your server function. This is useful when the
greeting depends on session state or is generated by a model.

\strong{\code{greeting_requested} input.} When the chat is visible on the page, has
no messages, and has no greeting set, Shiny fires
\verb{input$<id>_greeting_requested} (e.g. \code{input$chat_greeting_requested} for
\code{chat_ui("chat")}). The value is an event counter suitable for
\code{\link[shiny:observeEvent]{shiny::observeEvent()}}. Use it to trigger server-side greeting generation:

\if{html}{\out{<div class="sourceCode r">}}\preformatted{observeEvent(input$chat_greeting_requested, \{
  stream <- chat_client$stream_async("Generate a short welcome message.")
  chat_set_greeting("chat", chat_greeting(stream))
\})
}\if{html}{\out{</div>}}

This input fires when the chat component is first viewed on the page and
empty, and again after \code{\link[=chat_clear]{chat_clear()}} \code{(greeting = TRUE)}, enabling a
regenerate pattern where clearing the greeting automatically triggers a
fresh one.
}

\section{Thinking display}{


When a model produces reasoning or "thinking" tokens, shinychat renders them
in a collapsible panel above the response. The panel shows a live stream of
the model's reasoning while it thinks, then auto-collapses when the response
begins.

Thinking display works automatically with any model that supports it. Two
paths are supported:
\enumerate{
\item \strong{ellmer's \code{ContentThinking} objects.} Models that provide a structured
thinking API (e.g., Claude with extended thinking) emit \code{ContentThinking}
objects when you stream with \code{stream = "content"}. shinychat detects these
and routes them to the thinking panel. This is what \code{chat_append()} uses
internally when you pass it an ellmer content stream.
\item \strong{Raw \verb{<thinking>} tags.} Many open-source and local models (DeepSeek,
QwQ, Qwen, etc.) emit \verb{<thinking>...</thinking>} tags directly in their
markdown output. shinychat detects these tags during streaming and renders
the enclosed text in the thinking panel with no extra configuration.
}
\subsection{Topic labels}{

You can optionally get labeled sub-sections within the thinking panel by
asking the model to emit \verb{<topic>...</topic>} tags in its reasoning. These
are extracted and rendered as section headings inside the thinking display,
and the current topic appears in the collapsed header as a live status.

To use topic labels, add something like this to your system prompt:

\if{html}{\out{<div class="sourceCode">}}\preformatted{When thinking through a problem, wrap brief topic labels in <topic> tags
to indicate what you're currently reasoning about. For example:
<topic>parsing the input</topic>
}\if{html}{\out{</div>}}

Topic labels are entirely optional. Without them, the thinking panel still
works -- it just won't have sub-section headings.
}
}

\examples{
\dontshow{if (interactive()) withAutoprint(\{ # examplesIf}
library(shiny)
library(bslib)
library(shinychat)

ui <- page_fillable(
  chat_ui("chat", fill = TRUE)
)

server <- function(input, output, session) {
  observeEvent(input$chat_user_input, {
    # In a real app, this would call out to a chat client or API,
    # perhaps using the 'ellmer' package.
    response <- paste0(
      "You said:\n\n",
      "<blockquote>",
      htmltools::htmlEscape(input$chat_user_input),
      "</blockquote>"
    )
    chat_append("chat", response)
    chat_append("chat", stream)
  })
}

shinyApp(ui, server)
\dontshow{\}) # examplesIf}
}
