refactor: migrate components to Preact

This commit is contained in:
Stefan Imhoff
2023-04-04 17:40:19 +02:00
parent a15c4ef149
commit 208b9d9418
21 changed files with 219 additions and 115 deletions

View File

@@ -1,6 +1,7 @@
---
import { Sprite } from 'astro-icon';
import Link from '../components/Link.astro';
import { Link } from '../components';
export interface Props {
backLink?: string;

View File

@@ -1,20 +0,0 @@
---
interface Props {
as?: string;
children?: any;
class?: string;
}
const { as = 'h2', class: className, ...props } = Astro.props;
const Element = as;
---
<Element
class:list={[
'text-5 font-black tracking-tight mbe-10 mbs-16 first-of-type:mbs-0 dark:font-extrabold',
className,
]}
{...props}
>
<slot />
</Element>

View File

@@ -0,0 +1,28 @@
import cx from 'classnames';
import type { ComponentChild, FunctionalComponent } from 'preact';
interface Props {
as?: any;
class?: string;
children: ComponentChild;
}
export const Headline: FunctionalComponent<Props> = ({
as = 'h2',
class: className,
children,
...props
}) => {
const Tag = as;
const classes = cx(
'text-5 font-black tracking-tight mbe-10 mbs-16 first-of-type:mbs-0 dark:font-extrabold',
className
);
return (
<Tag class={classes} {...props}>
{children}
</Tag>
);
};

View File

@@ -1,5 +1,6 @@
---
import { LegalDate } from './LegalDate';
import { LegalDate } from '.';
import { site } from '../data/site';
---

View File

@@ -1,22 +0,0 @@
---
import type { HTMLAttributes } from 'astro/types';
type Props = HTMLAttributes<'a'>;
const props = { ...Astro.props };
const { class: className } = props;
if (typeof props.href !== 'string') props.href = '#';
const isExternal = props.href.startsWith('http');
---
<a
class:list={['link', className, { external: isExternal }]}
href={props.href}
rel={isExternal ? 'nofollow noopener noreferrer' : null}
target={isExternal ? '_blank' : null}
{...props}
>
<slot />
</a>

27
src/components/Link.tsx Normal file
View File

@@ -0,0 +1,27 @@
import cx from 'classnames';
import type { FunctionalComponent, JSX } from 'preact';
interface Props extends JSX.HTMLAttributes<HTMLAnchorElement> {}
export const Link: FunctionalComponent<Props> = ({
class: className,
children,
href = '#',
...props
}: Props) => {
const isExternal = (href as string).startsWith('http');
const classes = cx('link', { external: isExternal }, className as string);
return (
<a
class={classes}
href={href}
rel={isExternal ? 'nofollow noopener noreferrer' : undefined}
target={isExternal ? '_blank' : undefined}
{...props}
>
{children}
</a>
);
};

View File

@@ -1,5 +1,7 @@
---
import Link from './Link.astro';
import cx from 'classnames';
import { Link } from '.';
import navigation from '../data/navigation.json';
@@ -12,9 +14,10 @@ const currentPath = new URL(Astro.request.url).pathname;
navigation.map(({ title, url }) => (
<li class="mie-[10px] xs:mie-[15px]">
<Link
class={`text-3 font-light decoration-4 underline-offset-auto hover:underline hover:decoration-shibui-900/20 dark:hover:decoration-shibui-100/20 ${
currentPath === url && 'underline !decoration-accent decoration-4'
}`}
class={cx(
'text-3 font-light decoration-4 underline-offset-auto hover:underline hover:decoration-shibui-900/20 dark:hover:decoration-shibui-100/20',
{ 'underline !decoration-accent decoration-4': currentPath === url }
)}
href={url}
>
{title}

View File

@@ -1,8 +1,8 @@
---
import RSSLink from './RSSLink.astro';
import Subnavigation from './Subnavigation.astro';
import Legal from './Legal.astro';
import RSSLink from './RSSLink.astro';
import SocialLinks from './SocialLinks.astro';
import Subnavigation from './Subnavigation.astro';
import UpLink from './UpLink.astro';
---

View File

@@ -1,8 +1,7 @@
---
import { Sprite } from 'astro-icon';
import Link from './Link.astro';
import Subsubheadline from './Subsubheadline.astro';
import { Link, Subsubheadline } from '.';
---
<div class="grow mbe-5 sm:mbe-0">

View File

@@ -1,7 +1,7 @@
---
import { Sprite } from 'astro-icon';
import Link from './Link.astro';
import { Link } from '.';
import data from '../data/social-links.json';
---

View File

@@ -1,20 +0,0 @@
---
interface Props {
as?: string;
children?: any;
class?: string;
}
const { as = 'h3', class: className, ...props } = Astro.props;
const Element = as;
---
<Element
class:list={[
'text-4 font-black tracking-tight mbe-8 mbs-14 first-of-type:mbs-0 dark:font-extrabold',
className,
]}
{...props}
>
<slot />
</Element>

View File

@@ -0,0 +1,28 @@
import cx from 'classnames';
import type { ComponentChild, FunctionalComponent } from 'preact';
interface Props {
as?: any;
class?: string;
children: ComponentChild;
}
export const Subheadline: FunctionalComponent<Props> = ({
as = 'h3',
class: className,
children,
...props
}) => {
const Tag = as;
const classes = cx(
'text-4 font-black tracking-tight mbe-8 mbs-14 first-of-type:mbs-0 dark:font-extrabold',
className
);
return (
<Tag class={classes} {...props}>
{children}
</Tag>
);
};

View File

@@ -1,7 +1,9 @@
---
import cx from 'classnames';
import data from '../data/subnavigation.json';
import Link from './Link.astro';
import { Link } from '.';
const currentPath = new URL(Astro.request.url).pathname;
---
@@ -13,9 +15,10 @@ const currentPath = new URL(Astro.request.url).pathname;
<li>
<Link
href={url}
class={`font-light decoration-4 underline-offset-auto hover:underline hover:decoration-shibui-900/20 dark:hover:decoration-shibui-100/20 ${
currentPath === url && 'underline !decoration-accent decoration-4'
}`}
class={cx(
'font-light decoration-4 underline-offset-auto hover:underline hover:decoration-shibui-900/20 dark:hover:decoration-shibui-100/20',
{ 'underline !decoration-accent decoration-4': currentPath === url }
)}
>
{title}
</Link>

View File

@@ -1,20 +0,0 @@
---
interface Props {
as?: string;
children?: any;
class?: string;
}
const { as = 'h4', class: className, ...props } = Astro.props;
const Element = as;
---
<Element
class:list={[
'text-3 font-black tracking-tight mbe-5 mbs-14 first-of-type:mbs-0 dark:font-extrabold',
className,
]}
{...props}
>
<slot />
</Element>

View File

@@ -0,0 +1,28 @@
import cx from 'classnames';
import type { ComponentChild, FunctionalComponent } from 'preact';
interface Props {
as?: any;
class?: string;
children: ComponentChild;
}
export const Subsubheadline: FunctionalComponent<Props> = ({
as = 'h4',
class: className,
children,
...props
}) => {
const Tag = as;
const classes = cx(
'text-3 font-black tracking-tight mbe-5 mbs-14 first-of-type:mbs-0 dark:font-extrabold',
className
);
return (
<Tag class={classes} {...props}>
{children}
</Tag>
);
};

28
src/components/Text.tsx Normal file
View File

@@ -0,0 +1,28 @@
import cx from 'classnames';
import type { ComponentChild, FunctionalComponent } from 'preact';
interface Props {
as?: any;
class?: string;
children: ComponentChild;
}
export const Text: FunctionalComponent<Props> = ({
as = 'p',
class: className,
children,
...props
}) => {
const Tag = as;
const classes = cx(
'text-3 font-normal tracking-normal mbe-10 mbs-0 last-of-type:mbe-0 dark:font-light',
className
);
return (
<Tag class={classes} {...props}>
{children}
</Tag>
);
};

View File

@@ -0,0 +1,24 @@
import cx from 'classnames';
import type { FunctionalComponent, JSX } from 'preact';
import { Link } from '.';
interface Props extends JSX.HTMLAttributes<HTMLAnchorElement> {}
export const TextLink: FunctionalComponent<Props> = ({
class: className,
children,
...props
}: Props) => {
const classes = cx(
'font-semibold text-shibui-950 underline decoration-shibui-900/20 decoration-4 underline-offset-auto no-common-ligatures no-discretionary-ligatures hover:!decoration-accent focus:!decoration-accent dark:text-shibui-200/[0.87] dark:decoration-shibui-100/20',
className as string
);
return (
<Link class={classes} {...props}>
{children}
</Link>
);
};

View File

@@ -1,17 +0,0 @@
---
interface Props {
as?: string;
children?: any;
class?: string;
}
const { as = 'h1', class: className, ...props } = Astro.props;
const Element = as;
---
<Element
class:list={['text-7 font-black tracking-tight mbe-13 dark:font-extrabold', className]}
{...props}
>
<slot />
</Element>

25
src/components/Title.tsx Normal file
View File

@@ -0,0 +1,25 @@
import cx from 'classnames';
import type { ComponentChild, FunctionalComponent } from 'preact';
interface Props {
as?: any;
class?: string;
children: ComponentChild;
}
export const Title: FunctionalComponent<Props> = ({
as = 'h1',
class: className,
children,
...props
}) => {
const Tag = as;
const classes = cx('text-7 font-black tracking-tight mbe-13 dark:font-extrabold', className);
return (
<Tag class={classes} {...props}>
{children}
</Tag>
);
};

View File

@@ -1,7 +1,7 @@
---
import { Sprite } from 'astro-icon';
import Link from './Link.astro';
import { Link } from '.';
---
<div class="flex flex-1 justify-end">

8
src/components/index.ts Normal file
View File

@@ -0,0 +1,8 @@
export * from './Headline';
export * from './LegalDate';
export * from './Link';
export * from './Subheadline';
export * from './Subsubheadline';
export * from './Text';
export * from './TextLink';
export * from './Title';