Skip to content

Commit

Permalink
Update Sanity example for App Router.
Browse files Browse the repository at this point in the history
  • Loading branch information
stipsan committed Sep 19, 2023
1 parent bd6cedd commit 9bd9998
Show file tree
Hide file tree
Showing 90 changed files with 1,111 additions and 1,111 deletions.
46 changes: 46 additions & 0 deletions examples/cms-sanity/app/(blog)/AuthorAvatar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { sanityFetch } from '@/lib/fetch'
import { urlForImage } from '@/lib/image'
import Image from 'next/image'
import Balancer from 'react-wrap-balancer'

const query = /* groq */ `*[_type == "author" && _id == $id][0]`

export async function AuthorAvatar(params: { id: string }) {
const data = await sanityFetch<any>({
query,
params,
tags: [`author:${params.id}`],
})
const { name = 'Anonymous', image } = data
return (
<div className="flex items-center">
<div className="relative mr-4 h-12 w-12">
<Image
src={
image?.asset?._ref
? urlForImage(image).height(96).width(96).fit('crop').url()
: 'https://source.unsplash.com/96x96/?face'
}
className="rounded-full"
height={96}
width={96}
alt={image?.alt || ''}
/>
</div>
<div className="text-xl font-bold">
<Balancer>{name}</Balancer>
</div>
</div>
)
}

export function AuthorAvatarFallback() {
return (
<div className="flex animate-pulse items-center">
<div className="relative mr-4 h-12 w-12 rounded-full bg-gray-800/50 opacity-25" />
<div className="text-xl font-bold opacity-30">
Fetching author&hellip;
</div>
</div>
)
}
27 changes: 27 additions & 0 deletions examples/cms-sanity/app/(blog)/BlogHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use client'

import Link from 'next/link'
import { usePathname } from 'next/navigation'
import Balancer from 'react-wrap-balancer'

