refactor: move all text-related classes to Typography component (#198)
This commit is contained in:
parent
20e1423bf5
commit
aa373785de
12 changed files with 69 additions and 73 deletions
|
|
@ -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]} />
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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} />
|
||||
|
|
|
|||
|
|
@ -9,6 +9,6 @@ export interface Props {
|
|||
const { dates } = Astro.props;
|
||||
---
|
||||
|
||||
<Typography variant="item-subtitle">
|
||||
<Typography variant="item-subtitle-secondary">
|
||||
{formatDateRange(dates)}
|
||||
</Typography>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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} />
|
||||
|
|
|
|||
|
|
@ -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 && (
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue