stories/atoms/components/card/Card.stories.mdx

Summary

Maintainability
Test Coverage
import { ArgsTable, Meta, Story, Canvas } from '@storybook/addon-docs'
import { Card } from 'ui/atoms/card/Card'
import { Icon } from 'ui/atoms/icon/Icon'
import { Button } from 'ui/atoms/button/Button'
import { Typography } from 'ui/atoms/typography/Typography'
import { ThemeProvider } from 'ui/atoms/theme/ThemeProvider'
import { ThemeSwitcher } from 'ui/atoms/theme/ThemeSwitcher'
import PatrickStar from '../../../assets/patrick-star.png'
import './card.scss'
import '../component.scss'

<Meta
  title="Atoms/Card"
  component={Card}
  decorators={[
    Story => (
      <ThemeProvider>
        <div className="story-theme-switcher">
          <ThemeSwitcher />
        </div>
        <div className="component-story-main">
          <Story />
        </div>
      </ThemeProvider>
    )
  ]}
/>

# Card

> A window that presents high level information to entice browsing users to learn more.

[![stability-unstable](https://img.shields.io/badge/stability-unstable-yellow.svg)](https://github.com/emersion/stability-badges#unstable)

## Description

Cards are an entry point for further exploration. They present summarized information meant to describe further content.

Card have a `header`, `content` and a `footer` that allow you to fill it with information that catch the readers attention. You can also
decide its `background` and `size`, as well as if it should be `withBorder`or not.

## Overview

<Story
  name="Overview"
  argTypes={{
    header: {
      control: false,
      table: {
        type: { summary: 'Node' }
      }
    },
    content: {
      control: false,
      table: {
        type: { summary: 'Node' }
      }
    },
    footer: {
      control: false,
      table: {
        type: { summary: 'Node' }
      }
    }
  }}
  args={{
    background: 'primary',
    size: 'medium',
    withBorder: true
  }}
>
  {args => (
    <div
      style={{
        display: 'flex',
        justifyContent: 'center',
        padding: '24px 0'
      }}
    >
      <Card
        {...args}
        header={
          <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
            <Typography fontSize="small" style={{ border: 'solid 1px', padding: '4px 8px' }}>
              Header
            </Typography>
          </div>
        }
        content={
          <Typography
            as="div"
            style={{ textAlign: 'center' }}
            fontFamily="secondary"
            fontSize="x-large"
            fontWeight="xlight"
          >
            Content
          </Typography>
        }
        footer={
          <Typography
            as="div"
            style={{ textAlign: 'start', marginBottom: '4px' }}
            fontWeight="bold"
          >
            Footer
          </Typography>
        }
      />
    </div>
  )}
</Story>

---

### Properties

<ArgsTable story="Overview" />

## Backgrounds

Card comes with two backgrounds to choose from:

- **primary** (default): Discreet `background` with a solid color.
- **secondary**: Gradient colored `background`. Makes the card stand out more.

<Canvas>
  <Story name="Backgrounds">
    {() => {
      const cards = {
        primary: {
          background: 'primary',
          contentText: 'Primary',
          footerText: 'ØKP4 Design System'
        },
        secondary: {
          background: 'secondary',
          contentText: 'Secondary',
          footerText: 'Blockchain'
        }
      }
      return (
        <div
          style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '40px' }}
        >
          {Object.values(cards).map(({ background, contentText, footerText }) => (
            <Card
              background={background}
              header={
                <div style={{ display: 'flex' }}>
                  <Typography fontSize="small" style={{ border: 'solid 1px', padding: '4px 8px' }}>
                    Article
                  </Typography>
                </div>
              }
              content={
                <Typography as="div" style={{ textAlign: 'center' }} fontSize="x-large">
                  {contentText}
                </Typography>
              }
              footer={
                <Typography
                  as="div"
                  style={{ textAlign: 'end', marginBottom: '4px' }}
                  fontSize="small"
                >
                  {footerText}
                </Typography>
              }
            />
          ))}
        </div>
      )
    }}
  </Story>
</Canvas>

## Sizes

There are three sizes to choose from:

- **small**: Great for small screens where page real estate is limited and when you don't want your page to become too long.
- **medium** (default): Middle ground option. Perfect for when you want the card to contain a lot of information but also want to render several cards.
- **large**: Will take up a lot of the page and can contain a lot of information. Suitable for desktop pages.

