Skip to content

Conversation

@elnelson575
Copy link

@elnelson575 elnelson575 commented Nov 6, 2025

This PR makes card headers flex by default, with equivalent settings to .hstack.

This makes it much easier to organize complex inputs in headers with vanilla formatting or using other spacing utils to control how the items are spaced within the header.

We are not adding this to footers because it seems like footers are more likely to be longer blocks of text, like figure captions, footnotes, etc.

Minor breakage is possible for people currently expecting vertically stacked inputs in headers, however based on a quick survey of publicly available code on GitHub, this seems to be a very, very small population.

An example with a few inputs in a header:

library(shiny)
library(bslib)

ui <- page_fillable(
    tags$head(
        tags$link(rel = "stylesheet", type = "text/css", href = "styles.css")
    ),
    card(
        card_header(
            icon("star"),
            "Card 1 header",
            actionButton("go", "Go", class = "btn-sm"),
            actionButton("edit", "Edit", class = "btn-sm"),
            checkboxInput("checkbox", "Checkbox", value = FALSE),
        ),
        p("Card 1 body"),
        sliderInput("slider", "Slider", 0, 10, 5),
        max_height = "500px",
        card_footer(
            p(
                "lots of text here, texting text, real text that makes you think, text that texts, but doesn't text
            because it does not possess fingers, text that sits on the page and doesn't really do more than that,
            text that thwarts autocomplete because it is unexpected. Text."
            )
        ),
    )
)

server <- function(input, output) {}


shinyApp(ui = ui, server = server)
Screenshot 2025-11-06 at 1 30 15 PM

An example with ms-auto pushing the second part of the header to the far right:

library(shiny)
library(bslib)

ui <- page_fillable(
    tags$head(
        tags$link(rel = "stylesheet", type = "text/css", href = "styles.css")
    ),
    card(
        card_header(
            icon("star"),
            "Card 1 header",
            actionButton("go", "Go", class = "ms-auto btn-sm border-0"),
        ),
        p("Card 1 body"),
        sliderInput("slider", "Slider", 0, 10, 5),
        max_height = "500px",
        card_footer(
            p(
                "lots of text here, texting text, real text that makes you think, text that texts, but doesn't text
            because it does not possess fingers, text that sits on the page and doesn't really do more than that,
            text that thwarts autocomplete because it is unexpected. Text."
            )
        ),
    )
)

server <- function(input, output) {}
shinyApp(ui = ui, server = server)

Screenshot 2025-11-06 at 1 26 17 PM

@elnelson575 elnelson575 self-assigned this Nov 6, 2025
@elnelson575 elnelson575 requested a review from gadenbuie November 6, 2025 18:40
@elnelson575 elnelson575 marked this pull request as ready for review November 6, 2025 18:40
@gadenbuie
Copy link
Member

gadenbuie commented Nov 6, 2025

.bslib-gap-spacing primarily serves to remove margin-bottom as the primary way to space out elements, i.e. we're in a context where gap controls spacing.

.bslib-gap-spacing {
gap: var(--bslib-mb-spacer);
&,
& > .shiny-html-output,
& > .shiny-panel-conditional {
> .bslib-mb-spacing, > .form-group, > p, > pre {
margin-bottom: 0;
}
}
}

@gadenbuie gadenbuie changed the base branch from feat/toolbar-epic to main November 6, 2025 20:13
Copy link
Member

@gadenbuie gadenbuie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All good to merge once the last couple details are handled

@gadenbuie gadenbuie mentioned this pull request Nov 6, 2025
elnelson575 and others added 2 commits November 7, 2025 11:01
Co-authored-by: Garrick Aden-Buie <[email protected]>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh this is interesting! These snapshots are generated in the navset docs, specifically in man/fragments/ex-navset_tab.Rmd which end up at https://rstudio.github.io/bslib/reference/navset.html#navset-card-tab-

This change indicates that we'll need to review navset_card_tab() and we will likely end up needing to adjust the CSS rules for navset cards. Can you look into this?

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.

Make card_header() display flex (equivalent to .hstack) by default

3 participants