Card
A Card component is ideal for encapsulating a discrete piece of content which has a single action. Card provides several elements that allow for multiple variations to suit a variety of contexts.
Installation
npm install @nib/card
Note: You will also need to install the peerDependencies @nib/icons and @nib-components/theme.
Usage
import Card from '@nib/card';
Note: If you are using this component within a React Server Component (like the NextJS 13 App Router), it is suggested to import
Card
,CardContent
andCardFooter
individually.
import Card, {CardContent, CardFooter} from '@nib/card';
<Card image="https://via.placeholder.com/900x600" imageAlt="Placeholder"><CardContent title="Card Heading"><Copy>Enabling teams to create high-quality products and experiences faster for our members.</Copy></CardContent><CardFooter><Inline space={4} collapseBelow="sm"><PrimaryButton fullWidth>Get a quote</PrimaryButton><SecondaryButton fullWidth>Get a quote</SecondaryButton></Inline></CardFooter></Card>;
Interactive demo
Note:
GreyBox
is not a card component, it is purely for demonstration purposes.
Props
Card
Prop | Type | Default | Description |
---|---|---|---|
children (required) | node | The content of the card. Content must be placed within the <Card.Content /> and <Card.Footer /> components. | |
component | string or component | div | The underlying component wrapping the card. |
image | string or element | Image to be added to the Card header. The image used should have an aspect ratio of 3:2 . The value can be an <img> or <picture> element. | |
imageAlt | string | The alt tag value for the corresponding image prop. Only works when the image prop provided is a string. | |
imageLazyLoading | boolean | true | Whether the card image should be loaded lazily. |
icon | component | Icon to be added to the Card header. Must be an icon from the @nib/icons package. | |
tag | component | Tag to be added to the card. Must be a @nib/tag component. | |
align | string | left | The horizontal alignment of the card content. Must be one of left , right or center . |
padding | number or object | 4 | A size from our spacing scale. Can be made responsive by passing an object of breakpoints. Value(s) must be one of 1...10 . |
horizontalLayout | boolean | false | Whether to use a the horizontal layout of the Card. |
collapseBelow | string | A breakpoint value which defines when the horizontalLayout structure should collapse to a vertical card. | |
reverse | boolean | Whether to reverse the order of the card columns. Only works with the horizontalLayout prop. | |
height | string | A fixed height applied to the Card wrapper. Useful when using the horizontalLayout prop. | |
background | string | white | A colour background applied around the icon or image of the card. Must be one of light , white , sageGreen , sunsetPink or warmWhite . |
Card.Content
Prop | Type | Default | Description |
---|---|---|---|
title (required) | string | The card title. | |
children (required) | node | The card content. | |
titleSize | number | The size of the card title. Must be one of 1 , 2 , 3 , 4 , 5 , 6 . | |
titleComponent | string | The underlying component of the card title. Must be one of h1 , h2 , h3 , h4 , h5 , h6 , div , label , span , header |
Card.Footer
Prop | Type | Default | Description |
---|---|---|---|
children (required) | node | The card footer content. |
Card variations
There is an additional card variation exported by this package called FlashCard
.
FlashCard
Usage
import {FlashCard} from '@nib/card';<FlashCard icon={DoctorGraphicIcon}><FlashCard.Content title="5 easy vegan meals"><Copy>Enabling teams to create high-quality products and experiences faster for our customers.</Copy><Inline space={4}><Link to="#">Read more</Link></Inline></FlashCard.Content></FlashCard>
Note: If you are using this component within a React Server Component (like the NextJS 13 App Router), it is suggested to import
FlashCard
,FlashCardContent
andFlashCardFooter
individually.
import {FlashCard,FlashCardContent, FlashCardFooter} from '@nib/card';
<FlashCard icon={DoctorGraphicIcon}><FlashCardContent title="5 easy vegan meals"><Copy>Enabling teams to create high-quality products and experiences faster for our members.</Copy><Link to="#">Read more</Link></FlashCardContent></FlashCard>;
Props
This component has the same props as are outlined above, with the following exceptions used to simplify the component for users:
- Instead of
Card.Content
andCard.Footer
, the subcomponents areFlashCard.Content
andFlashCard.Footer
. - The
horizontalLayout
does not apply to this component. - Icons are required and therefore the
image
,imageAlt
, andimageLazyLoading
props are unavailable. - The
tag
prop is unavailable for this component.
Examples
A Card can be configured to suit a range of contexts and requirements:
Card Heading
Enabling teams to create high-quality products and experiences faster for our customers.
A simple Card without an image or icon.
Card Heading
Enabling teams to create high-quality products and experiences faster for our customers.
A Card with an image and all available elements displayed and left aligned.
Card Heading
Enabling teams to create high-quality products and experiences faster for our customers.
A Card with an icon and all available elments displayed and center aligned.
A Card with an image, wrapped in a link.
Card Heading
Enabling teams to create high-quality products and experiences faster for our customers.
A horizontal Card with a fixed height.
5 easy vegan meals
Enabling teams to create high-quality products and experiences faster for our customers.
A basic Flash Card.
Considerations
When using the component
prop to wrap the card in a link (i.e. an a
tag, or a Gatsby Link
), it is important not to use any other clickable content within the card itself. This includes Buttons and Links. The reason for this is that nested links will create screen reader inaccessibility.
The <Card.Footer />
should use action elements such as buttons and links. When using buttons, we advise wrapping multiple buttons in an Inline
component with a collapseBelow
value set. Using this alongside the fullWidth
prop on the Button
will ensure the buttons are full width at smaller screen sizes.
If using the Horizontal Card
be aware of the limited space for content. The card is split into two equal columns and so there is very little room for things like buttons in the <Card.Footer />
, especially on mobile devices. It is recommended to reduce content inside Buttons (to a single word) or to not use Buttons at all. Large content inside <Card.Footer />
can cause card width to grow and floating tag to be cut off.
We are aware of an a11y issue when a card is wrapped in a link where users cannot highlight card content. We will be addressing this in a future release.
Images
The image
prop accepts either a string, representing the image source, or an image component. When simply providing a url, ensure the image is an appropriate size, and maintains the correct aspect ratio for optimal display. Note that when a horizontal Card uses the collapseBelow
prop, the image may not behave as expected in responsive layouts. In such cases, or if the image rendering does not meet your requirements, you can pass your own image component to the image
prop for more customisation including multiple image sizes, types and densities.
Many cards
When using the card component, it is likely that you will want to output a group of cards, and not just one. We recommend using our layout components to place cards alongside one another. There are basically two patterns for doing this.
A single row
For a single row of cards (that collapses to a single column on mobile) we suggest using the Columns
and Column
layout components:
<Columns space={{xs: 4, md: 6}} collapseBelow="lg"><Column flex><Card/></Column><Column flex><Card/></Column><Column flex><Card/></Column></Columns>
This should be used when the number of cards is known, and fits nicely in one row (typically no more than 4).
Multiple rows
For a list of cards that wraps to multiple rows we suggest using the Tiles
layout component:
<Tiles space={4} columns={{ md: 2, xl: 3 }}><Card/><Card/><Card/><Card/><Card/><Card/></Tiles>// or more realistically<Tiles space={4} columns={{ md: 2, xl: 3 }}>{cards.map(card => <Card {...card}/>)}</Tiles>
In this example cards are stacked in a single column on mobile, in two columns from the md
breakpoint up until xl
, at which point three columns are used. With tiles it doesn't matter how many cards there are, they simply wrap to a new row and carry on.
This should be used when the number of cards is known to be greater than can fit nicely in one row.
Equal card heights
Both approaches should retain equal heights for the cards in the list, and the Card.Content
sub-component should be the one to grow to fill the vertical space. Note the flex
prop on the Column
component in the first example.