refactor: SocialIcons handling

This commit is contained in:
enscribe 2024-09-13 11:45:15 -07:00
parent 3c8ad67774
commit fbeab5a744
No known key found for this signature in database
GPG key ID: 9BBD5C4114E25322
9 changed files with 114 additions and 147 deletions

View file

@ -1,18 +1,35 @@
--- ---
import AvatarComponent from '@/components/ui/avatar' import AvatarComponent from '@/components/ui/avatar'
import { buttonVariants } from '@/components/ui/button'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import Link from '@components/Link.astro' import Link from '@components/Link.astro'
import type { Link as SocialLink } from '@consts'
import type { CollectionEntry } from 'astro:content' import type { CollectionEntry } from 'astro:content'
import { Github, Globe, Linkedin, Twitter } from 'lucide-react' import SocialIcons from './SocialIcons.astro'
type Props = { type Props = {
author: CollectionEntry<'authors'> author: CollectionEntry<'authors'>
linkDisabled?: boolean linkDisabled?: boolean
} }
const { author, linkDisabled = false } = Astro.props const { author, linkDisabled = false } = Astro.props
const { name, avatar, bio, pronouns, github, twitter, linkedin, website } = const {
author.data name,
avatar,
bio,
pronouns,
github,
twitter,
linkedin,
website,
mail,
} = author.data
const socialLinks: SocialLink[] = [
website && { href: website, label: 'Website' },
github && { href: github, label: 'GitHub' },
twitter && { href: twitter, label: 'Twitter' },
linkedin && { href: linkedin, label: 'LinkedIn' },
mail && { href: mail, label: 'Email' },
].filter(Boolean) as SocialLink[]
--- ---
<div <div
@ -47,64 +64,7 @@ const { name, avatar, bio, pronouns, github, twitter, linkedin, website } =
</div> </div>
<p class="text-sm text-muted-foreground">{bio}</p> <p class="text-sm text-muted-foreground">{bio}</p>
</div> </div>
<ul class="flex gap-2"> <SocialIcons links={socialLinks} />
{
github && (
<li>
<Link
href={`https://github.com/${github}`}
aria-label="GitHub"
title="GitHub"
class={buttonVariants({ variant: 'outline', size: 'icon' })}
>
<Github className="size-4" />
</Link>
</li>
)
}
{
twitter && (
<li>
<Link
href={`https://twitter.com/${twitter}`}
aria-label="Twitter"
title="Twitter"
class={buttonVariants({ variant: 'outline', size: 'icon' })}
>
<Twitter className="size-4" />
</Link>
</li>
)
}
{
linkedin && (
<li>
<Link
href={`https://linkedin.com/in/${linkedin}`}
aria-label="LinkedIn"
title="LinkedIn"
class={buttonVariants({ variant: 'outline', size: 'icon' })}
>
<Linkedin className="size-4" />
</Link>
</li>
)
}
{
website && (
<li>
<Link
href={website}
aria-label="Website"
title="Website"
class={buttonVariants({ variant: 'outline', size: 'icon' })}
>
<Globe className="size-4" />
</Link>
</li>
)
}
</ul>
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,5 +1,6 @@
--- ---
import Container from '@components/Container.astro' import Container from '@components/Container.astro'
import { SOCIAL_LINKS } from '@consts'
import SocialIcons from './SocialIcons.astro' import SocialIcons from './SocialIcons.astro'
--- ---
@ -13,7 +14,7 @@ import SocialIcons from './SocialIcons.astro'
&copy; {new Date().getFullYear()} All rights reserved. &copy; {new Date().getFullYear()} All rights reserved.
</p> </p>
</div> </div>
<SocialIcons /> <SocialIcons links={SOCIAL_LINKS} />
</div> </div>
</Container> </Container>
</footer> </footer>

View file

@ -28,13 +28,13 @@ const { title, description, image = '/static/twitter-card.png' } = Astro.props
<meta name="title" content={title} /> <meta name="title" content={title} />
<meta name="description" content={description} /> <meta name="description" content={description} />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"> <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"> <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"> <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="manifest" href="/site.webmanifest"> <link rel="manifest" href="/site.webmanifest" />
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#121212"> <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#121212" />
<meta name="msapplication-TileColor" content="#121212"> <meta name="msapplication-TileColor" content="#121212" />
<meta name="theme-color" content="#121212"> <meta name="theme-color" content="#121212" />
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
<meta property="og:url" content={Astro.url} /> <meta property="og:url" content={Astro.url} />

View file

@ -13,7 +13,7 @@ import logo from '../../public/static/logo.svg'
transition:persist transition:persist
> >
<Container> <Container>
<div class="flex flex-wrap items-center justify-between gap-x-4 py-4"> <div class="flex flex-wrap items-center justify-between gap-4 py-4">
<Link <Link
href="/" href="/"
class="flex flex-shrink-0 items-center gap-2 text-xl font-semibold transition-colors duration-300 hover:text-primary" class="flex flex-shrink-0 items-center gap-2 text-xl font-semibold transition-colors duration-300 hover:text-primary"

View file

