Components

Card

The Card component is a low-level primitive used to create regions of content.

In its most basic form, a Card is simply a div with a hover interaction. Similar to the component, Card is a primitive that can be used to create a wide variety of experiences and UIs. Card comes with a default set of styles including border, elevation, and padding for your convienence. See the recipes section of this page for examples.

import { Card } from '@sproutsocial/racine'
<Card role='presentation'>
<Text.SmallByline>SEEDS WEB</Text.SmallByline>
<Text.Headline mb={300}>Card component</Text.Headline>
<Box mx="auto" my={400}>
<SpotIllustration height="200px" name="coffee-cup" aria-hidden />
</Box>
<Text.BodyCopy mb={400}>
The card component is a styled primitive container.
</Text.BodyCopy>
</Card>

Properties

NameTypeDefaultDescriptionRequired?
childrenReact.ReactNode
disabledbooleanfalse
elevation
'low'
'medium'
'high'
'low'
hrefstring
onClick(event: React.MouseEvent | React.KeyboardEvent) => void
role
'button'
'link'
'presentation'
'checkbox'
'presentation'
selectedboolean

Configurable elevations

The Card components allows consumers to configure the elevation of the Card to their specific context.

Functional

The default elevation on Cards is low. This is appropriate for most Cards in a functional setting or a setting with limited space.

Expressive

Configurable elevations are also available for Cards in more expressive brand settings where space is plentiful.

Recipes

Use this Card when you want the Card itself to link to different places.

<Card
role="link"
href="https://seeds.sproutsocial.com/"
>
<Box display="flex" justifyContent="center" alignItems="center" my={400}>
<SpotIllustration
height="200px"
name="calendar-reporting"
aria-hidden
/>
</Box>
<Text.SmallByline>Reporting</Text.SmallByline>
<CardLink affordance>Visit calendar report</CardLink>
</Card>

Be sure to wrap the link text that you want to be read to assistive technologies in CardLink. This subcomponent receives the via context from the parent and handles all default link behavior while allowing the Card itself to act as the click target. The Card as a link will not work properly without this component.

CardLink takes an optional affordance prop that makes adding a little extra oomph to links extra easy.

Card as a button

Use this Card when you need a region of content to perform a specific action. We should avoid nesting interactive elements inside Cards when they are used as a button.

() => {
const [message, setMessage] = useState(false);
const _onClick = () => {
setMessage(true);
};
useEffect(() => {
const showMessage = setTimeout(() => {
setMessage(false);
}, 4000);
return function cleanup() {
clearTimeout(showMessage);
};
}, [message]);
return (
<>
{message ? (
<Box mb={400}>
<Banner text="Your click was successful." />
</Box>
) : (
<Box mb={400}>
<Banner
type="warning"
text={
<Box
width={1}
display="flex"
alignItems="center"
justifyContent="space-between"
>
<Text width={3/4}>
Avoid nesting interactive content inside a Card with
role='button'
</Text>
</Box>
}
/>
</Box>
)}
<Card role='button' onClick={_onClick}>
<Box mx="auto" mb={400}>
<SpotIllustration height="200px" name="coffee-cup" aria-hidden />
</Box>
<Text.SmallByline>SEEDS WEB</Text.SmallByline>
<Text.Headline mb={300}>Card component</Text.Headline>
<Text.BodyCopy>
The card component is a styled primitive container.
</Text.BodyCopy>
</Card>
</>
)
}

Card for presentation

Use this Card when you need a simple way to display a region of related content.

While these Cards do have an optional onClick, it should only be leveraged for non-user facing actions like pollinator events or other data collection. While the Card may contain an interactive element, the Card itself should never take action via the user.

<Card role='presentation'>
<Text.SmallByline>SEEDS WEB</Text.SmallByline>
<Text.Headline mb={300}>Card component</Text.Headline>
<Box mx="auto" my={400}>
<SpotIllustration height="200px" name="coffee-cup" aria-hidden />
</Box>
<Text.BodyCopy mb={400}>
The card component is a styled primitive container.
</Text.BodyCopy>
<Link fontSize={300} href="https://google.com/" external>
Use now
<Icon
mb={100}
ml={300}
size="mini"
name="arrow-right-solid"
role={undefined}
svgProps={{role: 'img', 'aria-label': 'opens in a new tab'}}
/>
</Link>
</Card>

Disabled Card

