diff options
| author | Armand Philippot <git@armandphilippot.com> | 2022-05-24 19:35:12 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-05-24 19:35:12 +0200 |
| commit | c85ab5ad43ccf52881ee224672c41ec30021cf48 (patch) | |
| tree | 8058808d9bfca19383f120c46b34d99ff2f89f63 /src/components/atoms/headings/heading.tsx | |
| parent | 52404177c07a2aab7fc894362fb3060dff2431a0 (diff) | |
| parent | 11b9de44a4b2f305a6a484187805e429b2767118 (diff) | |
refactor: use storybook and atomic design (#16)
BREAKING CHANGE: rewrite most of the Typescript types, so the content format (the meta in particular) needs to be updated.
Diffstat (limited to 'src/components/atoms/headings/heading.tsx')
| -rw-r--r-- | src/components/atoms/headings/heading.tsx | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/src/components/atoms/headings/heading.tsx b/src/components/atoms/headings/heading.tsx new file mode 100644 index 0000000..e385249 --- /dev/null +++ b/src/components/atoms/headings/heading.tsx @@ -0,0 +1,94 @@ +import { + createElement, + ForwardedRef, + forwardRef, + ForwardRefRenderFunction, + ReactNode, +} from 'react'; +import styles from './heading.module.scss'; + +export type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6; + +export type HeadingProps = { + /** + * The title alignment. Default: left; + */ + alignment?: 'center' | 'left'; + /** + * The heading body. + */ + children: ReactNode; + /** + * Set additional classnames. + */ + className?: string; + /** + * The heading id. + */ + id?: string; + /** + * Use an heading element or only its styles. Default: false. + */ + isFake?: boolean; + /** + * HTML heading level. + */ + level: HeadingLevel; + /** + * Adds margin. Default: true. + */ + withMargin?: boolean; +}; + +type TitleTagProps = Pick<HeadingProps, 'children' | 'className' | 'id'> & { + tagName: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p'; +}; + +const TitleTag = forwardRef< + HTMLHeadingElement | HTMLParagraphElement, + TitleTagProps +>( + ( + { children, tagName, ...props }, + ref: ForwardedRef<HTMLHeadingElement | HTMLParagraphElement> + ) => { + return createElement(tagName, { ...props, ref }, children); + } +); +TitleTag.displayName = 'TitleTag'; + +/** + * Heading component. + * + * Render an HTML heading element or a paragraph with heading styles. + */ +const Heading: ForwardRefRenderFunction<HTMLDivElement, HeadingProps> = ( + { + alignment = 'left', + children, + className, + id, + isFake = false, + level, + withMargin = true, + }, + ref: ForwardedRef<HTMLHeadingElement | HTMLParagraphElement> +) => { + const tagName = isFake ? 'p' : (`h${level}` as TitleTagProps['tagName']); + const levelClass = `heading--${level}`; + const alignmentClass = `heading--${alignment}`; + const marginClass = withMargin ? 'heading--margin' : 'heading--regular'; + + return ( + <TitleTag + tagName={tagName} + className={`${styles.heading} ${styles[levelClass]} ${styles[alignmentClass]} ${styles[marginClass]} ${className}`} + id={id} + ref={ref} + > + {children} + </TitleTag> + ); +}; + +export default forwardRef(Heading); |
