refactor: move all text-related classes to Typography component (#198)

This commit is contained in:
Konrad Szwarc 2023-02-06 21:53:45 +01:00 committed by GitHub
parent 20e1423bf5
commit aa373785de
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 69 additions and 73 deletions

View file

@ -1,5 +1,6 @@
---
import Description from '@/components/description.astro';
import { variantToClassName } from './typography.astro';
export interface Props {
content: string;
@ -7,9 +8,6 @@ export interface Props {
}
const { content, class: className } = Astro.props;
const baseClass =
/* tw */ 'text-sm leading-relaxed font-normal text-gray-500 sm:text-base sm:leading-relaxed dark:text-gray-300';
---
<Description content={content} classList={[baseClass, className]} />
<Description content={content} classList={[variantToClassName.paragraph, className]} />

View file

@ -1,18 +1,21 @@
---
import type { DownloadButton } from '@/types/shared';
import Typography from './typography.astro';
export interface Props extends DownloadButton {}
const { url, downloadedFileName, label } = Astro.props;
const classes = /* tw */ {
main: 'inline-flex items-center px-4 h-10 text-base font-medium rounded-md shadow-sm text-white bg-primary-600 select-none cursor-pointer',
main: 'inline-flex items-center px-4 h-10 rounded-md shadow-sm bg-primary-600 select-none cursor-pointer',
hover: 'hover:bg-primary-700',
active: 'active:translate-y-px',
focus: 'focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500',
};
const className = Object.values(classes).join(' ');
---
<a href={url} class:list={[classes.main, classes.hover, classes.active, classes.focus]} download={downloadedFileName}>
<Typography variant="button" as="a" href={url} class={className} download={downloadedFileName}>
{label}
</a>
</Typography>

View file

@ -1,5 +1,6 @@
---
import type { LabelledValue } from '@/types/shared';
import Typography from './typography.astro';
export interface Props extends LabelledValue {}
@ -8,15 +9,15 @@ const { label, value, url } = Astro.props;
const parsedValue = Array.isArray(value) ? value.join(', ') : value;
---
<div class="text-base">
<span class="font-medium text-gray-700 dark:text-gray-300">{label}:</span>
<div>
<Typography variant="label">{label}:</Typography>
{
url ? (
<a href={url} target="_blank" class="font-normal text-gray-500 underline dark:text-gray-400">
<Typography as="a" href={url} target="_blank" class="underline">
{parsedValue}
</a>
</Typography>
) : (
<span class="font-normal text-gray-500 dark:text-gray-400">{parsedValue}</span>
<Typography variant="value">{parsedValue}</Typography>
)
}
</div>

View file

@ -1,31 +1,27 @@
---
import type { Tag } from '@/types/shared';
import Icon from './icon.astro';
import Typography from './typography.astro';
export interface Props extends Tag {}
const { name, description, icon, iconColor, url } = Astro.props;
const className =
/* tw */ 'flex h-6 w-fit items-center gap-x-1.5 rounded bg-gray-100 px-2.5 text-sm font-medium tracking-wide text-gray-700 dark:bg-gray-700 dark:text-gray-100';
const className = /* tw */ 'flex h-6 w-fit items-center gap-x-1.5 rounded bg-gray-100 px-2.5 dark:bg-gray-700';
const customProps = url
? ({
href: url,
as: 'a',
target: '_blank',
rel: 'noopener noreferrer',
class: `${className} hover:bg-gray-200 dark:hover:bg-gray-600`,
} as const)
: {
class: className,
};
---
{
url ? (
<a
class:list={[className, 'hover:bg-gray-200 dark:hover:bg-gray-600']}
data-tooltip={description}
href={url}
target="_blank"
rel="noopener noreferrer"
>
{icon && <Icon name={icon} color={iconColor} size={16} />}
{name}
</a>
) : (
<div class={className} data-tooltip={description}>
{icon && <Icon name={icon} color={iconColor} size={16} />}
{name}
</div>
)
}
<Typography variant="tag" data-tooltip={description} {...customProps}>
{icon && <Icon name={icon} color={iconColor} size={16} />}
{name}
</Typography>

View file

@ -1,6 +1,7 @@
---
import type { TagsList } from '@/types/shared';
import Tag from './tag.astro';
import Typography from './typography.astro';
export interface Props extends Omit<TagsList, 'title'> {
title?: TagsList['title'];
@ -12,7 +13,7 @@ const { tags, title } = Astro.props;
{
title ? (
<div class="flex flex-col gap-1.5">
<div class="font-medium text-gray-700 dark:text-gray-300">{title}:</div>
<Typography variant="label">{title}:</Typography>
<div class="flex flex-wrap gap-3">
{tags.map((tag) => (
<Tag {...tag} />

View file

@ -9,6 +9,6 @@ export interface Props {
const { dates } = Astro.props;
---
<Typography variant="item-subtitle">
<Typography variant="item-subtitle-secondary">
{formatDateRange(dates)}
</Typography>

View file

@ -1,15 +1,5 @@
---
type TypographyVariant =
| 'main-title'
| 'main-subtitle'
| 'section-title'
| 'section-subtitle'
| 'item-title'
| 'item-title-suffix'
| 'item-subtitle'
| 'tile-title'
| 'tile-subtitle'
| 'paragraph';
type TypographyVariant = keyof typeof variantToElement;
const variantToElement = {
'main-title': 'h1',
@ -17,33 +7,50 @@ const variantToElement = {
'section-title': 'h2',
'section-subtitle': 'h3',
'item-title': 'h3',
'item-title-suffix': 'span',
'item-subtitle': 'p',
'item-subtitle-primary': 'p',
'item-subtitle-secondary': 'p',
'tile-title': 'h4',
'tile-subtitle': 'p',
paragraph: 'p',
label: 'span',
value: 'span',
skill: 'span',
tag: 'div',
button: 'div',
} as const;
const variantToClassName /* tw */ = {
export const variantToClassName: Record<TypographyVariant, string> /* tw */ = {
'main-title': 'text-3xl sm:text-4xl font-extrabold text-gray-900 dark:text-gray-100',
'main-subtitle': 'text-base sm:text-lg font-medium text-gray-700 dark:text-gray-100',
'section-title': 'text-3xl font-extrabold text-gray-900 dark:text-gray-100',
'section-subtitle': 'text-lg font-extrabold text-gray-900 dark:text-gray-100',
'item-title': 'text-xl font-extrabold text-gray-900 dark:text-gray-100',
'item-title-suffix': 'text-xl font-medium text-gray-700 dark:text-gray-100',
'item-subtitle': 'text-sm font-medium text-gray-700 dark:text-gray-100',
'item-subtitle-primary': 'text-base font-semibold leading-snug text-gray-900 dark:text-gray-100',
'item-subtitle-secondary': 'text-sm font-medium text-gray-700 dark:text-gray-100',
'tile-title': 'text-sm font-medium text-gray-700 dark:text-gray-200',
'tile-subtitle': 'text-sm font-normal text-gray-500 dark:text-gray-300',
paragraph: 'text-sm leading-relaxed font-normal text-gray-500 sm:text-base sm:leading-relaxed dark:text-gray-300',
label: 'text-base font-medium text-gray-700 dark:text-gray-300',
value: 'text-base font-normal text-gray-500 dark:text-gray-400',
skill: 'text-sm font-medium text-gray-700 dark:text-gray-300',
tag: 'text-sm font-medium tracking-wide text-gray-700 dark:text-gray-100',
button: 'text-base font-medium text-white',
};
export interface Props extends Omit<astroHTML.JSX.HTMLAttributes, 'slot'> {
variant?: TypographyVariant;
component?: keyof JSX.IntrinsicElements;
interface LinkProps {
href?: string;
target?: string;
rel?: string;
download?: string;
}
const { variant = 'paragraph', component, ...props } = Astro.props;
const Element = component ?? variantToElement[variant];
export interface Props extends Omit<astroHTML.JSX.HTMLAttributes, 'slot'>, LinkProps {
as?: keyof JSX.IntrinsicElements;
variant?: TypographyVariant;
}
const { variant = 'paragraph', as, class: className, ...props } = Astro.props;
const Element = as ?? variantToElement[variant];
---
<Element {...props} class:list={[variantToClassName[variant], props.class]}><slot /></Element>
<Element {...props} class:list={[variantToClassName[variant], className]}><slot /></Element>

View file

@ -17,7 +17,7 @@ const { title, institution, dates, description, links, image } = Astro.props;
<Thumbnail src={image} alt={`${institution} logo`} size="large" />
<div class="flex flex-col">
<Typography variant="item-title">{title}</Typography>
<div class="mb-0.5 text-base font-semibold leading-snug text-gray-900 dark:text-gray-100">{institution}</div>
<Typography variant="item-subtitle-primary" class="mb-0.5">{institution}</Typography>
<Timestamp dates={dates} />
</div>
</div>

View file

@ -18,7 +18,7 @@ const { role, company, dates, description, links, tagsList, image } = Astro.prop
<Thumbnail src={image} alt={`${company} logo`} size="large" />
<div class="flex flex-col">
<Typography variant="item-title">{role}</Typography>
<div class="mb-0.5 text-base font-semibold leading-snug text-gray-900 dark:text-gray-100">{company}</div>
<Typography variant="item-subtitle-primary" class="mb-0.5">{company}</Typography>
<Timestamp dates={dates} />
</div>
</div>

View file

@ -7,6 +7,7 @@ import Photo from '@/components/photo.astro';
import SectionCard from '@/web/components/section-card.astro';
import TagsList from '@/web/components/tags-list.astro';
import Typography from '@/web/components/typography.astro';
import LabelledValue from '@/web/components/labelled-value.astro';
export interface Props extends MainSection {}
@ -43,16 +44,7 @@ const { action, config, description, details, fullName, image, links, role, tags
</div>
<div class="flex flex-col gap-6">
<div class="inline-grid xl:grid-cols-[auto_auto]">
{
details.map(({ label: detailLabel, value }) => (
<div class="w-fit">
<Typography variant="paragraph">
<span class="text-gray-700 dark:text-gray-300">{detailLabel}: </span>
<span class="break-all dark:text-gray-400">{value}</span>
</Typography>
</div>
))
}
{details.map((detail) => <LabelledValue {...detail} />)}
</div>
<div class="flex flex-col gap-4">
<Description content={description} />

View file

@ -15,9 +15,7 @@ const IconWrapper = url ? 'a' : 'div';
<div class="flex h-5 items-center justify-between">
<IconWrapper class="flex gap-2 h-5" {...url && { href: url, target: '_blank', rel: 'noopener noreferrer' }}>
{icon && <Icon name={icon} color={iconColor} size={20} />}
<Typography variant="tile-subtitle">
<span class="text-gray-700 dark:text-gray-300">{name}</span>
</Typography>
<Typography variant="skill">{name}</Typography>
</IconWrapper>
{
description && (

View file

@ -16,7 +16,7 @@ const { author, content, image, links, relation } = Astro.props;
<Thumbnail src={image} alt={author} size="small" />
<div>
<Typography variant="item-title">{author}</Typography>
<Typography variant="item-subtitle">{relation}</Typography>
<Typography variant="item-subtitle-secondary">{relation}</Typography>
</div>
</div>
{