Skip to content

Commit 673e863

Browse files
authored
feat: simplify styles, give querychat components classes (#68)
* feat: simplify styles, give querychat components classes * docs: Update changelog/news
1 parent 60458b3 commit 673e863

File tree

12 files changed

+85
-158
lines changed

12 files changed

+85
-158
lines changed

pkg-py/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717

1818
If `client` is not provided, querychat will use the `QUERYCHAT_CLIENT` environment variable, which should be a provider-model string. If the envvar is not set, querychat uses OpenAI with the default model from `chatlas.ChatOpenAI()`.
1919

20+
* `querychat.ui()` now adds a `.querychat` class to the chat container and `querychat.sidebar()` adds a `.querychat-sidebar` class to the sidebar, allowing for easier customization via CSS. (#68)
2021

2122
## [0.1.0] - 2025-05-24
2223

pkg-py/examples/app-database-sqlite.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def use_github_models(system_prompt: str) -> chatlas.Chat:
3434
"titanic",
3535
greeting=greeting,
3636
data_description=data_desc,
37-
create_chat_callback=use_github_models,
37+
client=use_github_models,
3838
)
3939

4040
# Create UI
@@ -48,6 +48,7 @@ def use_github_models(system_prompt: str) -> chatlas.Chat:
4848
),
4949
title="querychat with Python (SQLite)",
5050
fillable=True,
51+
class_="bslib-page-dashboard",
5152
)
5253

5354

pkg-py/examples/app-dataframe-pandas.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def use_github_models(system_prompt: str) -> chatlas.Chat:
2525
"titanic",
2626
greeting=greeting,
2727
data_description=data_desc,
28-
create_chat_callback=use_github_models,
28+
client=use_github_models,
2929
)
3030

3131
# Create UI
@@ -39,6 +39,7 @@ def use_github_models(system_prompt: str) -> chatlas.Chat:
3939
),
4040
title="querychat with Python",
4141
fillable=True,
42+
class_="bslib-page-dashboard",
4243
)
4344

4445

pkg-py/examples/app.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def use_github_models(system_prompt: str) -> chatlas.Chat:
2323
querychat_config = qc.init(
2424
data_source=titanic,
2525
table_name="titanic",
26-
create_chat_callback=use_github_models,
26+
client=use_github_models,
2727
)
2828

2929
# Create UI
@@ -32,7 +32,13 @@ def use_github_models(system_prompt: str) -> chatlas.Chat:
3232
# Alternatively, use qc.ui(id) elsewhere if you don't want your
3333
# chat interface to live in a sidebar.
3434
qc.sidebar("chat"),
35-
ui.output_data_frame("data_table"),
35+
ui.card(
36+
ui.card_header("Titanic Data"),
37+
ui.output_data_frame("data_table"),
38+
fill=True,
39+
),
40+
fillable=True,
41+
class_="bslib-page-dashboard"
3642
)
3743

3844

@@ -49,4 +55,4 @@ def data_table():
4955

5056

5157
# Create Shiny app
52-
app = App(app_ui, server)
58+
app = App(app_ui, server)

pkg-py/src/querychat/querychat.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -458,9 +458,7 @@ def mod_ui() -> ui.TagList:
458458

459459
return ui.TagList(
460460
ui.include_css(css_path),
461-
# Chat interface goes here - placeholder for now
462-
# This would need to be replaced with actual chat UI components
463-
ui.chat_ui("chat"),
461+
ui.chat_ui("chat", class_="querychat"),
464462
)
465463

466464

@@ -494,6 +492,7 @@ def sidebar(
494492
mod_ui(id),
495493
width=width,
496494
height=height,
495+
class_="querychat-sidebar",
497496
**kwargs,
498497
)
499498

