diff --git a/src/components/common/Typography/Typography.stories.tsx b/src/components/common/Typography/Typography.stories.tsx new file mode 100644 index 0000000..8798bc1 --- /dev/null +++ b/src/components/common/Typography/Typography.stories.tsx @@ -0,0 +1,11 @@ +import type { Meta } from '@storybook/react'; + +import { Typography } from './Typography'; + +const meta = { + title: 'Components/Typography', + component: Typography, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; diff --git a/src/components/common/Typography/Typography.tsx b/src/components/common/Typography/Typography.tsx new file mode 100644 index 0000000..598b46f --- /dev/null +++ b/src/components/common/Typography/Typography.tsx @@ -0,0 +1,80 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import clsx from 'clsx'; +import React, { forwardRef, HTMLAttributes, ReactNode } from 'react'; + +export enum TypographyVariant { + H1, + H2, + H3, + H4, + H5, + H6, + P1, + P2, + P3, + P4, + P5, + P6, +} + +const tagByVariant: Record = { + [TypographyVariant.H1]: 'h1', + [TypographyVariant.H2]: 'h2', + [TypographyVariant.H3]: 'h3', + [TypographyVariant.H4]: 'h4', + [TypographyVariant.H5]: 'h5', + [TypographyVariant.H6]: 'h6', + [TypographyVariant.P1]: 'p', + [TypographyVariant.P2]: 'p', + [TypographyVariant.P3]: 'p', + [TypographyVariant.P4]: 'p', + [TypographyVariant.P5]: 'p', + [TypographyVariant.P6]: 'p', +}; + +const variantClasses: Record = { + [TypographyVariant.H1]: 'text-h1', + [TypographyVariant.H2]: 'text-h2', + [TypographyVariant.H3]: 'text-h3', + [TypographyVariant.H4]: 'text-h4', + [TypographyVariant.H5]: 'text-h5', + [TypographyVariant.H6]: 'text-h6', + [TypographyVariant.P1]: 'text-p1', + [TypographyVariant.P2]: 'text-p2', + [TypographyVariant.P3]: 'text-p3', + [TypographyVariant.P4]: 'text-p4', + [TypographyVariant.P5]: 'text-p5', + [TypographyVariant.P6]: 'text-p6', +}; + +interface BaseProps { + children?: ReactNode; + text?: ReactNode; + variant?: TypographyVariant; + className?: string; + truncate?: boolean; + noWrap?: boolean; +} + +export interface TypographyProps extends BaseProps, HTMLAttributes {} + +export const Typography = forwardRef( + ( + { variant = TypographyVariant.P1, className, children, text, truncate, noWrap, ...rest }, + ref, + ) => { + const Tag = tagByVariant[variant]; + const classes = clsx( + variantClasses[variant], + truncate && 'truncate', + noWrap && !truncate && 'whitespace-nowrap', + className, + ); + + return ( + + {children ?? text} + + ); + }, +); diff --git a/src/components/common/Typography/index.ts b/src/components/common/Typography/index.ts new file mode 100644 index 0000000..d64ebba --- /dev/null +++ b/src/components/common/Typography/index.ts @@ -0,0 +1 @@ +export * from './Typography'; diff --git a/src/components/common/index.ts b/src/components/common/index.ts index 8a58d33..fb1f30f 100644 --- a/src/components/common/index.ts +++ b/src/components/common/index.ts @@ -19,3 +19,4 @@ export * from './Tabs'; export * from './TextLink'; export * from './TimePicker'; export * from './Toaster'; +export * from './Typography'; diff --git a/src/types/index.ts b/src/types/index.ts index 26f49f0..8f83f4a 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -39,6 +39,7 @@ import { TextLinkProps, TimeFieldProps, TimePickerProps, + TypographyProps, } from '~/components'; export interface UIComponents { @@ -81,6 +82,7 @@ export interface UIComponents { TextField: TextFieldProps; TextInput: TextInputProps; TimeField: TimeFieldProps; + Typography: TypographyProps; } export interface AppelloKit {