import React, { useEffect, useRef, useState, type HTMLAttributes, type ReactNode } from 'react' import { useIntl } from '@cultureamp/i18n-react-intl' import classnames from 'classnames' import { Button, IconButton } from '~components/ButtonV1' import type { GenericButtonProps } from '~components/ButtonV1/GenericButton' import { Heading, type AllowedHeadingTags } from '~components/Heading' import { Icon } from '~components/Icon' import { Text } from '~components/Text' import { type OverrideClassName } from '~components/types/OverrideClassName' import styles from './GenericTile.module.css' export type TileAction = GenericButtonProps export type TileInformation = { text: string primaryAction?: TileAction secondaryAction?: TileAction } export type GenericTileProps = { children?: React.ReactNode title: React.ReactNode titleTag?: AllowedHeadingTags metadata?: string information?: TileInformation | React.ReactNode /** Provides accessible label for the title's info button @default "View more information: [title]" */ infoButtonLabel?: string variant?: 'default' | 'expert-advice' footer: React.ReactNode } & OverrideClassName, 'title'>> export const GenericTile = ({ children, title, titleTag = 'h3', metadata, information, infoButtonLabel, variant = 'default', footer, classNameOverride, ...restProps }: GenericTileProps): JSX.Element => { const [isFlipped, setIsFlipped] = useState() const { formatMessage } = useIntl() const infoButtonRef = useRef(null) const infoButtonReturnRef = useRef(null) useEffect(() => { if (isFlipped === true) return infoButtonReturnRef.current!.focus() if (isFlipped === false) return infoButtonRef.current!.focus() }, [isFlipped]) const translatedInfoLabel = formatMessage({ id: 'kzGenericTile.infoButtonLabel', defaultMessage: 'View more information:', description: 'Prompts user to interact with button to reveal more information', }) const renderTitle = (): JSX.Element => (
{title} {metadata && (
{metadata}
)}
) const renderFront = (): JSX.Element => (
{information && (
} onClick={(): void => setIsFlipped(true)} disabled={isFlipped} aria-hidden={isFlipped} ref={infoButtonRef} />
)} {renderTitle()}
{children && children}
{footer &&
{footer}
}
) const renderInformation = ( informationProp: GenericTileProps['information'] | undefined, ): JSX.Element | React.ReactNode => { if (informationProp && typeof informationProp === 'object' && 'text' in informationProp) { return ( <> {informationProp.text} {(informationProp.primaryAction ?? informationProp.secondaryAction) && (
{informationProp.secondaryAction && (
)} ) } return informationProp } const renderBack = (): ReactNode => { if (!information) return null const returnButtonLabel = formatMessage({ id: 'kzGenericTile.infoButtonReturnLabel', defaultMessage: 'Hide information:', description: 'Prompts user to interact with button to hide information', }) return (
} onClick={(): void => setIsFlipped(false)} disabled={!isFlipped} aria-hidden={!isFlipped} ref={infoButtonReturnRef} />
{renderInformation(information)}
) } return (
{isFlipped ? renderBack() : renderFront()}
) } GenericTile.displayName = 'GenericTile'