Lines changed: 9 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,15 @@
1-
:root {
2-
--bslib-sidebar-main-bg: #f8f8f8;
3-
}
4-
5-
.querychat-container {
6-
display: flex;
7-
flex-direction: column;
8-
height: 100%;
9-
width: 100%;
10-
}
11-
12-
.querychat-messages {
13-
flex: 1;
14-
overflow-y: auto;
15-
padding: 10px;
16-
display: flex;
17-
flex-direction: column;
18-
}
19-
20-
.querychat-input-container {
21-
display: flex;
22-
padding: 10px;
23-
border-top: 1px solid #ccc;
24-
}
25-
26-
.querychat-input {
27-
flex: 1;
28-
padding: 8px;
29-
border: 1px solid #ccc;
30-
border-radius: 4px;
31-
resize: none;
32-
min-height: 40px;
33-
margin-right: 8px;
34-
}
35-
36-
.querychat-send-button {
37-
padding: 8px 16px;
38-
background-color: #0d6efd;
39-
color: white;
40-
border: none;
41-
border-radius: 4px;
42-
cursor: pointer;
43-
}
44-
45-
.querychat-send-button:hover {
46-
background-color: #0a58ca;
47-
}
48-
49-
.querychat-message {
50-
max-width: 85%;
51-
padding: 8px 12px;
52-
margin-bottom: 8px;
53-
border-radius: 8px;
54-
word-wrap: break-word;
55-
}
56-
57-
.querychat-user-message {
58-
align-self: flex-end;
59-
background-color: #0d6efd;
60-
color: white;
61-
}
62-
63-
.querychat-assistant-message {
64-
align-self: flex-start;
65-
background-color: #e9ecef;
66-
}
67-
68-
.querychat-message table {
69-
width: 100%;
70-
border-collapse: collapse;
71-
margin: 10px 0;
72-
}
73-
74-
.querychat-message table td,
75-
.querychat-message table th {
76-
border: 1px solid #ccc;
1+
.querychat shiny-chat-message table td,
2+
.querychat shiny-chat-message table th {
3+
border: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color);
774
padding: 3px;
785
}
796

