text updates

This commit is contained in:
Nate Kelley 2025-02-28 13:02:46 -07:00
parent a9ab327b75
commit 9ce1b3e843
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
14 changed files with 543 additions and 8 deletions

View File

@ -96,7 +96,7 @@ export const LegendItemDot: React.FC<
<div
className={cn(
'flex h-full w-full items-center justify-center overflow-hidden',
size === 'sm' ? 'text-xxs' : 'text-xxs'
size === 'sm' ? 'text2xs' : 'text2xs'
)}>
<Target />
</div>

View File

@ -258,7 +258,7 @@ const DropdownItem: React.FC<
{loading && <CircleSpinnerLoader size={9} />}
<div className={cn('flex flex-col gap-y-1', truncate && 'overflow-hidden')}>
<span className={cn(truncate && 'truncate')}>{label}</span>
{secondaryLabel && <span className="text-gray-light text-xxs">{secondaryLabel}</span>}
{secondaryLabel && <span className="text-gray-light text2xs">{secondaryLabel}</span>}
</div>
{shortcut && <DropdownMenuShortcut>{shortcut}</DropdownMenuShortcut>}
{link && (

View File

@ -19,7 +19,7 @@ KeyboardShortcutPill.displayName = 'KeyboardShortcutPill';
const TooltipShortcut: React.FC<{ shortcut: string }> = ({ shortcut }) => {
return (
<div className="border-border bg-background text-xxs pointer-events-none relative flex h-5 w-[1.375rem] items-center justify-center rounded border-[0.5px] leading-none shadow">
<div className="border-border bg-background text2xs pointer-events-none relative flex h-5 w-[1.375rem] items-center justify-center rounded border-[0.5px] leading-none shadow">
{shortcut}
</div>
);

View File

@ -91,5 +91,5 @@ const SelectItemSelector: React.FC<{
SelectItemSelector.displayName = 'SelectItemSelector';
const SelectItemSecondaryText: React.FC<{ children: React.ReactNode }> = ({ children }) => {
return <span className="text-gray-light text-xxs">{children}</span>;
return <span className="text-gray-light text2xs">{children}</span>;
};

View File

@ -105,7 +105,7 @@ const Tag: React.FC<{
onRemove(value);
}}
className="hover:text-foreground text-icon-color hover:bg-item-hover-active pointer-events-auto flex h-3.5 w-3.5 cursor-pointer items-center justify-center rounded-sm focus:outline-none">
<div className="text-xxs">
<div className="text2xs">
<Xmark />
</div>
</button>

View File

@ -37,7 +37,7 @@ const useTextStyles = createStyles(({ css, token }) => {
@apply text-xs;
`,
xxs: css`
@apply text-xxs;
@apply text2xs;
`
};
});

View File

@ -0,0 +1,110 @@
import type { Meta, StoryObj } from '@storybook/react';
import Paragraph from './Paragraph';
import { faker } from '@faker-js/faker';
const meta = {
title: 'UI/Typography/Paragraph',
component: Paragraph,
parameters: {
layout: 'centered'
},
tags: ['autodocs'],
argTypes: {
variant: {
control: 'select',
options: ['default', 'primary', 'secondary', 'tertiary', 'danger'],
description: 'The color variant of the text'
},
size: {
control: 'select',
options: ['base', 'sm', 'xs', 'md', 'lg'],
description: 'The size of the text'
},
lineHeight: {
control: 'select',
options: ['none', 'sm', 'base', 'md', 'lg'],
description: 'The line height of the text'
},
children: {
control: 'text',
description: 'The content of the paragraph'
},
className: {
control: 'text',
description: 'Additional CSS classes'
}
},
decorators: [
(Story) => (
<div className="flex max-w-[300px] flex-col gap-2 border p-2">
<Story />
</div>
)
]
} satisfies Meta<typeof Paragraph>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
args: {
children: faker.lorem.paragraphs(3),
variant: 'default',
size: 'base',
lineHeight: 'base'
}
};
export const Small: Story = {
args: {
children: faker.lorem.paragraph({ min: 1, max: 2 }),
size: 'sm',
variant: 'default',
lineHeight: 'base'
}
};
export const Primary: Story = {
args: {
children: faker.lorem.paragraphs(3),
variant: 'primary',
size: 'base',
lineHeight: 'base'
}
};
export const Secondary: Story = {
args: {
children: faker.lorem.paragraphs(3),
variant: 'secondary',
size: 'base',
lineHeight: 'base'
}
};
export const Large: Story = {
args: {
children: faker.lorem.paragraphs(3),
size: 'lg',
variant: 'default',
lineHeight: 'lg'
}
};
export const Danger: Story = {
args: {
children: faker.lorem.paragraphs(3),
variant: 'danger',
size: 'base',
lineHeight: 'base'
}
};
export const CustomLineHeight: Story = {
args: {
children: faker.lorem.paragraphs(3),
variant: 'default',
size: 'base',
lineHeight: 'lg'
}
};

View File

@ -0,0 +1,57 @@
import { cva, VariantProps } from 'class-variance-authority';
import React from 'react';
import { textColorVariants } from './variants';
import { cn } from '@/lib/utils';
const paragraphVariants = cva('', {
variants: {
size: {
base: 'text-base',
sm: 'text-sm',
xs: 'text-xs',
md: 'text-md',
lg: 'text-lg'
},
lineHeight: {
none: 'leading-[1]!',
sm: 'leading-[1.2]!',
base: 'leading-[1.3]!',
md: 'leading-[1.4]!',
lg: 'leading-[1.5]!'
}
}
});
type ParagraphProps = {
className?: string;
style?: React.CSSProperties;
onClick?: React.MouseEventHandler<HTMLHeadingElement>;
children: React.ReactNode;
} & VariantProps<typeof textColorVariants> &
VariantProps<typeof paragraphVariants>;
const Paragraph: React.FC<ParagraphProps> = ({
onClick,
variant = 'default',
size = 'base',
children,
className,
style,
lineHeight = 'base'
}) => {
console.log(lineHeight);
return (
<p
className={cn(
paragraphVariants({ size, lineHeight }),
textColorVariants({ variant }),
className
)}
style={style}
onClick={onClick}>
{children}
</p>
);
};
export default Paragraph;

View File

@ -0,0 +1,123 @@
import type { Meta, StoryObj } from '@storybook/react';
import Text from './Text';
const meta: Meta<typeof Text> = {
title: 'UI/Typography/Text',
component: Text,
tags: ['autodocs'],
args: {
children: 'Sample Text'
},
argTypes: {
variant: {
control: 'select',
options: ['default', 'secondary', 'tertiary', 'danger', 'primary', 'inherit', 'link']
},
size: {
control: 'select',
options: ['xxs', 'xs', 'sm', 'base', 'md', 'lg', 'xl', '2xl']
},
truncate: {
control: 'boolean',
defaultValue: false
}
}
};
export default meta;
type Story = StoryObj<typeof Text>;
export const AllSizes: Story = {
render: (args) => (
<div className="flex flex-col gap-0">
<Text size="4xl" {...args}>
Text 4XL Size (30px)
</Text>
<Text size="3xl" {...args}>
Text 3XL Size (24px)
</Text>
<Text size="2xl" {...args}>
Text 2XL Size (20px)
</Text>
<Text size="xl" {...args}>
Text XL Size (18px)
</Text>
<Text size="lg" {...args}>
Text Large Size (16px)
</Text>
<Text size="sm" {...args}>
Text Small Size (12px)
</Text>
<Text size="xs" {...args}>
Text XS Size (11px)
</Text>
<Text size="2xs" {...args}>
Text 2XS Size (8px)
</Text>
<Text size="3xs" {...args}>
Text 3XS Size (6px)
</Text>
</div>
)
};
export const Default: Story = {
args: {
variant: 'default',
size: 'base'
}
};
export const Secondary: Story = {
args: {
variant: 'secondary',
size: 'base'
}
};
export const Primary: Story = {
args: {
variant: 'primary',
size: 'base'
}
};
export const Large: Story = {
args: {
variant: 'default',
size: 'lg'
}
};
export const Small: Story = {
args: {
variant: 'default',
size: 'sm'
}
};
export const Link: Story = {
args: {
variant: 'link',
size: 'base',
children: 'Click me'
}
};
export const Truncated: Story = {
args: {
variant: 'default',
size: 'base',
truncate: true,
children:
'This is a very long text that will be truncated when it exceeds the available space in the container'
},
decorators: [
(Story) => (
<div className="overflow-hidden" style={{ width: '200px' }}>
<Story />
</div>
)
]
};

View File

@ -0,0 +1,57 @@
import { cn } from '@/lib/classMerge';
import { cva, VariantProps } from 'class-variance-authority';
import React from 'react';
import { textColorVariants } from './variants';
const textVariants = cva('', {
variants: {
size: {
'3xs': 'text-3xs',
'2xs': 'text-2xs',
xs: 'text-xs',
sm: 'text-sm',
base: 'text-base',
md: 'text-md',
lg: 'text-lg',
xl: 'text-xl',
'2xl': 'text-2xl',
'3xl': 'text-3xl',
'4xl': 'text-4xl'
},
truncate: {
true: 'truncate',
false: ''
}
}
});
type TextProps = {
className?: string;
style?: React.CSSProperties;
onClick?: React.MouseEventHandler<HTMLSpanElement>;
children: React.ReactNode;
} & VariantProps<typeof textVariants> &
VariantProps<typeof textColorVariants>;
const Text: React.FC<TextProps> = ({
variant = 'default',
size = 'base',
truncate,
className,
style,
onClick,
children
}) => {
const TextNode = truncate ? 'div' : 'span';
return (
<TextNode
style={style}
className={cn(textVariants({ size, truncate }), textColorVariants({ variant }), className)}
onClick={onClick}>
{children}
</TextNode>
);
};
export default Text;

View File

@ -0,0 +1,109 @@
import type { Meta, StoryObj } from '@storybook/react';
import Title from './Title';
const meta: Meta<typeof Title> = {
title: 'UI/Typography/Title',
component: Title,
tags: ['autodocs'],
args: {
children: 'Sample Title'
},
argTypes: {
variant: {
control: 'select',
options: ['default', 'secondary', 'tertiary', 'danger', 'primary', 'inherit', 'link']
},
size: {
control: 'select',
options: ['h1', 'h2', 'h3', 'h4', 'h5']
},
as: {
control: 'select',
options: ['h1', 'h2', 'h3', 'h4', 'h5']
},
truncate: {
control: 'boolean',
defaultValue: false
}
}
};
export default meta;
type Story = StoryObj<typeof Title>;
export const AllLevels: Story = {
render: (args) => (
<div className="flex flex-col gap-0">
<Title size="h1" {...args}>
Heading Level 1 (3xl - 24px)
</Title>
<Title size="h2" {...args}>
Heading Level 2 (2xl - 20px)
</Title>
<Title size="h3" {...args}>
Heading Level 3 (xl - 18px)
</Title>
<Title size="h4" {...args}>
Heading Level 4 (lg - 16px)
</Title>
<Title size="h5" {...args}>
Heading Level 5 (md - 14px)
</Title>
</div>
)
};
export const Default: Story = {
args: {
variant: 'default',
size: 'h1'
}
};
export const Secondary: Story = {
args: {
variant: 'secondary',
size: 'h1'
}
};
export const Primary: Story = {
args: {
variant: 'primary',
size: 'h1'
}
};
export const DifferentLevel: Story = {
args: {
variant: 'default',
size: 'h3'
}
};
export const CustomTag: Story = {
args: {
variant: 'default',
size: 'h1',
as: 'h2',
children: 'H1 size but H2 tag'
}
};
export const Truncated: Story = {
args: {
variant: 'default',
size: 'h1',
truncate: true,
children:
'This is a very long title that will be truncated when it exceeds the available space in the container'
},
decorators: [
(Story) => (
<div style={{ width: '300px' }}>
<Story />
</div>
)
]
};

View File

@ -0,0 +1,64 @@
import { cn } from '@/lib/classMerge';
import { cva, VariantProps } from 'class-variance-authority';
import React from 'react';
import { textColorVariants } from './variants';
const titleVariants = cva('', {
variants: {
size: {
h1: 'text-3xl',
h2: 'text-2xl',
h3: 'text-xl',
h4: 'text-lg',
h5: 'text-md'
},
truncate: {
true: 'truncate',
false: ''
}
},
defaultVariants: {
size: 'h4'
}
});
type TitleLevel = 'h1' | 'h2' | 'h3' | 'h4' | 'h5';
type TitleProps = {
as?: TitleLevel;
className?: string;
style?: React.CSSProperties;
onClick?: React.MouseEventHandler<HTMLHeadingElement>;
children: React.ReactNode;
} & VariantProps<typeof titleVariants> &
VariantProps<typeof textColorVariants>;
const Title: React.FC<TitleProps> = ({
as = 'h1',
variant = 'default',
size,
truncate,
className,
style,
onClick,
children
}) => {
// If size is not explicitly set, use the heading level as the size
const effectiveSize = size || as;
const Component = as;
return (
<Component
style={style}
className={cn(
titleVariants({ size: effectiveSize, truncate }),
textColorVariants({ variant }),
className
)}
onClick={onClick}>
{children}
</Component>
);
};
export default Title;

View File

@ -0,0 +1,15 @@
import { cva } from 'class-variance-authority';
export const textColorVariants = cva('', {
variants: {
variant: {
default: 'text-text-default',
secondary: 'text-text-secondary',
tertiary: 'text-text-tertiary',
danger: 'text-text-danger',
primary: 'text-text-primary',
inherit: 'text-inherit',
link: 'text-text-default hover:text-text-primary'
}
}
});

View File

@ -21,8 +21,6 @@
--text-3xs--line-height: 1;
--text-2xs: 8px;
--text-2xs--line-height: 1;
--text-xxs: 10px;
--text-xxs--line-height: 1;
--text-xs: 11px;
--text-xs--line-height: 1;
--text-sm: 12px;
@ -98,6 +96,8 @@
--color-text-disabled: var(--color-gray-light);
--color-text-secondary: var(--color-gray-dark);
--color-text-tertiary: var(--color-gray-light);
--color-text-danger: var(--color-danger-foreground);
--color-text-primary: var(--color-primary);
}
@import './tailwindAnimations.css';