<Canvas>
  <Story name="Sizes">
    {() => {
      const cards = {
        small: {
          size: 'small',
          contentText: 'Small'
        },
        medium: {
          size: 'medium',
          contentText: 'Medium'
        },
        large: {
          size: 'large',
          contentText: 'Large'
        }
      }
      return (
        <div
          style={{
            display: 'flex',
            flexDirection: 'column',
            alignItems: 'center',
            gap: '40px'
          }}
        >
          {Object.values(cards).map(({ size, contentText }) => (
            <Card
              size={size}
              background="secondary"
              withBorder="true"
              content={
                <Typography as="div" style={{ textAlign: 'center' }} fontSize="x-large">
                  {contentText}
                </Typography>
              }
            />
          ))}
        </div>
      )
    }}
  </Story>
</Canvas>

## Border

Using `withBorder` adds a thin border to the card, this can help you avoid problems with contrast.
Card comes with a border as default value.

<Canvas>
  <Story name="Border">
    {() => {
      const cards = {
        withBorder: {
          withBorder: true,
          headerText: 'With border',
          footerText: '🫶 Ahh I can clearly see where the card ends'
        },
        withoutBorder: {
          withBorder: false,
          headerText: 'Without border',
          footerText: '🙀 Where did the border go?!'
        }
      }
      return (
        <div
          style={{
            display: 'flex',
            flexDirection: 'column',
            alignItems: 'center',
            gap: '40px'
          }}
        >
          {Object.values(cards).map(({ withBorder, headerText, footerText }) => (
            <Card
              withBorder={withBorder}
              header={
                <Typography as="div" fontSize="x-large">
                  {headerText}
                </Typography>
              }
              footer={
                <Typography
                  as="div"
                  style={{ textAlign: 'end', marginBottom: '4px' }}
                  fontSize="small"
                >
                  {footerText}
                </Typography>
              }
            />
          ))}
        </div>
      )
    }}
  </Story>
</Canvas>

## Header, Content and Footer

The heart of the card is its `header`, `content` and `footer` elements. They constitute the content
meant to inform and entice the reader.

The elements are layed out the same way a page would be organised, with the header on top, content in the middle
and footer on the bottom. These are just landmarks though and its up to you to style your card they way you want it.

<Canvas>
  <Story name="Header / Content / Footer">
    {() => {
      const handleClick = () => {
        window.open('https://www.linkedin.com/company/okp4-open-knowledge-protocol-for/mycompany/')
      }
      const cards = {
        shareData: {
          headerElement: (
            <div class="card-story-content-first-header">
              <Typography as="h1" fontFamily="secondary" fontWeight="bold">
                SHARE DATA
              </Typography>
            </div>
          ),
          footerElement: (
            <div className="card-story-content-first-footer">
              <img src={PatrickStar} alt="Patrick Star from Spongebob" />
              <div className="card-story-content-first-footer-quote">
                <Typography as="div" fontSize="small">
                  “We're not cavemen, we have technology"
                </Typography>
              </div>
            </div>
          )
        },
        openWeatherData: {
          headerElement: (
            <Typography
              as="div"
              fontSize="small"
              fontWeight="bold"
              style={{
                border: '1px solid',
                padding: '6px 8px',
                width: 'fit-content',
                marginLeft: 'auto'
              }}
            >
              Popular
            </Typography>
          ),
          contentElement: (
            <div class="card-story-content-second-content">
              <Typography as="div" fontFamily="secondary">
                Open Weather Data
              </Typography>
              <Typography as="div" fontSize="small">
                Public data on the weather
              </Typography>
            </div>
          ),
          footerElement: (
            <div class="card-story-content-second-footer">
              <Typography as="div" fontSize="small" fontWeight="bold">
                All Data Sets
              </Typography>
              <Icon name="next" />
            </div>
          )
        },
        linkedin: {
          headerElement: (
            <div class="card-story-content-third-header">
              <Typography style={{ flexShrink: '0' }} fontFamily="secondary" fontWeight="bold">
                Linkedin
              </Typography>
              <Icon name="linkedin-square" className="card-story-content-third-header-icon" />
            </div>
          ),
          contentElement: (
            <div class="card-story-content-third-content">
              <Typography as="div" fontWeight="xlight">
                Connect with ØKP4 on LinkedIn
              </Typography>
            </div>
          ),
          footerElement: (
            <div class="card-story-content-third-footer">
              <Button label="Connect nøw!" onClick={handleClick} />
            </div>
          )
        }
      }
      return (
        <div class="card-story-content">
          {Object.values(cards).map(
            ({ headerElement, contentElement, footerElement, background }) => (
              <Card
                header={headerElement}
                content={contentElement}
                footer={footerElement}
                background="secondary"
              />
            )
          )}
        </div>
      )
    }}
  </Story>
</Canvas>