Card
is a box of related content usually describing a single object. It can be composed of several subcomponents, we give full overview of those subcomponents below.
Card
supports vertical
and horizontal
orientation which is controlled by CardContext
, see examples below.
This component uses a Card
from react-bootstrap as a base component and extends it with additional subcomponents. See React-Bootstrap for additional documentation.
Basic Usage#
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const isExtraSmall = useMediaQuery ( { maxWidth : breakpoints . extraSmall . maxWidth } ) ;
return (
< Card style = { { width : isExtraSmall ? "100%" : "18rem" } } >
< Card.ImageCap
src = " https://picsum.photos/360/200/ "
srcAlt = " Card image "
/>
< Card.Header
title = " Card Title "
/>
< Card.Section >
This is a card section. It can contain anything but usually text, a list, or list of links. Multiple sections have a card divider between them.
</ Card.Section >
< Card.Footer >
< Button > Action 1 </ Button >
</ Card.Footer >
</ Card >
) }
Card variants# Use variant
prop to use Card
specific style variant.
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const [ cardVariant , setCardVariant ] = useState ( 'light' ) ;
const isExtraSmall = useMediaQuery ( { maxWidth : breakpoints . extraSmall . maxWidth } ) ;
return (
< >
{ }
< ExamplePropsForm
inputs = { [
{ value : cardVariant , setValue : setCardVariant , options : [ 'light' , 'dark' , 'muted' ] , name : 'variant' } ,
] }
/>
{ }
< Card style = { { width : isExtraSmall ? "100%" : "18rem" } } variant = { cardVariant } >
< Card.ImageCap
src = " https://picsum.photos/360/200/ "
srcAlt = " Card image "
/>
< Card.Header title = " Card Title " />
< Card.Section >
This is a card section. It can contain anything but usually text, a list, or list of links. Multiple sections have a card divider between them.
</ Card.Section >
< Card.Footer textElement = " Course " >
< Button
variant = { cardVariant === 'dark' ? 'inverse-primary' : 'primary' }
>
Action
</ Button >
</ Card.Footer >
</ Card >
</ >
) }
Clickable card# You use isClickable
prop to add additional hover
and focus
styling to the Card
.
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const isExtraSmall = useMediaQuery ( { maxWidth : breakpoints . extraSmall . maxWidth } ) ;
return (
< Card style = { { width : isExtraSmall ? "100%" : "18rem" } } isClickable >
< Card.ImageCap
src = " https://picsum.photos/360/200/ "
srcAlt = " Card image "
/>
< Card.Header
title = " Card Title "
/>
< Card.Section >
This is a card section. It can contain anything but usually text, a list, or list of links. Multiple sections have a card divider between them.
</ Card.Section >
< Card.Footer >
< Button > Action 1 </ Button >
</ Card.Footer >
</ Card >
) } ;
As link# You can also use Card
as a link by passing the value HyperLink
(or a
, Link
) to the as
property, note that
Card
will override the default link styling to make its content appear as regular text.
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const isExtraSmall = useMediaQuery ( { maxWidth : breakpoints . extraSmall . maxWidth } ) ;
return (
< Card
as = { Hyperlink }
destination = " https://www.edx.org "
style = { { width : isExtraSmall ? "100%" : "18rem" } }
isClickable
>
< Card.ImageCap
src = " https://picsum.photos/360/200/ "
srcAlt = " Card image "
/>
< Card.Header title = " Card Title " />
< Card.Section >
This is a card section. It can contain anything but usually text, a list, or list of links.
Multiple sections have a card divider between them.
</ Card.Section >
< Card.Footer >
< Button > Action 1 </ Button >
</ Card.Footer >
</ Card >
) }
You may add a header by adding a Card.Header
component.
This header displays a title, subtitle, and may contain actions.
Show editable code example Any Paragon component or export may be added to the code example.
< div >
< Card className = " mb-2 " >
< Card.Header title = " Title " />
</ Card >
< Card >
< Card.Header
title = " Title "
subtitle = " Subtitle "
/>
</ Card >
</ div >
Actions# The Card.Header
supports custom actions via the actions prop and renders them on the top right of the header.
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const isExtraSmall = useMediaQuery ( { maxWidth : breakpoints . extraSmall . maxWidth } ) ;
return (
< div >
< Card className = " mb-2 " >
< Card.Header
title = " Title "
subtitle = " Subtitle "
isStacked = { ! ! isExtraSmall }
actions = {
< ActionRow
isStacked = { ! ! isExtraSmall }
style = { { marginBottom : isExtraSmall ? ".5rem" : 0 } }
>
< Button variant = " tertiary " > Action 1 </ Button >
< Button > Action 2 </ Button >
</ ActionRow >
}
/>
</ Card >
< Card >
< Card.Header
title = " Title "
subtitle = " Subtitle "
actions = {
< Dropdown >
< Dropdown.Toggle
id = " dropdown-toggle-with-iconbutton "
as = { IconButton }
src = { MoreVert }
iconAs = { Icon }
variant = " primary "
alt = " Actions dropdown "
/>
< Dropdown.Menu >
< Dropdown.Item href = " #/action-1 " > Action </ Dropdown.Item >
< Dropdown.Item href = " #/action-2 " > Another action </ Dropdown.Item >
< Dropdown.Item href = " #/action-3 " > Something else </ Dropdown.Item >
</ Dropdown.Menu >
</ Dropdown >
}
/>
</ Card >
</ div >
) }
Sizes# The Card.Header
supports two size variants, "sm"
and "md"
.
Add size="sm"
for smaller header content and actions.
Show editable code example Any Paragon component or export may be added to the code example.
< Card >
< Card.Header
title = " Title "
subtitle = " Subtitle "
actions = {
< ActionRow >
< Button > Action </ Button >
</ ActionRow >
}
size = " sm "
/>
</ Card >
Section# Card.Section
is the main block to display card content. Can include its own title and actions separate from other card components. Multiple sections have a Card.Divider
between them.
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const isExtraSmall = useMediaQuery ( { maxWidth : breakpoints . extraSmall . maxWidth } ) ;
return (
< Card >
< Card.Section
title = " Section title "
actions = {
< ActionRow isStacked = { ! ! isExtraSmall } >
< Button > Action 1 </ Button >
< Button > Action 2 </ Button >
</ ActionRow >
}
>
This is a card section. It can contain anything but usually text, a list, or list of links. Multiple sections have a card divider between them.
</ Card.Section >
< Card.Divider />
< Card.Section
title = " Section "
actions = {
< ActionRow isStacked = { ! ! isExtraSmall } >
< Button > Action 1 </ Button >
< Button > Action 2 </ Button >
</ ActionRow >
}
>
This is another section variant.
</ Card.Section >
< Card.Divider />
< Card.Section >
This is a section without title or actions, just content.
</ Card.Section >
</ Card >
) }
Card.Footer
is the bottom part of the card. Usually used to outline actions that can be taken on the card object.
Note that Card.Footer
has a separate orientation
prop which will override the value from CardContext
, this was implemented because there are some use cases where you would want to display Card
with horizontal orientation containing footer with vertical orientation.
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const footerLink = < a href = ' #link ' > Footer text as a link </ a > ;
const isExtraSmall = useMediaQuery ( { maxWidth : breakpoints . extraSmall . maxWidth } ) ;
return (
< >
< Card >
< Card.Footer orientation = { isExtraSmall ? "horizontal" : "vertical" } >
< Button > Action 1 </ Button >
< Button > Action 2 </ Button >
</ Card.Footer >
< Card.Divider />
< Card.Footer
orientation = { isExtraSmall ? "horizontal" : "vertical" }
textElement = " Optional footer text to display "
>
< Button > Action 1 </ Button >
< Button > Action 2 </ Button >
</ Card.Footer >
< Card.Divider />
< Card.Footer
orientation = { isExtraSmall ? "horizontal" : "vertical" }
textElement = { footerLink }
>
< Button > Action 1 </ Button >
< Button > Action 2 </ Button >
</ Card.Footer >
</ Card >
< Card style = { { width : isExtraSmall ? "100%" : "40%" } } >
< Card.Footer textElement = " Stacked vertical variant " isStacked >
< Button > Action 1 </ Button >
< Button > Action 2 </ Button >
</ Card.Footer >
</ Card >
</ >
)
}
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const isExtraSmall = useMediaQuery ( { maxWidth : breakpoints . small . maxWidth } ) ;
return (
< Card style = { { width : isExtraSmall ? "100%" : "40%" } } >
< Card.Footer orientation = " horizontal " >
< Button > Action 1 </ Button >
< Button > Action 2 </ Button >
</ Card.Footer >
< Card.Divider />
< Card.Footer orientation = " horizontal " textElement = " Optional footer text to display " >
< Button > Action 1 </ Button >
< Button > Action 2 </ Button >
</ Card.Footer >
< Card.Divider />
< Card.Footer orientation = " horizontal " textElement = " Horizontal stacked variant " isStacked >
< Button > Action 1 </ Button >
< Button > Action 2 </ Button >
</ Card.Footer >
</ Card >
) }
With Image Cap# ImageCap
is an image that sits on the top or the left edge of a Card
. Can contain an optional logo image.
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const isExtraSmall = useMediaQuery ( { maxWidth : breakpoints . small . maxWidth } ) ;
return (
< Card style = { { width : isExtraSmall ? "100%" : "40%" } } >
< Card.ImageCap
src = " https://picsum.photos/360/200/ "
srcAlt = " Card image "
logoSrc = " https://via.placeholder.com/150 "
logoAlt = " Card logo "
/>
< Card.Header
title = " Title "
subtitle = " Subtitle "
/>
< Card.Section
title = " Section title "
>
This is a card section. It can contain anything but usually text, a list, or list of links. Multiple sections have a card divider between them.
</ Card.Section >
< Card.Footer >
< Button > Action 1 </ Button >
</ Card.Footer >
</ Card >
) }
Horizontal variant# When using horizontal variant Paragon provides additional component Card.Body
which acts as a wrapper for content you want to display between ImageCap
and Footer
. Use it if content contains multiple components.
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const isSmall = useMediaQuery ( { maxWidth : breakpoints . small . maxWidth } ) ;
const isExtraSmall = useMediaQuery ( { maxWidth : breakpoints . extraSmall . maxWidth } ) ;
return (
< >
< Card
className = " mb-4 "
orientation = { isSmall ? "vertical" : "horizontal" }
>
< Card.ImageCap
src = " https://picsum.photos/360/200/ "
srcAlt = " Card image "
logoSrc = " https://via.placeholder.com/150 "
logoAlt = " Card logo "
/>
< Card.Body >
< Card.Header
title = " Title "
subtitle = " Subtitle "
/>
< Card.Section
title = " Section title "
>
Here we want to display both Header and Section between ImageCap and Footer components, so we use Card.
Body to accomplish that.
</ Card.Section >
</ Card.Body >
< Card.Footer orientation = { isExtraSmall ? "horizontal" : "vertical" } >
< Button > Action 1 </ Button >
< Button > Action 2 </ Button >
</ Card.Footer >
</ Card >
< Card className = " mb-4 " orientation = { isSmall ? "vertical" : "horizontal" } >
< Card.ImageCap
src = " https://picsum.photos/360/200/ "
srcAlt = " Card image "
logoSrc = " https://via.placeholder.com/150 "
logoAlt = " Card logo "
/>
< Card.Section
title = " Section title "
>
In this Card we only want to display Section, therefore no need to use Card.Body wrapper.
</ Card.Section >
< Card.Footer orientation = { isExtraSmall ? "horizontal" : "vertical" } >
< Button > Action 1 </ Button >
< Button > Action 2 </ Button >
</ Card.Footer >
</ Card >
< Card orientation = { isSmall ? "vertical" : "horizontal" } >
< Card.ImageCap
src = " https://picsum.photos/360/200/ "
srcAlt = " Card image "
logoSrc = " https://via.placeholder.com/150 "
logoAlt = " Card logo "
/>
< Card.Body >
< Card.Header
title = " Title "
/>
< Card.Section
title = " Section title "
>
This is a special case where we want to have Footer with vertical orientation in the Card with horizontal orientation.
</ Card.Section >
< Card.Footer orientation = { isExtraSmall ? "horizontal" : "vertical" } textElement = " Some footer text " >
< Button > Action 1 </ Button >
< Button > Action 2 </ Button >
</ Card.Footer >
</ Card.Body >
</ Card >
</ >
) }
Card status# Note that in the example below, the content of Card
is wrapped inside Card.Body
. The d-flex
class is added for the horizontal
orientation to achieve horizontal variant. The flex-column
class is added for the main Card
component.
An optional actions
prop may be passed to include call-to-action button(s).
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const [ orientation , setOrientation ] = useState ( 'vertical' ) ;
const [ variant , setVariant ] = useState ( 'warning' ) ;
const [ showCardStatusActions , setCardStatusActions ] = useState ( 'false' ) ;
const isVertical = orientation === 'vertical' ;
const cardBodyByOrientation = {
vertical : (
< >
< Card.ImageCap
src = " https://picsum.photos/360/200/ "
srcAlt = " Card image "
logoSrc = " https://via.placeholder.com/150 "
logoAlt = " Card logo "
/>
< Card.Header title = " Card title " />
< Card.Section >
This is a wider card with supporting text below as a natural lead-in to
additional content. This card has even longer content than the first to
show that equal height action.
</ Card.Section >
</ >
) ,
horizontal : (
< div className = " d-flex " >
< Card.ImageCap
src = " https://picsum.photos/360/200/ "
srcAlt = " Card image "
logoSrc = " https://via.placeholder.com/150 "
logoAlt = " Card logo "
/>
< Card.Body >
< Card.Header title = " Card title " />
< Card.Section >
This is a wider card with supporting text below as a natural lead-in to
additional content. This card has even longer content than the first to
show that equal height action.
</ Card.Section >
</ Card.Body >
</ div >
) ,
} ;
return (
< >
{ }
< ExamplePropsForm
inputs = { [
{ value : orientation , setValue : setOrientation , options : [ 'horizontal' , 'vertical' ] , name : 'orientation' } ,
{ value : variant , setValue : setVariant , options : [ 'primary' , 'warning' , 'danger' , 'success' ] , name : 'status-variant' } ,
{ value : showCardStatusActions , setValue : setCardStatusActions , options : [ 'true' , 'false' ] , name : 'card-status-actions' } ,
] }
/>
{ }
< CardGrid
columnSizes = { {
xs : 12 ,
lg : isVertical ? 6 : 12 ,
} }
>
< Card
orientation = { orientation }
className = { classNames ( { 'flex-column' : ! isVertical } ) }
>
{ cardBodyByOrientation [ orientation ] }
<Card.Status
icon= { Warning }
variant= { variant }
actions= { ( ( ) => {
if ( showCardStatusActions === "false" ) { return undefined ; }
if ( orientation === 'horizontal' ) {
return (
< ActionRow >
< Button size = " sm " variant = { variant === 'primary' ? 'inverse-tertiary' : 'tertiary' } >
Dismiss
</ Button >
< Button size = " sm " variant = " brand " >
Learn more
</ Button >
</ ActionRow >
) ;
}
return (
< Button size = " sm " variant = " brand " block >
Learn more
</ Button >
) ;
} ) ( ) }
>
< HipsterIpsum
numShortParagraphs = { orientation === "vertical" ? 1 : undefined }
numParagraphs = { 1 }
/>
</ Card.Status >
</ Card >
</ CardGrid >
</ >
) ;
} ;
Card Content Block Empty# With image#
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const isExtraSmall = useMediaQuery ( { maxWidth : breakpoints . small . maxWidth } ) ;
return (
< Card style = { { width : isExtraSmall ? "100%" : "25rem" } } >
< Card.ImageCap
src = " https://picsum.photos/360/200/ "
srcAlt = " Card image "
/>
< Card.Section className = " text-center " >
< h2 > Headline </ h2 >
< p > This is an optional text description. </ p >
< Button variant = " brand " > Action </ Button >
</ Card.Section >
</ Card >
) }
Without image#
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const isExtraSmall = useMediaQuery ( { maxWidth : breakpoints . small . maxWidth } ) ;
return (
< Card style = { { width : isExtraSmall ? "100%" : "25rem" } } >
< Card.Section className = " text-center " >
< h2 > Headline </ h2 >
< p > This is an optional text description. </ p >
< Button variant = " brand " > Action </ Button >
</ Card.Section >
</ Card >
) }
Horizontal variant with image#
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const isSmall = useMediaQuery ( { maxWidth : breakpoints . small . maxWidth } ) ;
return (
< Card orientation = { isSmall ? "vertical" : "horizontal" } >
< Card.ImageCap
src = " https://picsum.photos/360/200/ "
srcAlt = " Card image "
/>
< Card.Body >
< Card.Section >
< h2 > Headline </ h2 >
< p > This is an optional text description. </ p >
</ Card.Section >
</ Card.Body >
< Card.Footer className = " justify-content-end " >
< Button variant = " brand " > Action </ Button >
</ Card.Footer >
</ Card >
) }
Horizontal variant without image#
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const isSmall = useMediaQuery ( { maxWidth : breakpoints . small . maxWidth } ) ;
return (
< Card orientation = { isSmall ? "vertical" : "horizontal" } >
< Card.Section >
< h2 > Headline </ h2 >
< p > This is an optional text description. </ p >
</ Card.Section >
< Card.Footer className = " justify-content-end " >
< Button variant = " brand " > Action </ Button >
</ Card.Footer >
</ Card >
) }
Fallback Image# With Fallback custom Image# You can specify fallbackSrc
image to show in case your main src
fails to load.
A fallback source is available for both the main ImageCap
component image and the logo.
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const isExtraSmall = useMediaQuery ( { maxWidth : breakpoints . small . maxWidth } ) ;
return (
< Card style = { { width : isExtraSmall ? "100%" : "40%" } } >
< Card.ImageCap
src = " fakeURL "
fallbackSrc = " https://picsum.photos/360/200/ "
srcAlt = " Card image "
logoSrc = " fakeURL "
fallbackLogoSrc = " https://www.edx.org/images/logos/edx-logo-elm.svg "
logoAlt = " Card logo "
/>
< Card.Header title = " Title " subtitle = " Subtitle " />
< Card.Section title = " Section title " >
This is a card section. It can contain anything but usually text, a list, or list of links.
Multiple sections have a card divider between them.
</ Card.Section >
< Card.Footer >
< Button > Action 1 </ Button >
</ Card.Footer >
</ Card >
) }
With default Fallback Image# The default fallback image will be displayed if fallbackSrc
is not specified.
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const isExtraSmall = useMediaQuery ( { maxWidth : breakpoints . small . maxWidth } ) ;
return (
< Card style = { { width : isExtraSmall ? "100%" : "40%" } } >
< Card.ImageCap
src = " fakeURL "
srcAlt = " Card image "
logoSrc = " fakeURL "
fallbackLogoSrc = " https://www.edx.org/images/logos/edx-logo-elm.svg "
logoAlt = " Card logo "
/>
< Card.Header title = " Title " subtitle = " Subtitle " />
< Card.Section title = " Section title " >
This is a card section. It can contain anything but usually text, a list, or list of links.
Multiple sections have a card divider between them.
</ Card.Section >
< Card.Footer >
< Button > Action 1 </ Button >
</ Card.Footer >
</ Card >
) }
With loading state# Vertical variant#
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const isExtraSmall = useMediaQuery ( { maxWidth : breakpoints . extraSmall . maxWidth } ) ;
return (
< Card isLoading style = { { width : isExtraSmall ? "100%" : "18rem" } } >
< Card.ImageCap
src = " https://picsum.photos/360/200/ "
srcAlt = " Card image "
/>
< Card.Header title = " Card Title " />
< Card.Section >
This is a card section. It can contain anything but usually text, a list, or list of links. Multiple sections have a card divider between them.
</ Card.Section >
< Card.Footer >
< Button > Action 1 </ Button >
</ Card.Footer >
</ Card >
) }
Horizontal variant#
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const isExtraSmall = useMediaQuery ( { maxWidth : breakpoints . extraSmall . maxWidth } ) ;
return (
< Card isLoading orientation = { isExtraSmall ? "vertical" : "horizontal" } >
< Card.ImageCap
skeletonHeight = { isExtraSmall ? 140 : null }
src = " https://picsum.photos/360/200/ "
srcAlt = " Card image "
logoSrc = " https://via.placeholder.com/150 "
logoAlt = " Card logo "
/>
< Card.Body >
< Card.Header title = " Title " />
< Card.Section title = " Section title " >
This is a special case where we want to have Footer with vertical
orientation in the Card with horizontal orientation.
</ Card.Section >
< Card.Footer orientation = " vertical " textElement = " Some footer text " >
< Button > Action 1 </ Button >
< Button > Action 2 </ Button >
</ Card.Footer >
</ Card.Body >
</ Card >
) }
CardGrid# This component displays a collection of Cards as a grid (with customizable responsive behavior), where
all cards in a given row have equal height. Try shrinking the width of your browser to view the responsive
behavior.
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const [ hasEqualColumnHeights , setHasEqualColumnHeights ] = useState ( 'true' ) ;
const ExampleCard = ( ) => (
< Card >
< Card.ImageCap
src = " https://picsum.photos/360/200/ "
srcAlt = " Card image "
/>
< Card.Header
title = " Card title "
/>
< Card.Section
title = " Section title "
>
< HipsterIpsum numShortParagraphs = { 1 } />
</ Card.Section >
< Card.Footer textElement = { < small className = " text-muted " > Last updated 3 mins ago </ small > } />
</ Card >
) ;
return (
< >
{ }
< ExamplePropsForm
inputs = { [
{
value : hasEqualColumnHeights ,
setValue : setHasEqualColumnHeights ,
options : [ 'true' , 'false' ] ,
name : 'Has equal card grid column heights' ,
} ,
] }
/>
{ }
< CardGrid
columnSizes = { {
xs : 12 ,
lg : 6 ,
xl : 4 ,
} }
hasEqualColumnHeights = { hasEqualColumnHeights === 'true' }
>
< ExampleCard />
< ExampleCard />
< ExampleCard />
< ExampleCard />
< ExampleCard />
< ExampleCard />
</ CardGrid >
</ >
) ;
}
CardDeck# Displays child Card
components in a horizontal row with equal height and width, with an appropriate gutter between cards. The width of each child Card
component is determined by the (optional) columnSizes
prop. If any child Card
components overflow beyond the parent's width, they will be hidden but accessible via scrolling horizontally or keyboard navigation.
For accessibility, if the child Card
components are interactive (e.g., isClickable
), pass the hasInteractiveChildren
prop so the CardDeck
itself isn't focusable.
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const [ hasInteractiveChildren , setHasInteractiveChildren ] = useState ( 'false' ) ;
const [ hasEqualColumnHeights , setHasEqualColumnHeights ] = useState ( 'true' ) ;
const CardComponent = ( ) => (
< Card isClickable = { hasInteractiveChildren === 'true' } >
< Card.ImageCap
src = " https://picsum.photos/360/200/ "
srcAlt = " Card image "
/>
< Card.Header title = " Card title " />
< Card.Section >
< HipsterIpsum numShortParagraphs = { 1 } />
</ Card.Section >
</ Card >
) ;
return (
< >
{ }
< ExamplePropsForm
inputs = { [
{
value : hasInteractiveChildren ,
setValue : setHasInteractiveChildren ,
options : [ 'true' , 'false' ] ,
name : 'Has interactive children' ,
} ,
{
value : hasEqualColumnHeights ,
setValue : setHasEqualColumnHeights ,
options : [ 'true' , 'false' ] ,
name : 'Has equal card deck column heights' ,
} ,
] }
/>
{ }
< CardDeck
hasInteractiveChildren = { hasInteractiveChildren === 'true' }
hasEqualColumnHeights = { hasEqualColumnHeights === 'true' }
>
< CardComponent />
< CardComponent />
< CardComponent />
< CardComponent />
< CardComponent />
</ CardDeck >
</ >
) ;
}
CardDeck.Deprecated# Gives any child Card
components equal height with an appropriate gutter between cards. Each child Card
component's width will be adjusted (e.g., become more narrow) to ensure all Card
components fit within its parent's width.
Note: This component is a pass-thru from react-bootstrap
.
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const CardComponent = ( ) => (
< Card >
< Card.ImageCap
src = " https://picsum.photos/360/200/ "
srcAlt = " Card image "
/>
< Card.Header title = " Card title " />
< Card.Section title = " Section title " >
< HipsterIpsum numShortParagraphs = { 1 } />
</ Card.Section >
</ Card >
) ;
return (
< CardDeck.Deprecated >
< CardComponent />
< CardComponent />
< CardComponent />
</ CardDeck.Deprecated >
)
}
CardCarousel# Extends CardDeck
to support navigating between any overflow Card
components via left and right IconButton
components as a scrollable carousel.
Includes support for an optional title
and subtitle
. You may rely on the default styles for the titles (e.g., if passing strings) or alternatively you may also pass custom HTML and JSX.
Show editable code example Any Paragon component or export may be added to the code example.
( ) => {
const [ canScrollHorizontal , setCanScrollHorizontal ] = useState ( 'true' ) ;
const [ disableOpacityMasks , setDisableOpacityMasks ] = useState ( 'false' ) ;
const [ hasOverflowCards , setHasOverflowCards ] = useState ( 'true' ) ;
const CardComponent = ( ) => (
< Card isClickable >
< Card.ImageCap
src = " https://picsum.photos/360/200/ "
srcAlt = " Card image "
/>
< Card.Header title = " Card title " />
< Card.Section title = " Section title " >
< HipsterIpsum numShortParagraphs = { 1 } />
</ Card.Section >
</ Card >
) ;
const cardItems = useMemo ( ( ) => {
if ( hasOverflowCards === 'true' ) {
return Array . from ( { length : 8 } ) . map ( ( ) => < CardComponent key = { uuidv4 ( ) } /> ) ;
}
return Array . from ( { length : 2 } ) . map ( ( ) => < CardComponent key = { uuidv4 ( ) } /> ) ;
} , [ hasOverflowCards ] ) ;
return (
< >
{ }
< ExamplePropsForm
inputs = { [
{
value : canScrollHorizontal ,
setValue : setCanScrollHorizontal ,
options : [ 'true' , 'false' ] ,
name : 'canScrollHorizontal' ,
} ,
{
value : disableOpacityMasks ,
setValue : setDisableOpacityMasks ,
options : [ 'true' , 'false' ] ,
name : 'disableOpacityMasks' ,
} ,
{
value : hasOverflowCards ,
setValue : setHasOverflowCards ,
options : [ 'true' , 'false' ] ,
name : 'hasOverflowCards' ,
}
] }
/>
{ }
< CardCarousel
ariaLabel = " example card carousel "
title = { < h3 > Recommended for you </ h3 > }
subtitle = " The following content was picked just for you. "
canScrollHorizontal = { canScrollHorizontal === 'true' }
disableOpacityMasks = { disableOpacityMasks === 'true' }
onScrollPrevious = { ( ) => { console . log ( 'onScrollPrevious' ) ; } }
onScrollNext = { ( ) => { console . log ( 'onScrollNext' ) ; } }
>
{ cardItems }
</ CardCarousel >
</ >
) ;
}
Theme Variables (SCSS)# $card-spacer-y : .75 rem !default ;
$card-spacer-x : 1.25 rem !default ;
$card-border-width : $border-width !default ;
$card-border-radius : $border-radius !default ;
$card-border-color : rgba ( $black , .125 ) !default ;
$card-border-focus-color : $primary-500 !default ;
$card-border-focus-color-dark : theme-color ( "primary" , "focus" ) !default ;
$card-inner-border-radius : subtract ( $card-border-radius , $card-border-width ) !default ;
$card-cap-bg : rgba ( $black , .03 ) !default ;
$card-cap-color : null !default ;
$card-height : null !default ;
$card-color : null !default ;
$card-bg : $white !default ;
$card-bg-dark : $primary-500 !default ;
$card-bg-muted : $light-200 !default ;
$card-img-overlay-padding : 1.25 rem !default ;
$card-group-margin : calc ( $grid-gutter-width / 2 ) !default ;
$card-deck-margin : $card-group-margin !default ;
$card-grid-margin : $card-group-margin !default ;
$card-deck-margin-bottom : map_ get ( $spacers , 3 ) !default ;
$card-grid-margin-bottom : map_ get ( $spacers , 3 ) !default ;
$card-columns-count : 3 !default ;
$card-columns-gap : 1.25 rem !default ;
$card-columns-margin : $card-spacer-y !default ;
$card-divider-bg : $light-400 !default ;
$card-footer-actions-gap : .5 rem !default ;
$card-logo-left-offset : 1.5 rem !default ;
$card-logo-bottom-offset : 1 rem !default ;
$card-logo-left-offset-horizontal : .4375 rem !default ;
$card-logo-bottom-offset-horizontal : .4375 rem !default ;
$card-logo-width : 7.25 rem !default ;
$card-logo-height : 4.125 rem !default ;
$card-image-border-radius : $card-border-radius !default ;
$card-logo-border-radius : .25 rem !default ;
$card-footer-text-font-size : $x-small-font-size ;
$card-image-horizontal-max-width : 240 px !default ;
$card-image-horizontal-min-width : $card-image-horizontal-max-width !default ;
$card-image-vertical-max-height : 140 px !default ;
$loading-skeleton-spacer : .313 rem !default ;
$card-focus-border-offset : 5 px !default ;
$card-focus-border-width : 2 px !default ;
$card-focus-border-radius : calc ( $card-focus-border-offset + $card-border-radius ) !default ;
Props API# This is a pass through component from React-Bootstrap, see original props documentation here.
This component does not receive any props.
className string
The class name for the CardGrid component
children node
Required
The Card components to organize into a responsive grid
columnSizes shape
{xs: number
,
sm: number
,
md: number
,
lg: number
,
xl: number
,
}An object containing the desired column size at each breakpoint, following a similar
props API as react-bootstrap/Col
Default {
sm: 12,
lg: 6,
xl: 4,
} hasEqualColumnHeights bool
Whether to disable the default equal height cards across rows in the card grid
Default true className string
Specifies class name to append to the base element.
children node
Specifies contents of the component.
Default null title node
Specifies title of the Section
.
actions node
Specifies node to render on the bottom right of the Section
(i.e. ActionRow
).
muted bool
Specifies whether to display Section
with muted styling.
Default false skeletonHeight number
Specifies height of skeleton in loading state.
Default 100 skeletonWidth number
Specifies width of skeleton in loading state.
className string
Specifies class name to append to the base element.
This is a pass through component from React-Bootstrap, see original props documentation here.
children node
Specifies the content of the component.
className string
The class to append to the base element.
className string
Specifies class name to append to the base element.
fallbackSrc string
Specifies fallback image src.
Default cardSrcFallbackImg srcAlt string
Specifies image alt text.
logoSrc string
Specifies logo src to put on top of the image.
fallbackLogoSrc string
Specifies fallback image logo src.
logoAlt string
Specifies logo image alt text.
skeletonHeight number
Specifies height of Image skeleton in loading state.
Default 140 skeletonWidth number
Specifies width of Image skeleton in loading state.
logoSkeleton bool
Specifies whether the cap should be displayed during loading.
Default false logoSkeletonHeight number
Specifies height of Logo skeleton in loading state.
Default 41 logoSkeletonWidth number
Specifies width of Logo skeleton in loading state.
imageLoadingType enum
'eager' | 'lazy'
Specifies loading type for images
Default 'eager' children node
Required
Specifies the content of the component.
className string
The class to append to the base element.
icon func
Icon that will be shown in the top-left corner.
variant enum
'primary' | 'success' | 'danger' | 'warning'
Specifies variant to use.
Default 'warning' title element
| string
Specifies title for the Card.Status
.
actions node
Specifies any optional actions, e.g. button(s).
This is a pass through component from React-Bootstrap, see original props documentation here.
className string
The class name for the CardDeck component
children node
Required
The Card components to organize
columnSizes shape
{xs: number
,
sm: number
,
md: number
,
lg: number
,
xl: number
,
}An object containing the desired column size at each breakpoint, following a similar
props API as react-bootstrap/Col
Default {
sm: 12,
lg: 6,
xl: 4,
} hasInteractiveChildren bool
Whether the child Card
components are interactive/focusable. If not, a tabindex="0"
is
added to be a11y-compliant
Default false canScrollHorizontal bool
Whether the CardDeck
supports horizontal scrolling when there are overflow children
Default true hasOverflowScrollItems bool
Whether the children of CardDeck should be processed by useOverflowScrollItems
to give
each child a known/stable CSS classname
Default false hasEqualColumnHeights bool
Whether to disable the default equal height cards
Default true children node
Required
The Card
items for the CardCarousel
.
ariaLabel string
Required
Text describing the CardCarousel for screen readers
columnSizes shape
{xs: number
,
sm: number
,
md: number
,
lg: number
,
xl: number
,
}Customize the responsive columnSizes used by the carousel.
Default {
sm: 12,
lg: 6,
xl: 4,
} hasInteractiveChildren bool
Whether the carousel has interactive children (e.g., clickable cards).
Default false canScrollHorizontal bool
Whether the carousel can be scrolled manually by users.
Default true disableOpacityMasks bool
Whether the default opacity masks should be shown at the start/end, if applicable.
Default false onScrollPrevious func
Callback function for when the user scrolls to the previous element.
onScrollNext func
Callback function for when the user scrolls to the next element.
CardCarouselControls elementType
Optional override for the default CardCarouselControls
Usage Insights# Card Expand all Project Name Paragon Version Instance Count frontend-app-admin-portal 21.13.1 43 frontend-app-authn 22.10.0 1 frontend-app-course-authoring 22.8.1 33 frontend-app-discussions 22.7.0 1 frontend-app-ecommerce 20.46.3 1 frontend-app-enterprise-public-catalog 21.13.1 4 frontend-app-learner-dashboard 22.9.0 3 frontend-app-learner-portal-enterprise 21.13.1 30 frontend-app-learning 22.8.1 4 frontend-app-library-authoring 21.11.3 11 frontend-app-ora-grading 21.11.3 4 frontend-app-support-tools 21.13.1 7 prospectus 20.46.2 8
CardBody Expand all Project Name Paragon Version Instance Count frontend-app-admin-portal 21.13.1 5 frontend-app-course-authoring 22.8.1 15 frontend-app-learner-dashboard 22.9.0 2 frontend-app-learner-portal-enterprise 21.13.1 3 frontend-app-library-authoring 21.11.3 1 prospectus 20.46.2 2
CardCarousel Expand all Project Name Paragon Version Instance Count frontend-app-learner-portal-enterprise 21.13.1 1
CardDeck Expand all Project Name Paragon Version Instance Count frontend-app-learner-portal-enterprise 21.13.1 1
CardDivider Expand all Project Name Paragon Version Instance Count frontend-app-course-authoring 22.8.1 9 prospectus 20.46.2 1
CardFooter Expand all Project Name Paragon Version Instance Count frontend-app-admin-portal 21.13.1 16 frontend-app-course-authoring 22.8.1 13 frontend-app-learner-dashboard 22.9.0 1 frontend-app-learner-portal-enterprise 21.13.1 7 frontend-app-learning 22.8.1 3 frontend-app-library-authoring 21.11.3 3 frontend-app-ora-grading 21.11.3 1 frontend-app-support-tools 21.13.1 2
CardGrid Expand all Project Name Paragon Version Instance Count frontend-app-admin-portal 21.13.1 12 frontend-app-course-authoring 22.8.1 2 frontend-app-learner-portal-enterprise 21.13.1 18 prospectus 20.46.2 3
CardHeader Expand all Project Name Paragon Version Instance Count frontend-app-admin-portal 21.13.1 10 frontend-app-authn 22.10.0 1 frontend-app-course-authoring 22.8.1 16 frontend-app-enterprise-public-catalog 21.13.1 2 frontend-app-learner-dashboard 22.9.0 2 frontend-app-learner-portal-enterprise 21.13.1 22 frontend-app-learning 22.8.1 4 frontend-app-library-authoring 21.11.3 5 frontend-app-support-tools 21.13.1 5
CardImageCap Expand all Project Name Paragon Version Instance Count frontend-app-admin-portal 21.13.1 10 frontend-app-authn 22.10.0 1 frontend-app-enterprise-public-catalog 21.13.1 2 frontend-app-learner-dashboard 22.9.0 2 frontend-app-learner-portal-enterprise 21.13.1 11 frontend-app-learning 22.8.1 1
CardSection Expand all Project Name Paragon Version Instance Count frontend-app-admin-portal 21.13.1 38 frontend-app-authn 22.10.0 1 frontend-app-course-authoring 22.8.1 27 frontend-app-discussions 22.7.0 1 frontend-app-enterprise-public-catalog 21.13.1 9 frontend-app-learner-dashboard 22.9.0 1 frontend-app-learner-portal-enterprise 21.13.1 46 frontend-app-learning 22.8.1 4 frontend-app-library-authoring 21.11.3 8 frontend-app-ora-grading 21.11.3 2 frontend-app-support-tools 21.13.1 10 prospectus 20.46.2 3
CardStatus Expand all Project Name Paragon Version Instance Count frontend-app-admin-portal 21.13.1 2 frontend-app-course-authoring 22.8.1 1 frontend-app-learner-portal-enterprise 21.13.1 2