Skip to main content

Recipes

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

Live Editor
function CardAsLinkExample() {
  return (
    <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 href 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.

Live Editor
function CardAsButtonExample() {
  const [message, setMessage] = React.useState(false);

  const _onClick = () => {
    setMessage(true);
  };

  React.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.

Live Editor
function CardForPresentationExample() {
  return (
    <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 disabled prop. This disabled state leverages the Seeds disabled mixin.

Live Editor
function DisabledCardExample() {
  const [message, setMessage] = React.useState(false);

  const _onClick = () => {
    setMessage(true);
  };

  React.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 selected prop.

Live Editor
function SelectableCardExample() {
  const [selectedState, setSelectedState] = React.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.

Live Editor
function ListOfCardsExample() {
  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.

Live Editor
function ComplexCardExample() {
  return (
    <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>
  );
}