Cards can also be disabled via the prop. This disabled state leverages the Seeds disabled mixin.

() => {
const [message, setMessage] = useState(false);
const _onClick = () => {
setMessage(true);
};
useEffect(() => {
const showMessage = setTimeout(() => {
setMessage(false);
}, 4000);
return function cleanup() {
clearTimeout(showMessage);
};
}, [message]);
return (
<>
{message ? (
<Box mb={400}>
<Banner text="Your click was successful." />
</Box>
) : (
<Box mb={400}>
<Banner
type="warning"
text={
<Box
width={1}
display="flex"
alignItems="center"
justifyContent="space-between"
>
<Text width={3/4}>
Avoid nesting interactive content inside a Card with
role='button'
</Text>
</Box>
}
/>
</Box>
)}
<Card role='button' onClick={_onClick} disabled>
<Box mx="auto" mb={400}>
<SpotIllustration height="200px" name="coffee-cup" aria-hidden />
</Box>
<Text.SmallByline>SEEDS WEB</Text.SmallByline>
<Text.Headline mb={300}>Card component</Text.Headline>
<Text.BodyCopy>
The card component is a styled primitive container.
</Text.BodyCopy>
</Card>
</>
)
}

Selectable Card

Cards can be individually selected via the prop.

() => {
const [selectedState, setSelectedState] = useState(false);
const toggle = () => setSelectedState(!selectedState);
return (
<Card onClick={toggle} role='checkbox' selected={selectedState}>
<CardContent my={450} mx="auto">
<Icon name="chart-pie-outline" size="jumbo" color="icon.base" aria-hidden />
</CardContent>
<CardFooter flexDirection="column">
<Text.SmallSubHeadline>Card Title</Text.SmallSubHeadline>
<Text.SmallBodyCopy>
This is a card that can be selected.
</Text.SmallBodyCopy>
</CardFooter>
</Card>
)
}

List of Cards

When creating a list of Cards, be sure to use a semantic list element.

() => {
const cards = [
{
subhead: 'Reporting',
reportName: 'Profile performance',
image: 'reporting',
href: 'https://app.sproutsocial.com/reports/group_report',
},
{
subhead: 'Reporting',
reportName: 'Post performance',
image: 'reporting-folder',
href: 'https://app.sproutsocial.com/reports/post_performance',
},
{
subhead: 'Reporting',
reportName: 'Tag performance',
image: 'analytics-offering',
href: 'https://app.sproutsocial.com/reports/tag_performance',
},
{
subhead: 'Reporting',
reportName: 'Paid performance',
image: 'listening-tour',
href: 'https://app.sproutsocial.com/reports/cross_network_campaign_performance',
},
];
const StyledList = styled.ul`
list-style: none;
display: flex;
flex-wrap: wrap;
`;
return (
<StyledList>
{cards.map((card) => {
return (
<li>
<Card role="link" href={card.href} width="300px" mr={400} mb={400}>
<Box
display="flex"
justifyContent="center"
alignItems="center"
my={400}
>
<SpotIllustration
height="200px"
name={card.image}
aria-hidden
/>
</Box>
<Text.SmallByline>{card.subhead}</Text.SmallByline>
<CardLink affordance>Visit {card.reportName} report</CardLink>
</Card>
</li>
);
})}
</StyledList>
);
}

Complex Card

Three subcomponents are available to make composing complex layouts with Card easy.

  • <CardHeader />
  • <CardContent />
  • <CardFooter />

Simply drop elements into these subcomponent and the Card will handle the padding and layout for you. Card subcomponents can still utilize system props for overrides when necessary.

import { Card,CardHeader,CardContent,CardFooter } from '@sproutsocial/racine'
<Card role="presentation">
<CardHeader>
<Avatar appearance="leaf" size="24px" name="Card Header" />
<Text.SubHeadline ml={300}>This is a card header</Text.SubHeadline>
</CardHeader>
<CardContent>
<Text.SmallBodyCopy as="p">
We can use the CardContent component to render cool content as seen
here:
</Text.SmallBodyCopy>
</CardContent>
<CardFooter>
<Link external href="https://google.com">
<Box display="flex" alignItems="center">
Action in CardFooter
<Icon
ml={200}
name="arrow-right-up-outline"
role={undefined}
svgProps={{role: 'img', 'aria-label': 'opens in a new tab'}}
/>
</Box>
</Link>
</CardFooter>
</Card>