@ -1,59 +1,57 @@
--- ---
import { buttonVariants } from '@/components/ui/button' import { buttonVariants } from '@/components/ui/button'
import { cn } from '@/lib/utils'
import Link from '@components/Link.astro' import Link from '@components/Link.astro'
import { SITE } from '@consts' import type { Link as SocialLink } from '@consts'
import { Github, Linkedin, Mail, Rss, Twitter } from 'lucide-react' import {
Github,
Globe,
Linkedin,
Mail,
MessageCircleQuestion,
Rss,
Twitter,
} from 'lucide-react'
interface Props {
links: SocialLink[]
className?: string
}
const { links, className } = Astro.props
const iconMap = {
Website: Globe,
GitHub: Github,
LinkedIn: Linkedin,
Twitter: Twitter,
Email: Mail,
RSS: Rss,
}
const getSocialLink = ({ href, label }: SocialLink) => ({
href: label === 'Email' ? `mailto:${href}` : href,
ariaLabel: label,
Icon: iconMap[label as keyof typeof iconMap] || MessageCircleQuestion,
})
--- ---
<ul class="not-prose flex flex-wrap gap-2" role="list"> <ul class={cn('not-prose flex flex-wrap gap-2', className)} role="list">
{
links.map((link) => {
const { href, ariaLabel, Icon } = getSocialLink(link)
return (
<li> <li>
<Link <Link
href="#" href={href}
aria-label="Twitter" aria-label={ariaLabel}
title="Twitter" title={ariaLabel}
class={buttonVariants({ variant: 'outline', size: 'icon' })} class={buttonVariants({ variant: 'outline', size: 'icon' })}
> >
<Twitter className="size-4" /> <Icon className="size-4" />
</Link>
</li>
<li>
<Link
href="#"
aria-label="GitHub"
title="GitHub"
class={buttonVariants({ variant: 'outline', size: 'icon' })}
>
<Github className="size-4" />
</Link>
</li>
<li>
<Link
href="#"
aria-label="LinkedIn"
title="LinkedIn"
class={buttonVariants({ variant: 'outline', size: 'icon' })}
>
<Linkedin className="size-4" />
</Link>
</li>
<li>
<Link
href="#"
aria-label="Email"
title="Email"
class={buttonVariants({ variant: 'outline', size: 'icon' })}
>
<Mail className="size-4" />
</Link>
</li>
<li>
<Link
href={`${SITE.SITEURL}/rss.xml`}
aria-label="RSS feed"
title="RSS feed"
class={buttonVariants({ variant: 'outline', size: 'icon' })}
>
<Rss className="size-4" />
</Link> </Link>
</li> </li>
)
})
}
</ul> </ul>

View file

@ -34,7 +34,7 @@ function buildToc(headings: Heading[]) {
Table of Contents Table of Contents
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5 transition-transform group-open:rotate-180" class="size-5 transition-transform group-open:rotate-180"
viewBox="0 0 20 20" viewBox="0 0 20 20"
fill="currentColor" fill="currentColor"
> >
@ -45,7 +45,7 @@ function buildToc(headings: Heading[]) {
</svg> </svg>
</summary> </summary>
<nav> <nav>
<ul class="py-3"> <ul class="pt-3">
{toc.map((heading) => <TableOfContentsHeading heading={heading} />)} {toc.map((heading) => <TableOfContentsHeading heading={heading} />)}
</ul> </ul>
</nav> </nav>

View file

@ -6,7 +6,7 @@ export type Site = {
SITEURL: string SITEURL: string
} }
export type NavigationLink = { export type Link = {
href: string href: string
label: string label: string
} }
@ -20,8 +20,15 @@ export const SITE: Site = {
SITEURL: 'https://astro-erudite.vercel.app', SITEURL: 'https://astro-erudite.vercel.app',
} }
export const NAV_LINKS: NavigationLink[] = [ export const NAV_LINKS: Link[] = [
{ href: '/blog', label: 'blog' }, { href: '/blog', label: 'blog' },
{ href: '/authors', label: 'authors' }, { href: '/authors', label: 'authors' },
{ href: '/about', label: 'about' }, { href: '/about', label: 'about' },
] ]
export const SOCIAL_LINKS: Link[] = [
{ href: 'https://github.com/jktrn', label: 'GitHub' },
{ href: 'https://twitter.com/enscry', label: 'Twitter' },
{ href: 'jason@enscribe.dev', label: 'Email' },
{ href: '/rss.xml', label: 'RSS' },
]

View file

@ -4,6 +4,7 @@ pronouns: 'he/him'
avatar: 'https://gravatar.com/avatar/9bfdc4ec972793cf05cb91efce5f4aaaec2a0da1bf4ec34dad0913f1d845faf6.webp?size=256' avatar: 'https://gravatar.com/avatar/9bfdc4ec972793cf05cb91efce5f4aaaec2a0da1bf4ec34dad0913f1d845faf6.webp?size=256'
bio: 'd(-_-)b' bio: 'd(-_-)b'
website: 'https://enscribe.dev' website: 'https://enscribe.dev'
twitter: 'enscry' twitter: 'https://twitter.com/enscry'
github: 'jktrn' github: 'https://github.com/jktrn'
mail: 'jason@enscribe.dev'
--- ---