I'm building a Quarto dashboard with format: dashboard and server: shiny. I'm comparing value boxes that are:
written directly in the UI, versus created dynamically using renderUI() in the server
The UI-based value boxes appear side-by-side as expected. But the server-rendered ones appear stacked vertically, even though they're intended to share the same layout height.
Is there a known layout limitation for uiOutput() in format: dashboard? Is there a workaround that allows multiple server-rendered value boxes to appear side-by-side like those defined in the UI?
Background: I need to use renderUI()
because I'm developing a multi-language app using shiny.i18n
, and only server-side rendering allows dynamic UI elements like value_box()
to update correctly when the language is changed.
Here is MRE:
---
title: "Value Box Layout Comparison"
format:
dashboard:
orientation: columns
page-navigation: true
page-navigation-id: site_nav
server: shiny
---
```{r}
#| context: setup
library(shiny)
library(bslib)
```
## Sidebar {.sidebar}
Nothing here — just a comparison between UI and server-based value boxes.
## Value Boxes directly in UI
### Three value boxes side-by-side {height="40%"}
```{r}
value_box(
title = "Box UI 1",
value = 42,
theme = "primary"
)
value_box(
title = "Box UI 2",
value = 58,
theme = "primary"
)
value_box(
title = "Box UI 3",
value = 68,
theme = "primary"
)
```
### Three value boxes side-by-side {height="60%"}
```{r}
#| component: input
#| title: Just space
cat("Just space")
```
## Value Boxes rendered from server
### Three value boxes via `renderUI()` {height="40%"}
```{r}
#| title: Value Boxes rendered from server
uiOutput("box_server_1")
uiOutput("box_server_2")
uiOutput("box_server_3")
```
### Three value boxes side-by-side {height="60%"}
```{r}
#| component: input
#| title: Just space
cat("Just space")
```
```{r}
#| context: server
output$box_server_1 <- renderUI({
value_box(
title = "Box Server 1",
value = 123,
theme = "danger"
)
})
output$box_server_2 <- renderUI({
value_box(
title = "Box Server 2",
value = 321,
theme = "danger"
)
})
output$box_server_3 <- renderUI({
value_box(
title = "Box Server 3",
value = 456,
theme = "danger"
)
})
```
Desired output:
The blue value boxes with renderUI
. Many thanks.
Shiny does not automatically arrange the elements inside a grid. To do this, you can use bslib's layout_column_wrap()
:
layout_column_wrap(
width = 1/3,
uiOutput("box_server_1"),
uiOutput("box_server_2"),
uiOutput("box_server_3"),
)
However, this seems to let the title of the card disappear. You can keep if it you define the card explicitly:
::: {.card title="Value Boxes rendered from server"}
```{r}
layout_column_wrap(
width = 1/3,
uiOutput("box_server_1"),
uiOutput("box_server_2"),
uiOutput("box_server_3"),
)
```
:::