import { forwardRef, type HTMLAttributes, type ForwardedRef, type ReactNode, type ReactElement, } from 'react'; import { Article, ButtonLink, type ButtonLinkProps } from '../../atoms'; import { CardCoverProvider, CardFooterMetaProvider } from './card-provider'; import styles from './card.module.scss'; type CardBaseProps = T extends string ? Omit : Omit, 'children'>; export type CardProps = CardBaseProps & { /** * The card contents. */ children: ReactNode; /** * The card cover. You need to add a `` as children to use it. */ cover?: ReactElement; /** * Should the contents be centered? * * @default false */ isCentered?: boolean; /** * Link the card to another page. * * @default undefined */ linkTo?: T; /** * The meta to place in the card footer. You need to add a `` * as children to use it. */ meta?: ReactElement; /** * The card variant. * * @default 1 */ variant?: 1 | 2; }; const CardWrapper = ( { children, className = '', cover, isCentered = false, linkTo, meta, variant = 1, ...props }: CardProps, ref: ForwardedRef ) => { const wrapperClass = [ styles.wrapper, styles[isCentered ? 'wrapper--centered' : 'wrapper--not-centered'], styles[linkTo ? 'wrapper--is-link' : 'wrapper--is-block'], className, ].join(' '); const cardClass = [ styles.card, styles[cover ? 'card--has-cover' : 'card--no-cover'], styles[meta ? 'card--has-footer-meta' : 'card--no-footer-meta'], styles[`card--variant-${variant}`], ].join(' '); return ( {linkTo ? ( )} className={wrapperClass} ref={ref} // eslint-disable-next-line react/jsx-no-literals -- Shape allowed shape="auto" to={linkTo} >
{children}
) : (
)} className={wrapperClass} ref={ref as ForwardedRef} >
{children}
)}
); }; /** * Card component * * Render a card with title and some other optional data. * * TODO: remove `cover` and `meta` props (and adapt CSS) when support for CSS * `:has()` pseudo-class will be good enough. */ export const Card = forwardRef(CardWrapper);