The Basics

    What it is

    Card displays content and actions related to a single concept or item. It can contain images, video, text, buttons, and links. Cards are great for displaying collections: their consistent shape allows them to tile easily and scale responsively.

    By default, Card isn’t interactive, but it can contain interactive elements. It also has a clickable variation, where the entire Card acts an oversized button or link.

    How it works

    • Card displays a range of content, including static images and text, embedded videos, and forms.
    • The user engages with any interactive elements right in the Card, while on the page.

    In the clickable variation:

    • Hovering displays Card’s hover state.
    • Clicking displays Card’s pressed state and:
      • Triggers the action (if Card is acting as a button)
      • Opens the relevant page or section (if Card is acting as a link)
    • If Card contains other buttons or links in the button row, the user can activate them independently, without triggering the clickable Card.

    When to use

    • To summarize a single concept or item (like key information about a provider’s office) in a concise, self-contained element
    • To display a collection or group of items at the same level of hierarchy (in a set of multiple Cards)
    • To display links to other pages on a dashboard or home page

    When not to use

    • For information that should be condensed and easy to scan, because Card takes up a lot of space
    • As an easy way to separate content areas on a web page, when a simple <div> would work
    • When a List with dividers would suffice, because Card’s additional UI elements add unnecessary visual complexity

    What to use instead

    List

    Use List to show items in a condensed view that’s easy to scan.

    DataTable

    Use DataTable to show items in a view that’s easy to scan and sort.

    Accordion

    Use Accordion to display related content in a vertical list.

    How to use

    A single Card represents a single concept or item and can be used by itself. To represent multiple concepts or items, use multiple Cards. Card tiles easily, making it a great choice for representing a collection or group, like:

    • Upcoming appointments in a schedule
    • Links to patient education resources
    • Representations of inpatient rooms
    Do:

    Use a single Card to represent a single item or concept.

    <p>Use a single Card to represent a single item or concept.</p>
    Don't:

    Group multiple items or concepts in a single Card.

    <p>Group multiple items or concepts in a single Card.</p>

    Use a different pattern to represent nested items or concepts. Don’t put a Card in a Card.

    Card has several content areas, making it a very flexible component:

    • Media slot: Area at the top for a visual element like an image, video, or other graphic element. This content is full width, even with Card’s default padding.
    • Heading: Text that summarizes what the card represents. You can also include a heading description, which can serve as a subheading or elaborate on the heading.
    • Body: The main content area. In a clickable Card, this should not contain interactive elements (because they conflict with the clickable behavior).
    • Button row: Area at the bottom for buttons and links.

    Clickable Cards

    Card can be set to make the entire element clickable, so that Card functions as an oversized button or link. Use cases for this could include:

    • Card shows the title and a short description of a web page. Users click the Card to open the page.
    • A dashboard includes Cards that show summaries of different data. Users click each Card to open a separate page with more detailed data.
    • A set of Cards represents a library of patient education handouts. Users click a Card to select it and add it to their saved items.

    Buttons and links are the only interactive elements that should be used in a clickable Card. They should be placed in the button row so they don’t interfere with the clickable behavior.

    Do:

    Put buttons or links in the button row of a clickable Card.

    <p>Put buttons or links in the button row of a clickable Card.</p>
    Don't:

    Use other interactive elements in a clickable Card.

    <p>Use other interactive elements in a clickable Card.</p>

    Style

    Design details

    No additional information for this component.

    Placement and hierarchy

    Cards are good for fluid layouts, because they tile horizontally, as well as vertically on small screens. Multiple Cards should tile from left to right in their container. When they reach the right edge, they should continue on the next row, from left to right.

    The number of Cards per row varies, depending on the size of the Card and the width of the container. One Card per row is a good layout on smaller screens or in narrow containers (<760px), making it easy to scroll on mobile devices.

    Placement and hierarchy

    Content

    Media options

    Card has a media slot that can contain images, video, or audio:

    • Images default to full width, even when Card’s default padding is applied.
    • Videos shouldn’t autoplay. Include controls for basic playback features like play and pause.
    • Audio (like podcasts or other recordings) shouldn’t autoplay. As with video, add playback controls.

    If using different media types in the same set of Cards, use descriptive headings or some other indicator to convey the type of media each Card contains.

    Text and formatting

    • Use title case for Card heading text.
    • Use sentence case for Card heading description text.
    • Use sentence case for Card body text. Keep it short so the card doesn’t get too tall.
    • Use title case for any action buttons associated with the content. Put these buttons in the button row at the bottom of the Card.
    • For clickable cards, include descriptive text for screen readers to announce what clicking the Card will do (“Go to medication list”, “Book an appointment”, “Read information about type 2 diabetes”).

    Demos

    Card Basic Share

    Card With Buttons Share

    Cards With Images Share

    Coding

    Developer tips

    Clickable Cards

    To make the entire Card clickable, supply a function to the onClick prop. This also gives the border of the Card a visual style on hover (indicating that it can be clicked) and on click (indicating that it was clicked).

    Interactive elements in clickable Cards

    Avoid putting interactive elements (like buttons or links) in the body of a clickable Card, because it creates a confusing user experience.

    It also causes technical problems. Card works as a container for whatever content is passed as children, which renders in the Card body. Technically, you can add any valid JSX, but if you add interactive elements as children to a clickable Card, event bubbling will cause problems. When users click an element in the Card body, the event will bubble up to the parent Card component, which usually isn’t the desired behavior.

    If you need to add buttons or links to your clickable Card, put them in the button row at the bottom of the Card using the buttons prop. Elements passed to the buttons prop are cloned and have event handlers for mouseenter and mouseleave events added to them. This prevents showing the Card’s hover state when hovering over these elements and triggering the onClick function when they’re activated.

    If your use case absolutely requires putting interactive elements in the body of a clickable Card, you can use event.stopPropagation() on the elements’ click handlers as a workaround. To prevent click events triggered by any element passed as a child from bubbling up to the Card component, use the stopPropagation() method before the end of each interactive child's click handler:

    <Card>
    <a
    href="<https://athenahealth.com>"
    onClick={(e) => {
    // All click handler code should go before the next line
    e.stopPropagation();
    }}
    >
    Go to athenahealth!
    </a>
    </Card>;

    Padding

    By default, the padded prop is set to {true} and adds padding around all content inside Card except for mediaSlot content, which is full width. Set padded={false} to remove it.

    Repository

    Implementation links

    Card directory in Bitbucket

    Implementation details

    It is strongly recommended to familiarize yourself with the Forge source code. While this documentation is a best effort to document the intent and usage of a component, sometimes some features only become clear when looking at the source code. Also, looking at Forge's source code may help identify and fix bugs in either your application or Forge itself.

    Storybook files

    Forge maintains at least one storybook file per component. While the primary audience for these files is typically the Forge team, these storybook files may cover usages of the component not covered by a demo. The storybook for the latest version of forge can be found at go/forge-storybook-lts.

    Testing library

    Forge strongly encourages using testing-library to write tests for your application.

    "The more your tests resemble the way your software is used, the more confidence they can give you."

    If you're having trouble testing a Forge component using testing-library, it would be a good idea to see how Forge tests its own components. For the most part, Forge tries to use screen.getByRole as much as it can, as that API provides the best feedback on a11y compliance. Forge discourages the use of document.querySelector and screen.getByTestId as both APIs encourage using implementation details to test your component, and discourage adding roles to your component.

    With that being said, many of Forge's components were not built with accessibility in mind. These components do break the recommendations listed above.

    Import statements

    In Nimbus applications

    athenaOne serves the Forge bundle independently from your application's bundle. Importing Forge components directly from '@athena/forge' takes advantage of this feature.

    import { Card } from '@athena/forge'

    In standalone applications

    Importing components using the exact path to the module takes advantage of webpack's tree shaking feature. Webpack will include only that module and its dependencies.

    import Card from '@athena/forge/Card';

    To use this import guidance, Typescript applications must use typescript >= 4.7.3, and should add this setting to their tsconfig.json file:

    {
    "compilerOptions": {
    "moduleResolution": "Node16",
    }
    }

    If this setting doesn't work for your application, use this import statement instead:

    import Card from '@athena/forge/dist/Card';

    Props