Skip to content

Commit 4a829f1

Browse files
authored
feat: add document search example (#31)
* feat: add document search example * chore: update sdk versions * chore: cleanup * fix: swap SanityApp for ResourceProvider: - SanityApp now uses remote login for deployments; ResourceProvider should provide the required context without needing to authenticate (since we’re not exposing write actions at the moment)
1 parent a8e7e1d commit 4a829f1

File tree

7 files changed

+510
-37
lines changed

7 files changed

+510
-37
lines changed

apps/sdk-explorer/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
"@sanity/color": "^3.0.6",
1515
"@sanity/icons": "^3.5.7",
1616
"@sanity/logos": "^2.1.13",
17-
"@sanity/sdk": "^0.0.0-rc",
18-
"@sanity/sdk-react": "^0.0.0-rc",
17+
"@sanity/sdk": "0.0.0-alpha.25",
18+
"@sanity/sdk-react": "0.0.0-alpha.25",
1919
"@sanity/types": "^3.72.1",
2020
"@sanity/ui": "^2.11.4",
2121
"@tailwindcss/vite": "^4.0.0",

apps/sdk-explorer/src/App.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {type JSX} from 'react'
55
import {BrowserRouter, Link, Route, Routes} from 'react-router'
66
import {createGlobalStyle} from 'styled-components'
77

8+
import DocumentSearch from './document-collections/DocumentSearch/DocumentSearch'
89
import DocumentTable from './document-collections/DocumentTable/DocumentTable'
910
import PreviewGrid from './document-collections/PreviewGrid/PreviewGrid'
1011
import PreviewList from './document-collections/PreviewList/PreviewList'
@@ -62,9 +63,10 @@ export default function App(): JSX.Element {
6263
<Container width={2} padding={4}>
6364
<Routes>
6465
<Route path="/" element={<Home />} />
66+
<Route path="/document-collections/document-search" element={<DocumentSearch />} />
67+
<Route path="/document-collections/document-table" element={<DocumentTable />} />
6568
<Route path="/document-collections/preview-list" element={<PreviewList />} />
6669
<Route path="/document-collections/preview-grid" element={<PreviewGrid />} />
67-
<Route path="/document-collections/document-table" element={<DocumentTable />} />
6870
<Route path="/groq/movies-by-actor" element={<MoviesByActor />} />
6971
</Routes>
7072
</Container>

apps/sdk-explorer/src/Home.tsx

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {type JSX} from 'react'
33

44
import ExampleCard from './ExampleCard'
55
import DocumentTableImage from './images/DocumentTable.svg'
6+
import DocumentSearchImage from './images/DoumentSearch.svg'
67
import MoviesByActorImage from './images/MoviesByActor.svg'
78
import PreviewGridImage from './images/PreviewGrid.svg'
89
import PreviewListImage from './images/PreviewList.svg'
@@ -42,6 +43,14 @@ export default function Home(): JSX.Element {
4243
</Text>
4344

4445
<Stack space={3}>
46+
<ExampleCard
47+
to="/document-collections/document-search"
48+
title="Document search"
49+
description="An interface for generating dynamic document searches"
50+
hooks={['useDocuments', 'useProjection']}
51+
styling="Sanity UI"
52+
img={DocumentSearchImage}
53+
/>
4554
<ExampleCard
4655
to="/document-collections/document-table"
4756
title="Document table"
@@ -50,14 +59,6 @@ export default function Home(): JSX.Element {
5059
styling="Tailwind"
5160
img={DocumentTableImage}
5261
/>
53-
<ExampleCard
54-
to="/document-collections/preview-list"
55-
title="Preview list"
56-
description="A list of document previews"
57-
hooks={['useDocuments', 'useProjection']}
58-
styling="Sanity UI"
59-
img={PreviewListImage}
60-
/>
6162
<ExampleCard
6263
to="/document-collections/preview-grid"
6364
title="Preview grid"
@@ -66,6 +67,14 @@ export default function Home(): JSX.Element {
6667
styling="Tailwind"
6768
img={PreviewGridImage}
6869
/>
70+
<ExampleCard
71+
to="/document-collections/preview-list"
72+
title="Preview list"
73+
description="A list of document previews"
74+
hooks={['useDocuments', 'useProjection']}
75+
styling="Sanity UI"
76+
img={PreviewListImage}
77+
/>
6978
</Stack>
7079
</Stack>
7180
</Stack>
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import {DocumentHandle, useDocuments, useProjection} from '@sanity/sdk-react'
2+
import {Card, Flex, Label, Stack, Text, TextInput} from '@sanity/ui'
3+
import {type JSX, Suspense, useState} from 'react'
4+
5+
import ExampleLayout from '../../ExampleLayout'
6+
7+
interface Projection {
8+
title: string
9+
overviewText: string
10+
imageUrl: string
11+
}
12+
13+
// Component for rendering an item from the `useDocuments` result
14+
function DocumentResult({documentHandle}: {documentHandle: DocumentHandle}) {
15+
// Use the `useProjection` hook to get the document’s title, overview text, and poster image URL
16+
const {
17+
data: {title, overviewText, imageUrl},
18+
} = useProjection<Projection>({
19+
...documentHandle,
20+
projection: `{
21+
title,
22+
'overviewText': pt::text(overview),
23+
'imageUrl': poster.asset->url,
24+
}`,
25+
})
26+
27+
return (
28+
<Card>
29+
<Flex gap={4} align="flex-start">
30+
<img src={imageUrl} alt="" width={64} height={96} />
31+
<Stack space={4}>
32+
<Text weight="medium">{title}</Text>
33+
<Text size={1} muted style={{maxInlineSize: '76ch'}}>
34+
{overviewText}
35+
</Text>
36+
</Stack>
37+
</Flex>
38+
</Card>
39+
)
40+
}
41+
42+
export default function DocumentSearch(): JSX.Element {
43+
// Create a state variable for keeping track of the search input’s value
44+
const [search, setSearch] = useState('')
45+
46+
const {data: movies} = useDocuments({
47+
filter: '_type == "movie"',
48+
// Pass the `search` state variable to the `useDocuments` hook’s `search` parameter
49+
search,
50+
})
51+
52+
return (
53+
<ExampleLayout
54+
title="Document search"
55+
hooks={['useDocuments', 'useProjection']}
56+
codeUrl="https://github.com/sanity-io/sdk-examples/blob/main/apps/sdk-explorer/src/document-collections/DocumentSearch/DocumentSearch.tsx"
57+
styling="Sanity UI"
58+
summary="This example passes a state variable to the useDocuments hook’s ‘search’ argument, enabling the creation of a dynamic search interface for documents in the targeted dataset(s). (Note: the ‘search’ parameter currently searches for matches across all of a document’s string fields.)"
59+
>
60+
<Stack space={5}>
61+
<Stack space={3}>
62+
<Label htmlFor="movieSearch">Enter your search term:</Label>
63+
{/* Use a search input to set the value of the `search` state variable */}
64+
<TextInput
65+
id="movieSearch"
66+
value={search}
67+
onChange={(e) => setSearch(e.currentTarget.value)}
68+
padding={4}
69+
type="search"
70+
placeholder="Start typing"
71+
/>
72+
</Stack>
73+
74+
{search === ''
75+
? ''
76+
: movies.map((movie) => (
77+
<Suspense key={movie.documentId}>
78+
<DocumentResult documentHandle={movie} />
79+
</Suspense>
80+
))}
81+
</Stack>
82+
</ExampleLayout>
83+
)
84+
}

0 commit comments

Comments
 (0)