80-
.querychat-message table th {
81-
background-color: #f0f0f0;
7+
.querychat shiny-chat-message table td {
8+
font-family: var(--bs-font-monospace);
829
}
8310

84-
.querychat-message pre {
85-
background-color: #f4f4f4;
86-
padding: 8px;
87-
border-radius: 4px;
88-
overflow-x: auto;
11+
/* querychat takes up the full sidebar, so move the collapse toggle out of the way */
12+
.bslib-sidebar-layout:has(.querychat-sidebar):not(.sidebar-collapsed)>.collapse-toggle {
13+
right: 4px;
14+
top: 4px;
8915
}
90-
91-
.querychat-message code {
92-
font-family: monospace;
93-
}

pkg-r/NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,5 @@
2323
* querychat now requires `ellmer` version 0.3.0 or later and uses rich tool cards for dashboard updates and database queries. (#65)
2424

2525
* New `querychat_app()` function lets you quickly launch a Shiny app with a querychat chat interface. (#66)
26+
27+
* `querychat_ui()` now adds a `.querychat` class to the chat container and `querychat_sidebar()` adds a `.querychat-sidebar` class to the sidebar, allowing for easier customization via CSS. (#68)

pkg-r/R/querychat.R

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,20 @@
33
#' This will perform one-time initialization that can then be shared by all
44
#' Shiny sessions in the R process.
55
#'
6-
#' @param data_source A querychat_data_source object created by `querychat_data_source()`.
6+
#' @param data_source A querychat_data_source object created by
7+
#' `querychat_data_source()`.
8+
#'
79
#' To create a data source:
810
#' - For data frame: `querychat_data_source(df, tbl_name = "my_table")`
911
#' - For database: `querychat_data_source(conn, "table_name")`
1012
#' @param greeting A string in Markdown format, containing the initial message
1113
#' to display to the user upon first loading the chatbot. If not provided, the
1214
#' LLM will be invoked at the start of the conversation to generate one.
13-
#' @param data_description A string containing a data description for the chat model. We have found
14-
#' that formatting the data description as a markdown bulleted list works best.
15-
#' @param extra_instructions A string containing extra instructions for the chat model.
15+
#' @param data_description A string containing a data description for the chat
16+
#' model. We have found that formatting the data description as a markdown
17+
#' bulleted list works best.
18+
#' @param extra_instructions A string containing extra instructions for the
19+
#' chat model.
1620
#' @param client An `ellmer::Chat` object, a string to be passed to
1721
#' [ellmer::chat()] describing the model to use (e.g. `"openai/gpt-4o"`), or a
1822
#' function that creates a chat client. When using a function, the function
@@ -26,11 +30,11 @@
2630
#' using [ellmer::chat_openai()].
2731
#' @param create_chat_func `r lifecycle::badge('deprecated')`. Use the `client`
2832
#' argument instead.
29-
#' @param system_prompt A string containing the system prompt for the chat model.
30-
#' The default generates a generic prompt, which you can enhance via the `data_description` and
31-
#' `extra_instructions` arguments.
32-
#' @param auto_close_data_source Should the data source connection be automatically
33-
#' closed when the shiny app stops? Defaults to TRUE.
33+
#' @param system_prompt A string containing the system prompt for the chat
34+
#' model. The default generates a generic prompt, which you can enhance via
35+
#' the `data_description` and `extra_instructions` arguments.
36+
#' @param auto_close_data_source Should the data source connection be
37+
#' automatically closed when the shiny app stops? Defaults to TRUE.
3438
#'
3539
#' @returns An object that can be passed to `querychat_server()` as the
3640
#' `querychat_config` argument. By convention, this object should be named
@@ -124,14 +128,15 @@ querychat_init <- function(
124128
#' UI components for querychat
125129
#'
126130
#' These functions create UI components for the querychat interface.
127-
#' `querychat_ui` creates a basic chat interface, while `querychat_sidebar`
128-
#' wraps the chat interface in a `bslib::sidebar` component designed to be used
129-
#' as the `sidebar` argument to `bslib::page_sidebar`.
131+
#' `querychat_ui()` creates a basic chat interface, while `querychat_sidebar()`
132+
#' wraps the chat interface in a [bslib::sidebar()] component designed to be
133+
#' used as the `sidebar` argument to [bslib::page_sidebar()].
130134
#'
131135
#' @param id The ID of the module instance.
132-
#' @param width The width of the sidebar (when using `querychat_sidebar`).
133-
#' @param height The height of the sidebar (when using `querychat_sidebar`).
134-
#' @param ... Additional arguments passed to `bslib::sidebar` (when using `querychat_sidebar`).
136+
#' @param width,height In `querychat_sidebar()`: the width and height of the
137+
#' sidebar.
138+
#' @param ... In `querychat_sidebar()`: additional arguments passed to
139+
#' [bslib::sidebar()].
135140
#'
136141
#' @return A UI object that can be embedded in a Shiny app.
137142
#'
@@ -141,8 +146,10 @@ querychat_sidebar <- function(id, width = 400, height = "100%", ...) {
141146
bslib::sidebar(
142147
width = width,
143148
height = height,
149+
class = "querychat-sidebar",
144150
...,
145-
querychat_ui(id) # purposely NOT using ns() here, we're just a passthrough
151+
# purposely NOT using ns() for `id`, we're just a passthrough
152+
querychat_ui(id)
146153
)
147154
}
148155

@@ -159,7 +166,12 @@ querychat_ui <- function(id) {
159166
script = "querychat.js",
160167
stylesheet = "styles.css"
161168
),
162-
shinychat::chat_ui(ns("chat"), height = "100%", fill = TRUE)
169+
shinychat::chat_ui(
170+
ns("chat"),
171+
height = "100%",
172+
fill = TRUE,
173+
class = "querychat"
174+
)
163175
)
164176
}
165177

pkg-r/R/querychat_app.R

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ querychat_app <- function(config, ..., bookmark_store = "url") {
4444
config$data_source$table_name,
4545
"</code></span>"
4646
)),
47+
class = "bslib-page-dashboard",
4748
sidebar = querychat_sidebar("chat"),
4849
bslib::card(
4950
fill = FALSE,
@@ -130,7 +131,7 @@ querychat_app <- function(config, ..., bookmark_store = "url") {
130131
})
131132
}
132133

133-
app <- shiny::shinyApp(ui, server, ..., enableBookmarking = bookmark_store)
134+
app <- shiny::shinyApp(ui, server, enableBookmarking = bookmark_store)
134135
tryCatch(shiny::runGadget(app), interrupt = function(cnd) NULL)
135136
invisible(chat)
136137
}

pkg-r/inst/htmldep/styles.css

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,15 @@
1-
:root {
2-
--bslib-sidebar-main-bg: #f8f8f8;
3-
}
4-
5-
.popover {
6-
--bs-popover-header-bg: #222;
7-
--bs-popover-header-color: #fff;
8-
}
9-
10-
.popover .btn-close {
11-
filter: var(--bs-btn-close-white-filter);
12-
}
13-
shiny-chat-message table td,
14-
shiny-chat-message table th {
1+
.querychat shiny-chat-message table td,
2+
.querychat shiny-chat-message table th {
153
border: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color);
164
padding: 3px;
175
}
186

19-
shiny-chat-message table td {
7+
.querychat shiny-chat-message table td {
208
font-family: var(--bs-font-monospace);
219
}
2210

23-
#show_title:empty,
24-
#show_query:empty {
25-
/* Prevent empty title/query blocks from taking any space */
26-
border: 0;
27-
padding: 0;
28-
margin-bottom: 0;
29-
}
30-
31-
#show_title:empty,
32-
#show_query {
33-
/* We can't affect the flex parent's gap, so instead we use a negative margin
34-
to counteract it. In the case of #show_query, we don't even want the gap
35-
even when it's showing, as it results in too much space between the two. */
36-
margin-top: calc(-1 * var(--bslib-mb-spacer));
11+
/* querychat takes up the full sidebar, so move the collapse toggle out of the way */
12+
.bslib-sidebar-layout:has(.querychat-sidebar):not(.sidebar-collapsed)>.collapse-toggle {
13+
right: 4px;
14+
top: 4px;
3715
}

0 commit comments

Comments
 (0)