Skip to content

Commit cd8dfd0

Browse files
authored
Add search to Copilot Cookbook (#53108)
1 parent d419bba commit cd8dfd0

File tree

4 files changed

+71
-26
lines changed

4 files changed

+71
-26
lines changed

src/frame/components/context/CategoryLandingContext.tsx

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,7 @@ import {
55
FeaturedLink,
66
getFeaturedLinksFromReq,
77
} from 'src/landings/components/ProductLandingContext'
8-
9-
export type TocItem = {
10-
fullPath: string
11-
title: string
12-
intro?: string
13-
childTocItems?: Array<{
14-
fullPath: string
15-
title: string
16-
intro: string
17-
octicon?: string
18-
category?: string[]
19-
complexity?: string[]
20-
industry?: string[]
21-
}>
22-
}
8+
import { TocItem } from '#src/landings/types.ts'
239

2410
export type CategoryLandingContextT = {
2511
title: string

src/landings/components/CategoryLanding.tsx

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { useState } from 'react'
12
import { useRouter } from 'next/router'
23
import cx from 'classnames'
34
import { CookBookArticleCard } from './CookBookArticleCard'
@@ -11,14 +12,31 @@ import { useCategoryLandingContext } from 'src/frame/components/context/Category
1112
import { ClientSideRedirects } from 'src/rest/components/ClientSideRedirects'
1213
import { RestRedirect } from 'src/rest/components/RestRedirect'
1314
import { Breadcrumbs } from 'src/frame/components/page-header/Breadcrumbs'
15+
import { ArticleCardItems } from '../types'
1416

1517
export const CategoryLanding = () => {
1618
const router = useRouter()
1719
//const { t } = useTranslation('toc')
1820
const { title, intro, tocItems } = useCategoryLandingContext()
1921

2022
// tocItems contains directories and its children, we only want the child articles
21-
const onlyFlatItems = tocItems.flatMap((item) => item.childTocItems || [])
23+
const onlyFlatItems: ArticleCardItems = tocItems.flatMap((item) => item.childTocItems || [])
24+
25+
const [searchResults, setSearchResults] = useState<ArticleCardItems>(onlyFlatItems)
26+
27+
const handleSearch = (query: string) => {
28+
const results = onlyFlatItems.filter((token) => {
29+
return Object.values(token).some((value) => {
30+
if (typeof value === 'string') {
31+
return value.toLowerCase().includes(query.toLowerCase())
32+
} else if (Array.isArray(value)) {
33+
return value.some((item) => item.toLowerCase().includes(query.toLowerCase()))
34+
}
35+
return false
36+
})
37+
})
38+
setSearchResults(results)
39+
}
2240

2341
return (
2442
<DefaultLayout>
@@ -44,14 +62,14 @@ export const CategoryLanding = () => {
4462
<div className="pt-8">
4563
<div className="py-5 border-bottom">
4664
<div className="col-lg-4 col-sm-12 float-md-left pb-3 mr-5 ml-1">
47-
<h2>Explore {onlyFlatItems.length} prompt articles</h2>
65+
<h2>Explore {searchResults.length} prompt articles</h2>
4866
</div>
4967
<div>
50-
<CookBookFilter />
68+
<CookBookFilter tokens={onlyFlatItems} onSearch={handleSearch} />
5169
</div>
5270
</div>
5371
<ul className="clearfix gutter-md-spacious">
54-
{onlyFlatItems.map((item, index) => (
72+
{searchResults.map((item, index) => (
5573
<li key={index} className="col-md-4 col-sm-12 list-style-none float-left p-4">
5674
<CookBookArticleCard
5775
title={item.title}

src/landings/components/CookBookFilter.tsx

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,39 @@
11
import { TextInput, ActionMenu, ActionList, Button } from '@primer/react'
22
import { SearchIcon } from '@primer/octicons-react'
3+
import { useRef, useEffect } from 'react'
4+
import { ArticleCardItems } from '#src/landings/types.ts'
5+
6+
type Props = {
7+
tokens: ArticleCardItems
8+
onSearch: (query: string) => void
9+
isSearchOpen?: boolean
10+
}
11+
12+
export const CookBookFilter = ({ onSearch, isSearchOpen }: Props) => {
13+
const inputRef = useRef<HTMLInputElement>(null)
14+
useEffect(() => {
15+
if (isSearchOpen) {
16+
inputRef.current?.focus()
17+
}
18+
}, [isSearchOpen])
319

4-
export const CookBookFilter = () => {
520
return (
621
<>
722
<div>
8-
<TextInput
9-
leadingVisual={SearchIcon}
10-
className="float-lg-left m-1"
11-
sx={{ minWidth: ['stretch', 'stretch', 'stretch', 250] }}
12-
placeholder="Search articles"
13-
/>
23+
<form onSubmit={(e) => e.preventDefault()}>
24+
<TextInput
25+
leadingVisual={SearchIcon}
26+
className="float-lg-left m-1"
27+
sx={{ minWidth: ['stretch', 'stretch', 'stretch', 250] }}
28+
placeholder="Search articles"
29+
ref={inputRef}
30+
autoComplete="false"
31+
onChange={(e) => {
32+
const query = e.target.value || ''
33+
onSearch(query)
34+
}}
35+
/>
36+
</form>
1437
</div>
1538
<div className="d-flex">
1639
<ActionMenu>

src/landings/types.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
export type BaseTocItem = {
2+
fullPath: string
3+
title: string
4+
intro?: string
5+
}
6+
7+
export type ChildTocItem = BaseTocItem & {
8+
octicon?: string
9+
category?: string[]
10+
complexity?: string[]
11+
industry?: string[]
12+
}
13+
14+
export type TocItem = BaseTocItem & {
15+
childTocItems?: ChildTocItem[]
16+
}
17+
18+
export type ArticleCardItems = ChildTocItem[]

0 commit comments

Comments
 (0)