This PR improves the card_image() API and fixes a few minor rough edges, including fixing #1071.
Currently card_image() is by default wrapped in a card_body() container. This happens even if setting container = NULL because the card_image() result doesn't have a card_item class. This makes it impossible to use card_image() for the card image caps described in the Boostrap docs.
With this PR, we now default to container = NULL and, when this is the case, call as.card_item() on the image so that the image is treated as a card item.
I'm not sure how much value container adds -- it's easy enough to do card_body(card_image()) if that's really desired -- and I don't think there's any harm in unconditionally adding the card_item class to the image. I'd be in favor of deprecating the container argument (unless I've missed an important use case).
border_radius gains "auto", the new default value. When border_radius = "auto", we add a card_image_auto class to the card_image() output that is detected by card(). We then automatically add the card-img-top, card-img-bottom, or card-img class if the card image is the first, last or only child. In all other cases, we don't modify the image tag.
I changed the default value of card_image(fill = ) to FALSE. fill = TRUE might have worked better when card_image() was always wrapped in a card_body() but in most cases having fill = TRUE will cause the image to stretch, distorting the image. I don't think this is what most people want from card_image().
I added a bit of logic such that a URI or non-local file path can be given to file. Instead of having to write
This is backwards compatible in the sense that when a value is passed to src, that value is used directly. The advantage is that we won't even consulte file when src is provided, allowing card_image(src = "cat.png") to skip the base64 encoding.
I added alt = "" as a default argument that appears before the dots. This has the side effect of marking most card_image() uses as decorative. That's probably better than the default of not having alt text at all, and it intends to bring increased attention to alt text without breaking existing apps by making alt required. Fixes #1071
Example app
```r
library(shiny)
# library(bslib)
pkgload::load_all()
card_img <- card_image(
file = "https://picsum.photos/seed/posit/600/300"
)
ui <- page_fillable(
layout_column_wrap(
width = 300,
# advanced usage with a card image overlay
# see: https://getbootstrap.com/docs/5.3/components/card/#image-overlays
card(
class = "text-light",
card_image(
file = "https://picsum.photos/seed/posit/600/900",
# fill = TRUE,
border_radius = "all"
),
card_body(
class = "card-img-overlay",
lorem::ipsum(2)
)
),
# Typical usage: card top cap
card(
card_img,
lorem::ipsum(1),
),
# Typical usage: card bottom cap
card(
lorem::ipsum(1),
card_img,
),
# Typical usage: images for top/bottom cap, plus one in middle
card(
fill = FALSE,
card_img,
lorem::ipsum(1, 2),
card_img,
lorem::ipsum(1, 2),
card_img
)
)
)
server <- function(input, output, session) {
}
shinyApp(ui, server)
```
This PR improves the
card_image()
API and fixes a few minor rough edges, including fixing #1071.Currently
card_image()
is by default wrapped in acard_body()
container. This happens even if settingcontainer = NULL
because thecard_image()
result doesn't have acard_item
class. This makes it impossible to usecard_image()
for the card image caps described in the Boostrap docs.With this PR, we now default to
container = NULL
and, when this is the case, callas.card_item()
on theimage
so that the image is treated as a card item.I'm not sure how much value
container
adds -- it's easy enough to docard_body(card_image())
if that's really desired -- and I don't think there's any harm in unconditionally adding thecard_item
class to theimage
. I'd be in favor of deprecating thecontainer
argument (unless I've missed an important use case).border_radius
gains"auto"
, the new default value. Whenborder_radius = "auto"
, we add acard_image_auto
class to thecard_image()
output that is detected bycard()
. We then automatically add thecard-img-top
,card-img-bottom
, orcard-img
class if the card image is the first, last or only child. In all other cases, we don't modify the image tag.I changed the default value of
card_image(fill = )
toFALSE
.fill = TRUE
might have worked better whencard_image()
was always wrapped in acard_body()
but in most cases havingfill = TRUE
will cause the image to stretch, distorting the image. I don't think this is what most people want fromcard_image()
.I added a bit of logic such that a URI or non-local file path can be given to
file
. Instead of having to writeusers can just give the URL to
file
This is backwards compatible in the sense that when a value is passed to
src
, that value is used directly. The advantage is that we won't even consultefile
whensrc
is provided, allowingcard_image(src = "cat.png")
to skip the base64 encoding.I added
alt = ""
as a default argument that appears before the dots. This has the side effect of marking mostcard_image()
uses as decorative. That's probably better than the default of not having alt text at all, and it intends to bring increased attention to alt text without breaking existing apps by makingalt
required. Fixes #1071Example app
```r library(shiny) # library(bslib) pkgload::load_all() card_img <- card_image( file = "https://picsum.photos/seed/posit/600/300" ) ui <- page_fillable( layout_column_wrap( width = 300, # advanced usage with a card image overlay # see: https://getbootstrap.com/docs/5.3/components/card/#image-overlays card( class = "text-light", card_image( file = "https://picsum.photos/seed/posit/600/900", # fill = TRUE, border_radius = "all" ), card_body( class = "card-img-overlay", lorem::ipsum(2) ) ), # Typical usage: card top cap card( card_img, lorem::ipsum(1), ), # Typical usage: card bottom cap card( lorem::ipsum(1), card_img, ), # Typical usage: images for top/bottom cap, plus one in middle card( fill = FALSE, card_img, lorem::ipsum(1, 2), card_img, lorem::ipsum(1, 2), card_img ) ) ) server <- function(input, output, session) { } shinyApp(ui, server) ```