Skip to content

React:Examples:Card

Card 컴포넌트 작성 방법

Card.tsx

import React from 'react';
import styles from './Card.module.scss';

type ReactChildType =
  | string
  | number
  | React.ReactElement<any, string | React.JSXElementConstructor<any>>
  | React.ReactFragment
  | React.ReactPortal;

interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
  icon?: React.ReactElement;
  children?: React.ReactNode;
}

function filterHeading(child: ReactChildType) {
  return (
    React.isValidElement(child) &&
    typeof child.type === 'string' &&
    child.type.match(/^[hH][1-6]$/g)
  );
}

export default class Card extends React.Component<CardProps> {
  render() {
    const {icon, children, className, ...rootProps} = this.props;
    const rootDivClass = styles.card + (className && ` ${className}`);

    const flattenChildren = React.Children.toArray(children);
    const firstHeading = flattenChildren.filter(filterHeading)[0];
    const body = flattenChildren.filter(c => c !== firstHeading);

    return (
      <div className={rootDivClass} {...rootProps}>
        <div className={styles.cardHeader}>
          <div className={styles.cardIcon}>{icon}</div>
          <div className={styles.cardTitle}>{firstHeading}</div>
        </div>

        <span className={styles.cardDivider} />

        <div className={styles.cardContent}>{body}</div>
      </div>
    );
  }
}

Card.module.scss

@tailwind base;
@tailwind components;
@tailwind utilities;

.card {
  @apply bg-white/5;
  @apply rounded-sm;
  @apply flex flex-col;

  .cardHeader {
    @apply font-medium text-xl;
    @apply flex flex-row items-center;
    @apply min-w-full;
    @apply px-4 py-2;
    @apply gap-2;

    .cardIcon {
      @apply text-2xl;
    }

    .cardTitle {
      @apply text-lg;
    }
  }

  .cardDivider {
    @apply h-px w-full;
    @apply bg-black/20;
  }

  .cardContent {
    @apply overflow-y-auto;
  }
}

See also