export default function BlogHeader({ title }: { title: string }) {
const pathname = usePathname()
if (pathname === '/') {
return (
<header className="mx-5 mb-10 mt-16 flex flex-col items-center md:mb-12 md:flex-row md:justify-between">
<h1 className="text-6xl font-bold leading-tight tracking-tighter md:pr-8 md:text-8xl">
<Balancer>{title}</Balancer>
</h1>
</header>
)
}
return (
<header className="mx-5">
<h2 className="mb-20 mt-8 text-2xl font-bold leading-tight tracking-tight md:text-4xl md:tracking-tighter">
<Link href="/" className="hover:underline">
<Balancer>{title}</Balancer>
</Link>
</h2>
</header>
)
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
import { urlForImage } from '@/lib/image'
import cn from 'classnames'
import Image from 'next/image'
import Link from 'next/link'
import { urlForImage } from '../lib/sanity'

export default function CoverImage({ title, slug, image: source, priority }) {
interface CoverImageProps {
title: string
slug?: string
image?: { asset?: any; alt?: string }
priority?: boolean
}

export default function CoverImage(props: CoverImageProps) {
const { title, slug, image: source, priority } = props
const image = source?.asset?._ref ? (
<div
className={cn('shadow-small', {
'hover:shadow-medium transition-shadow duration-200': slug,
'transition-shadow duration-200 hover:shadow-medium': slug,
})}
>
<Image
className="w-full h-auto"
className="h-auto w-full"
width={2000}
height={1000}
alt={`Cover Image for ${title}`}
alt={source?.alt || ''}
src={urlForImage(source).height(1000).width(2000).url()}
sizes="100vw"
priority={priority}
Expand All @@ -27,7 +35,7 @@ export default function CoverImage({ title, slug, image: source, priority }) {
return (
<div className="sm:mx-0">
{slug ? (
<Link href={`/posts/${slug}`} aria-label={title}>
<Link href={`/${slug}`} aria-label={title}>
{image}
</Link>
) : (
Expand Down
68 changes: 68 additions & 0 deletions examples/cms-sanity/app/(blog)/MoreStories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import Link from 'next/link'
import { Suspense } from 'react'

import { sanityFetch } from '@/lib/fetch'
import { postFields } from '@/lib/queries'
import { AuthorAvatar, AuthorAvatarFallback } from './AuthorAvatar'
import CoverImage from './CoverImage'
import Date from './PostDate'

const query = /* groq */ `*[_type == "post" && _id != $skip] | order(date desc, _updatedAt desc) [0...$limit] {
${postFields}
}`

export default async function MoreStories(params: {
skip: string
limit: number
}) {
const data = await sanityFetch<any>({ query, params, tags: ['post'] })

return (
<>
<div className="mb-32 grid grid-cols-1 gap-y-20 md:grid-cols-2 md:gap-x-16 md:gap-y-32 lg:gap-x-32">
{data.map((post: any) => {
const {
_id,
title = 'Untitled',
slug,
mainImage,
excerpt,
author,
} = post
return (
<article key={_id}>
<div className="mb-5">
<CoverImage
slug={slug?.current}
title={title}
image={mainImage}
priority={false}
/>
</div>
<h3 className="mb-3 text-3xl leading-snug">
{slug?.current ? (
<Link href={`/${slug.current}`} className="hover:underline">
{title}
</Link>
) : (
title
)}
</h3>
<div className="mb-4 text-lg">
<Date dateString={post.publishedAt} />
</div>
{excerpt && (
<p className="mb-4 text-lg leading-relaxed">{excerpt}</p>
)}
{author?._ref && (
<Suspense fallback={<AuthorAvatarFallback />}>
<AuthorAvatar id={author._ref} />
</Suspense>
)}
</article>
)
})}
</div>
</>
)
}
25 changes: 25 additions & 0 deletions examples/cms-sanity/app/(blog)/PostBody.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.portableText {
@apply text-lg leading-relaxed;
}

.portableText p,
.portableText ul,
.portableText ol,
.portableText blockquote {
@apply my-6;
}

.portableText h2 {
@apply mb-4 mt-12 text-3xl leading-snug;
}

.portableText h3 {
@apply mb-4 mt-8 text-2xl leading-snug;
}

.portableText a {
@apply text-blue-500 underline;
}
.portableText a:hover {
@apply text-blue-800;
}
24 changes: 24 additions & 0 deletions examples/cms-sanity/app/(blog)/PostBody.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* This component uses Portable Text to render a post body.
*
* You can learn more about Portable Text on:
* https://www.sanity.io/docs/block-content
* https://github.com/portabletext/react-portabletext
* https://portabletext.org/
*
*/
import { PortableText } from '@portabletext/react'

import styles from './PostBody.module.css'

export default function PostBody({
body,
}: {
body: React.ComponentProps<typeof PortableText>['value']
}) {
return (
<div className={`mx-auto max-w-2xl ${styles.portableText}`}>
<PortableText value={body} />
</div>
)
}
11 changes: 11 additions & 0 deletions examples/cms-sanity/app/(blog)/PostDate.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { format, parseISO } from 'date-fns'
import Balancer from 'react-wrap-balancer'

export default function PostDate({ dateString }: { dateString: string }) {
const date = parseISO(dateString)
return (
<time dateTime={dateString}>
<Balancer>{format(date, 'LLLL d, yyyy')}</Balancer>
</time>
)
}
57 changes: 57 additions & 0 deletions examples/cms-sanity/app/(blog)/PreviewBanner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
'use client'

import { useEffect, useState, useTransition } from 'react'
import { useRouter } from 'next/navigation'

function useRefresh() {
const router = useRouter()
const [loading, startTransition] = useTransition()
const [again, setAgain] = useState(false)
useEffect(() => {
function handleMessage(event: MessageEvent) {
if (event.data?.sanity && event.data.type === 'reload') {
startTransition(() => {
router.refresh()
setAgain(true)
})
}
}
window.addEventListener('message', handleMessage)
return () => window.removeEventListener('message', handleMessage)
}, [router])

useEffect(() => {
if (!again) return
const timeout = setTimeout(
() =>
startTransition(() => {
setAgain(false)
router.refresh()
}),
1000,
)
return () => clearTimeout(timeout)
}, [again])

return loading || again
}

export default function PreviewBanner() {
const loading = useRefresh()

return (
<div
className={`bg-black p-3 text-center text-white ${
loading ? 'animate-pulse' : ''
}`}
>
{'Previewing drafts. '}
<a
className="underline transition hover:opacity-50"
href="/api/disable-draft"
>
Back to published
</a>
</div>
)
}
Loading

0 comments on commit 9bd9998

Please sign in to comment.