diff --git a/src/components/general/Typography/Link.stories.tsx b/src/components/general/Typography/Link.stories.tsx index 74e9e65bf..8786cd167 100644 --- a/src/components/general/Typography/Link.stories.tsx +++ b/src/components/general/Typography/Link.stories.tsx @@ -1,35 +1,74 @@ -import { type Meta } from '@storybook/react' -import { type StoryObj } from '@storybook/react' -import { Space } from 'src/components' +import type { Meta } from '@storybook/react' +import type { StoryObj } from '@storybook/react' +import { Flex, Icon, Space, Tooltip } from 'src/components' import { Typography } from 'src/components/general/Typography/Typography' import { ExampleStory } from 'src/utils/ExampleStory' +import { TypographyColors } from './colors' const meta: Meta = { - title: 'Components/General/Link', + title: 'Components/General/Typography/Link', component: props => Example Link, args: { + children: 'Example Text', + type: undefined, + color: undefined, + size: 'base', code: false, copyable: false, delete: false, disabled: false, editable: false, ellipsis: false, - keyboard: false, mark: false, strong: false, italic: false, - type: undefined, underline: false, - onClick: (event: React.MouseEvent) => { - console.log('Link Clicked') - }, }, argTypes: { + children: { + control: 'text', + name: 'text', + }, type: { control: 'select', options: ['secondary', 'success', 'warning', 'danger'], }, + size: { + control: 'select', + options: ['base', 'sm', 'lg', 'xl'], + }, + color: { + control: 'select', + options: TypographyColors, + }, + copyable: { + control: 'boolean', + }, + delete: { + control: 'boolean', + }, + disabled: { + control: 'boolean', + }, + editable: { + control: 'boolean', + }, + ellipsis: { + control: 'boolean', + }, + mark: { + control: 'boolean', + }, + strong: { + control: 'boolean', + }, + italic: { + control: 'boolean', + }, + code: { + control: 'boolean', + }, }, } export default meta @@ -43,95 +82,28 @@ type Story = StoryObj export const Primary: Story = {} -export const Code: Story = { - args: { - code: true, - }, -} - -export const Copyable: Story = { - args: { - copyable: true, - }, -} - -export const Deleted: Story = { - args: { - delete: true, - }, -} - -export const Disabled: Story = { - args: { - disabled: true, - }, -} - -export const Editable: Story = { - args: { - editable: true, - }, -} - -export const Keyboard: Story = { - args: { - keyboard: true, - }, -} - -export const Marked: Story = { - args: { - mark: true, - }, -} - -export const Strong: Story = { - args: { - strong: true, - }, -} - -export const Italic: Story = { - args: { - italic: true, - }, -} - -export const Success: Story = { - args: { - type: 'success', - }, -} - -export const Secondary: Story = { - args: { - type: 'secondary', - }, -} - -export const Warning: Story = { - args: { - type: 'warning', - }, -} - -export const Danger: Story = { - args: { - type: 'danger', - }, -} - -export const Underline: Story = { - args: { - underline: true, - }, -} - -export const CustomOnClick: Story = { - args: { - onClick: event => { - alert('Custom Click Handler') - }, +export const InsideTooltip: Story = { + render: () => { + return ( + + + Typography inside of a tooltip, hover icon to see + + + Help lorem ipsum{' '} + + Learn More + + + + }> + + + + + ) }, } diff --git a/src/components/general/Typography/Paragraph.stories.tsx b/src/components/general/Typography/Paragraph.stories.tsx index e77bb86c7..1719a6473 100644 --- a/src/components/general/Typography/Paragraph.stories.tsx +++ b/src/components/general/Typography/Paragraph.stories.tsx @@ -1,5 +1,5 @@ -import { type Meta } from '@storybook/react' -import { type StoryObj } from '@storybook/react' +import type { Meta } from '@storybook/react' +import type { StoryObj } from '@storybook/react' import { Typography } from 'src/components/general/Typography/Typography' import { ExampleStory } from 'src/utils/ExampleStory' import { useMemo } from 'react' @@ -8,12 +8,16 @@ import { Radio } from 'src/components' import { Switch } from 'src/components' import { Slider } from 'src/components' import { Icon } from 'src/components' +import { TypographyColors } from './colors' const meta: Meta = { - title: 'Components/General/Typography.Paragraph', + title: 'Components/General/Typography/Paragraph', component: props => Paragraph text goes here, - args: { + children: 'Example Text', + type: undefined, + color: undefined, + size: 'base', code: false, copyable: false, delete: false, @@ -23,17 +27,52 @@ const meta: Meta = { mark: false, strong: false, italic: false, - type: undefined, underline: false, - onClick: event => { - console.log('Paragraph Clicked') - }, }, argTypes: { + children: { + control: 'text', + name: 'text', + }, type: { control: 'select', options: ['secondary', 'success', 'warning', 'danger'], }, + size: { + control: 'select', + options: ['base', 'sm', 'lg', 'xl'], + }, + color: { + control: 'select', + options: TypographyColors, + }, + copyable: { + control: 'boolean', + }, + delete: { + control: 'boolean', + }, + disabled: { + control: 'boolean', + }, + editable: { + control: 'boolean', + }, + ellipsis: { + control: 'boolean', + }, + mark: { + control: 'boolean', + }, + strong: { + control: 'boolean', + }, + italic: { + control: 'boolean', + }, + code: { + control: 'boolean', + }, }, } export default meta @@ -47,98 +86,6 @@ type Story = StoryObj export const Primary: Story = {} -export const Code: Story = { - args: { - code: true, - }, -} - -export const Copyable: Story = { - args: { - copyable: true, - }, -} - -export const DeletedLine: Story = { - args: { - delete: true, - }, -} - -export const Disabled: Story = { - args: { - disabled: true, - }, -} - -export const Editable: Story = { - args: { - editable: true, - }, -} - -export const Ellipsis: Story = { - args: { - ellipsis: true, - }, -} - -export const Marked: Story = { - args: { - mark: true, - }, -} - -export const Strong: Story = { - args: { - strong: true, - }, -} - -export const Italic: Story = { - args: { - italic: true, - }, -} - -export const Success: Story = { - args: { - type: 'success', - }, -} - -export const Secondary: Story = { - args: { - type: 'secondary', - }, -} - -export const Warning: Story = { - args: { - type: 'warning', - }, -} - -export const Danger: Story = { - args: { - type: 'danger', - }, -} - -export const Underline: Story = { - args: { - underline: true, - }, -} - -export const CustomOnClick: Story = { - args: { - onClick: event => { - alert('Custom Click Handler') - }, - }, -} - export const ExampleEditable: Story = { render: () => { const [editableStr, setEditableStr] = useState('This is an editable text.') diff --git a/src/components/general/Typography/Text.stories.tsx b/src/components/general/Typography/Text.stories.tsx index 35a867493..5edac07f7 100644 --- a/src/components/general/Typography/Text.stories.tsx +++ b/src/components/general/Typography/Text.stories.tsx @@ -1,35 +1,38 @@ -import { type Meta } from '@storybook/react' -import { type StoryObj } from '@storybook/react' +import type { Meta } from '@storybook/react' +import type { StoryObj } from '@storybook/react' import { Space } from 'src/components' import { Switch } from 'src/components' import { Typography } from 'src/components/general/Typography/Typography' import { ExampleStory } from 'src/utils/ExampleStory' import { useState } from 'react' import { expect } from '@storybook/test' +import { ColorText } from 'src/styles/style' +import { TypographyColors } from './colors' const meta: Meta = { - title: 'Components/General/Typography.Text', - component: props => Example Text, - + title: 'Components/General/Typography/Text', + component: props => {props.children}, args: { - code: false, + children: 'Example Text', + type: undefined, + color: undefined, size: 'base', + code: false, copyable: false, delete: false, disabled: false, editable: false, ellipsis: false, - keyboard: false, mark: false, strong: false, italic: false, - type: undefined, underline: false, - onClick: (event: React.MouseEvent) => { - console.log('Text Clicked') - }, }, argTypes: { + children: { + control: 'text', + name: 'text', + }, type: { control: 'select', options: ['secondary', 'success', 'warning', 'danger'], @@ -38,113 +41,48 @@ const meta: Meta = { control: 'select', options: ['base', 'sm', 'lg', 'xl'], }, + color: { + control: 'select', + options: TypographyColors, + }, + copyable: { + control: 'boolean', + }, + delete: { + control: 'boolean', + }, + disabled: { + control: 'boolean', + }, + editable: { + control: 'boolean', + }, + ellipsis: { + control: 'boolean', + }, + mark: { + control: 'boolean', + }, + strong: { + control: 'boolean', + }, + italic: { + control: 'boolean', + }, + code: { + control: 'boolean', + }, }, } export default meta type Story = StoryObj -/* - Initial story templates generated by AI. - Customize the stories based on specific requirements. -*/ - export const Primary: Story = { play: async context => { const text = context.canvasElement.querySelector('span') void expect(text?.textContent).toEqual('Example Text') - }, -} - -export const Code: Story = { - args: { - code: true, - }, -} - -export const Copyable: Story = { - args: { - copyable: true, - }, -} - -export const Deleted: Story = { - args: { - delete: true, - }, -} - -export const Disabled: Story = { - args: { - disabled: true, - }, -} - -export const Editable: Story = { - args: { - editable: true, - }, -} - -export const Keyboard: Story = { - args: { - keyboard: true, - }, -} - -export const Marked: Story = { - args: { - mark: true, - }, -} - -export const Strong: Story = { - args: { - strong: true, - }, -} - -export const Italic: Story = { - args: { - italic: true, - }, -} - -export const Success: Story = { - args: { - type: 'success', - }, -} - -export const Secondary: Story = { - args: { - type: 'secondary', - }, -} - -export const Warning: Story = { - args: { - type: 'warning', - }, -} - -export const Danger: Story = { - args: { - type: 'danger', - }, -} - -export const Underline: Story = { - args: { - underline: true, - }, -} - -export const CustomOnClick: Story = { - args: { - onClick: event => { - alert('Custom Click Handler') - }, + void expect(text?.style.color).toEqual(ColorText) }, } @@ -153,19 +91,19 @@ export const ExampleTexts: Story = { return ( }> - Ant Design (default) - Ant Design (secondary) - Ant Design (success) - Ant Design (warning) - Ant Design (danger) - Ant Design (disabled) - Ant Design (mark) - Ant Design (code) - Ant Design (keyboard) - Ant Design (underline) - Ant Design (delete) - Ant Design (strong) - Ant Design (italic) + Aquarium (default) + Aquarium (secondary) + Aquarium (success) + Aquarium (warning) + Aquarium (danger) + Aquarium (disabled) + Aquarium (mark) + Aquarium (code) + Aquarium (keyboard) + Aquarium (underline) + Aquarium (delete) + Aquarium (strong) + Aquarium (italic) ) diff --git a/src/components/general/Typography/Title.stories.tsx b/src/components/general/Typography/Title.stories.tsx index 3d60f9b03..61617f1f4 100644 --- a/src/components/general/Typography/Title.stories.tsx +++ b/src/components/general/Typography/Title.stories.tsx @@ -1,38 +1,35 @@ -import { type Meta } from '@storybook/react' -import { type StoryObj } from '@storybook/react' +import type { Meta } from '@storybook/react' +import type { StoryObj } from '@storybook/react' import { Typography } from 'src/components/general/Typography/Typography' import { ExampleStory } from 'src/utils/ExampleStory' const meta: Meta = { - title: 'Components/General/Title', + title: 'Components/General/Typography/Title', component: Typography.Title, - - args: {}, } + export default meta type Story = StoryObj -export const Primary = {} - -export const ExampleHeadings: Story = { +export const Primary: Story = { render: () => { return ( - h1. Ant Design + h1. Aquarium Component Library - h2. Ant Design + h2. Aquarium Component Library - h3. Ant Design + h3. Aquarium Component Library - h4. Ant Design + h4. Aquarium Component Library - h5. Ant Design + h5. Aquarium Component Library ) diff --git a/src/components/general/Typography/Typography.tsx b/src/components/general/Typography/Typography.tsx index 76a911c92..4b4fb1bd6 100644 --- a/src/components/general/Typography/Typography.tsx +++ b/src/components/general/Typography/Typography.tsx @@ -1,29 +1,14 @@ -import { - Typography as AntTypography, - type TypographyProps as AntTypographyProps, - ConfigProvider as AntConfigProvider, -} from 'antd' +import { Typography as AntTypography } from 'antd' import { ConfigProvider } from 'src/components' -import { type ReactNode } from 'react' -import { type TextProps as AntTextProps } from 'antd/es/typography/Text' -import { type TitleProps as AntTitleProps } from 'antd/es/typography/Title' -import { type LinkProps as AntLinkProps } from 'antd/es/typography/Link' -import { type ParagraphProps as AntParagraphProps } from 'antd/es/typography/Paragraph' +import type { ReactNode } from 'react' +import type { TextProps as AntTextProps } from 'antd/es/typography/Text' +import type { TitleProps as AntTitleProps } from 'antd/es/typography/Title' +import type { LinkProps as AntLinkProps } from 'antd/es/typography/Link' +import type { ParagraphProps as AntParagraphProps } from 'antd/es/typography/Paragraph' +import { getColorFromStyles, type TypographyColor } from './colors' +import { ColorTextLightSolid } from 'src/styles/style' -export interface ITypographyProps extends AntTypographyProps { - children: ReactNode -} - -export const Typography = (props: ITypographyProps) => ( - - {props.children} - -) - -type TypographySize = 'base' | 'sm' | 'lg' | 'xl' -export interface ITextProps extends AntTextProps { - size?: TypographySize -} +type TypographySize = 'base' | 'sm' | 'lg' | 'xl' | number // TODO: Replace hardcoded values in getFontSize and getLineHeight with tokens when design is ready // These values are currently coming from https://www.figma.com/design/LffDbOUjeYqDMZ3djs9Cga/mParticle-Foundation-v1.0.1?node-id=3745-8164&m=dev @@ -31,7 +16,8 @@ const getFontSize = (size: TypographySize): number => { if (size === 'base') return 14 if (size === 'sm') return 12 if (size === 'lg') return 16 - return 20 + if (size === 'xl') return 20 + return size } const getLineHeight = (size: TypographySize): number => { @@ -41,50 +27,116 @@ const getLineHeight = (size: TypographySize): number => { return 1.4 } -const Text = ({ size = 'base', ...props }: ITextProps) => { - const fontSize = getFontSize(size) - const lineHeight = getLineHeight(size) +/** + * @v-gtiburcio some feedback regarding the link component that migh be useful for aquarium documentation. + * a) there is no size prop to control the font-size 😢 + * b) if you want to match link color to be the same as the Typography.Text, + * the only way is to override the style. but it removes the hover state. so here I wanted something that looks like Typography.Text, + * but behaves like Typography.Link. for both options I had to do some sacrifices 😅 + * + * @v-gtiburcio awesome! 2 main things I've noticed re: link component are changing color to match with the text or adjusting font size + */ + +interface InternalTypographyProps { + size?: TypographySize + color?: TypographyColor + children: ReactNode +} + +export const Typography = () => { + return <>DO NOT USE +} + +type InternalTextProps = InternalTypographyProps & AntTextProps +type InternalTitleProps = InternalTypographyProps & AntTitleProps +type InternalLinkProps = InternalTypographyProps & AntLinkProps +type InternalParagraphProps = InternalTypographyProps & AntParagraphProps + +export interface ITextProps extends InternalTextProps { + tooltip?: boolean +} + +export interface ITitleProps extends InternalTitleProps {} + +export interface ILinkProps extends InternalLinkProps { + tooltip?: boolean +} + +export interface IParagraphProps extends InternalParagraphProps {} + +// Tried generalizing into a higher order component but couldn't do it type-safely, so just repeated the code +const Text = (props: ITextProps) => { + const { size, color, type, tooltip, children, ...rest } = props + + const fontSize = size ? getFontSize(size) : undefined + const lineHeight = size ? getLineHeight(size) : undefined + const fontColor = !type && color ? getColorFromStyles(color) : tooltip ? ColorTextLightSolid : undefined return ( - - {props.children} - + + {children} + ) } Typography.Text = Text -interface ITitleProps extends AntTitleProps { - children: ReactNode +const Title = (props: ITitleProps) => { + const { size, color, type, children, ...rest } = props + + const fontSize = size ? getFontSize(size) : undefined + const lineHeight = size ? getLineHeight(size) : undefined + const fontColor = !type && color ? getColorFromStyles(color) : undefined + + return ( + + + {children} + + + ) } -const Title = (props: ITitleProps) => ( - - {props.children} - -) Typography.Title = Title -export interface ILinkProps extends AntLinkProps { - children: ReactNode +const Link = (props: ILinkProps) => { + const { size, color, type, tooltip, underline, children, ...rest } = props + + const fontSize = size ? getFontSize(size) : undefined + const lineHeight = size ? getLineHeight(size) : undefined + const fontColor = !type && color ? getColorFromStyles(color) : tooltip ? ColorTextLightSolid : undefined + + return ( + + + {children} + + + ) } -const Link = (props: ILinkProps) => ( - - {props.children} - -) Typography.Link = Link -export interface IParagraphProps extends AntParagraphProps { - children: ReactNode +const Paragraph = (props: IParagraphProps) => { + const { size, color, type, children, ...rest } = props + + const fontSize = size ? getFontSize(size) : undefined + const lineHeight = size ? getLineHeight(size) : undefined + const fontColor = !type && color ? getColorFromStyles(color) : undefined + + return ( + + + {children} + + + ) } -const Paragraph = (props: IParagraphProps) => ( - - {props.children} - -) Typography.Paragraph = Paragraph diff --git a/src/components/general/Typography/colors.ts b/src/components/general/Typography/colors.ts new file mode 100644 index 000000000..af807bcd0 --- /dev/null +++ b/src/components/general/Typography/colors.ts @@ -0,0 +1,41 @@ +import * as styles from '../../../styles/style' + +export const TypographyColors = [ + 'ColorText', + 'ColorTextSecondary', + 'ColorTextTertiary', + 'ColorTextQuaternary', + 'ColorInfoText', + 'ColorInfoTextActive', + 'ColorPrimaryTextHover', + 'ColorPrimaryText', + 'ColorPrimaryTextActive', + 'ColorSuccessTextHover', + 'ColorSuccessText', + 'ColorSuccessTextActive', + 'ColorErrorTextHover', + 'ColorErrorText', + 'ColorErrorTextActive', + 'ColorWarningTextHover', + 'ColorWarningText', + 'ColorWarningTextActive', + 'ColorLink', + 'ColorLinkHover', + 'ColorLinkActive', + 'ColorTextPlaceholder', + 'ColorTextDisabled', + 'ColorTextHeading', + 'ColorTextLabel', + 'ColorTextDescription', + 'ColorTextLightSolid', +] as const + +export type TypographyColor = (typeof TypographyColors)[number] + +export function getColorFromStyles(color: TypographyColor | string): string { + if (styles[color as TypographyColor]) { + return (styles as unknown as Record)[color as TypographyColor] + } + + return color +}