blog: sharpen cards, search, toc
This commit is contained in:
@@ -15,11 +15,11 @@ export function PostCard({ slug, title, date, excerpt, tags = [], author, readin
|
|||||||
whileHover={shouldReduceMotion ? undefined : { y: -2 }}
|
whileHover={shouldReduceMotion ? undefined : { y: -2 }}
|
||||||
transition={{ duration: 0.35, delay: shouldReduceMotion ? 0 : Math.min(index * 0.04, 0.18), ease: [0.22, 1, 0.36, 1] }}
|
transition={{ duration: 0.35, delay: shouldReduceMotion ? 0 : Math.min(index * 0.04, 0.18), ease: [0.22, 1, 0.36, 1] }}
|
||||||
viewport={{ once: true, amount: 0.2 }}
|
viewport={{ once: true, amount: 0.2 }}
|
||||||
className="group relative scroll-mt-20 rounded-2xl border border-border/90 bg-canvas p-5 shadow-card transition-[background-color,border-color,box-shadow] duration-200 ease-out hover:border-ink/25 hover:bg-surface/40 hover:shadow-card-hover dark:hover:border-ink/35 sm:p-7"
|
className="group relative scroll-mt-20 rounded-lg border border-border/90 bg-canvas p-5 shadow-card transition-[background-color,border-color,box-shadow] duration-200 ease-out hover:border-ink/25 hover:bg-surface/40 hover:shadow-card-hover dark:hover:border-ink/35 sm:p-7"
|
||||||
>
|
>
|
||||||
<Link href={`/blog/${slug}/`} className="block">
|
<Link href={`/blog/${slug}/`} className="block">
|
||||||
{coverImage && (
|
{coverImage && (
|
||||||
<div className="mb-5 overflow-hidden rounded-xl border border-border/80 bg-surface">
|
<div className="mb-5 overflow-hidden rounded-md border border-border/80 bg-surface">
|
||||||
<img
|
<img
|
||||||
src={coverImage}
|
src={coverImage}
|
||||||
alt={`Cover image for ${title}`}
|
alt={`Cover image for ${title}`}
|
||||||
@@ -45,7 +45,7 @@ export function PostCard({ slug, title, date, excerpt, tags = [], author, readin
|
|||||||
{tags && tags.length > 0 && (
|
{tags && tags.length > 0 && (
|
||||||
<div className="mt-5 flex flex-wrap gap-2">
|
<div className="mt-5 flex flex-wrap gap-2">
|
||||||
{tags.slice(0, 3).map((tag) => (
|
{tags.slice(0, 3).map((tag) => (
|
||||||
<Link key={tag} href={`/blog/tags/${tagToSlug(tag)}/`} className="rounded-full border border-border bg-surface/70 px-3 py-1 text-xs text-ink-soft transition-colors duration-200 hover:border-accent/60 hover:text-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent">
|
<Link key={tag} href={`/blog/tags/${tagToSlug(tag)}/`} className="rounded-sm border border-border bg-surface/70 px-3 py-1 font-mono text-[11px] uppercase tracking-wider text-ink-soft transition-colors duration-200 hover:border-accent/60 hover:text-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent">
|
||||||
{tag}
|
{tag}
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ export function PostSearch({ posts }: PostSearchProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<section aria-labelledby="posts-search-heading" className="space-y-8">
|
<section aria-labelledby="posts-search-heading" className="space-y-8">
|
||||||
<div className="space-y-5 rounded-xl border border-border bg-surface/30 p-4 sm:p-5">
|
<div className="space-y-5 rounded-lg border border-border bg-surface/30 p-4 sm:p-5">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<label id="posts-search-heading" htmlFor="post-search" className="block text-sm font-medium text-ink">
|
<label id="posts-search-heading" htmlFor="post-search" className="block text-sm font-medium text-ink">
|
||||||
Search posts
|
Search posts
|
||||||
@@ -158,7 +158,7 @@ export function PostSearch({ posts }: PostSearchProps) {
|
|||||||
type="search"
|
type="search"
|
||||||
value={query}
|
value={query}
|
||||||
onChange={(event) => setQuery(event.target.value)}
|
onChange={(event) => setQuery(event.target.value)}
|
||||||
placeholder="Search title, excerpt, tag, author, or slug"
|
placeholder="Search…"
|
||||||
className="min-w-0 flex-1 rounded-lg border border-border bg-canvas px-3 py-2 text-sm text-ink outline-none transition-colors placeholder:text-ink-soft/70 focus:border-accent focus:ring-2 focus:ring-accent/20"
|
className="min-w-0 flex-1 rounded-lg border border-border bg-canvas px-3 py-2 text-sm text-ink outline-none transition-colors placeholder:text-ink-soft/70 focus:border-accent focus:ring-2 focus:ring-accent/20"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
@@ -167,7 +167,7 @@ export function PostSearch({ posts }: PostSearchProps) {
|
|||||||
disabled={!query}
|
disabled={!query}
|
||||||
className="rounded-lg border border-border px-3 py-2 text-sm text-ink-soft transition-colors hover:border-accent/50 hover:text-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent disabled:cursor-not-allowed disabled:opacity-50"
|
className="rounded-lg border border-border px-3 py-2 text-sm text-ink-soft transition-colors hover:border-accent/50 hover:text-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent disabled:cursor-not-allowed disabled:opacity-50"
|
||||||
>
|
>
|
||||||
Clear search
|
Clear
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -185,7 +185,7 @@ export function PostSearch({ posts }: PostSearchProps) {
|
|||||||
type="button"
|
type="button"
|
||||||
aria-pressed={isSelected}
|
aria-pressed={isSelected}
|
||||||
onClick={() => setSelectedTag(isSelected ? null : tag.slug)}
|
onClick={() => setSelectedTag(isSelected ? null : tag.slug)}
|
||||||
className="rounded-full border border-border bg-canvas px-3 py-1 text-xs text-ink-soft transition-colors hover:border-accent/50 hover:text-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent aria-pressed:border-accent aria-pressed:bg-accent/10 aria-pressed:text-accent"
|
className="rounded-sm border border-border bg-canvas px-3 py-1 font-mono text-[11px] uppercase tracking-wider text-ink-soft transition-colors hover:border-accent/50 hover:text-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent aria-pressed:border-accent aria-pressed:bg-accent/10 aria-pressed:text-accent"
|
||||||
>
|
>
|
||||||
{tag.label} <span className="font-mono text-ink-soft/70">{tag.count}</span>
|
{tag.label} <span className="font-mono text-ink-soft/70">{tag.count}</span>
|
||||||
</button>
|
</button>
|
||||||
@@ -209,7 +209,7 @@ export function PostSearch({ posts }: PostSearchProps) {
|
|||||||
}}
|
}}
|
||||||
className="self-start rounded-lg border border-border px-3 py-1.5 text-sm text-ink-soft transition-colors hover:border-accent/50 hover:text-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent sm:self-auto"
|
className="self-start rounded-lg border border-border px-3 py-1.5 text-sm text-ink-soft transition-colors hover:border-accent/50 hover:text-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent sm:self-auto"
|
||||||
>
|
>
|
||||||
Clear filters
|
Clear
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -222,7 +222,7 @@ export function PostSearch({ posts }: PostSearchProps) {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<p className="text-ink-soft">No posts match your search.</p>
|
<p className="text-ink-soft">No matches.</p>
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -75,8 +75,8 @@ export function TableOfContents() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<nav aria-label="Table of contents" className="lg:sticky lg:top-20">
|
<nav aria-label="Table of contents" className="lg:sticky lg:top-20">
|
||||||
<h4 className="font-sans text-xs font-semibold uppercase tracking-wider text-ink-soft mb-3">
|
<h4 className="section-label mb-3">
|
||||||
On this page
|
INDEX
|
||||||
</h4>
|
</h4>
|
||||||
<ul className="space-y-1">
|
<ul className="space-y-1">
|
||||||
{headings.map((heading) => (
|
{headings.map((heading) => (
|
||||||
|
|||||||
Reference in New Issue
Block a user