Skip to content

Commit

Permalink
[ENG-1295] Implement a search bar for the API Portal (#293)
Browse files Browse the repository at this point in the history
* save

save

re-run yarn

* upgrade fuse.js

* TODO: integrate fuse.js for searching

* fix outline color

* mod +k for search

* style search button

TODO: add actual search functionality

* styling

* pass allMarkdown to Search.tsx

* basic search + UI working

* add operations to search index

* add demos to search index

* ensure styling looks good on light mode

* search is available on mobile

* fix key for children

* fix forward ref bug
  • Loading branch information
dphuang2 authored Nov 14, 2023
1 parent e5213a4 commit a0417ce
Show file tree
Hide file tree
Showing 29 changed files with 845 additions and 171 deletions.
3 changes: 3 additions & 0 deletions generator/konfig-next-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@mantine/next": "^6.0.13",
"@mantine/notifications": "^6.0.13",
"@mantine/prism": "^6.0.13",
"@mantine/spotlight": "^6.0.13",
"@octokit/auth-app": "^6.0.0",
"@octokit/rest": "^20.0.1",
"@tabler/icons-react": "^2.21.0",
Expand All @@ -48,6 +49,7 @@
"deepmerge": "^4.3.1",
"eslint": "8.41.0",
"eslint-config-next": "13.4.4",
"fuse.js": "^7.0.0",
"github-slugger": "^2.0.0",
"hast-util-to-text": "^3.1.2",
"httpsnippet": "^3.0.1",
Expand Down Expand Up @@ -77,6 +79,7 @@
"unist-util-position": "^4.0.4",
"unist-util-stringify-position": "^3.0.3",
"unist-util-visit": "^4.1.2",
"use-deep-compare": "^1.1.0",
"uuid": "^9.0.0",
"zod": "^3.21.4"
},
Expand Down
10 changes: 9 additions & 1 deletion generator/konfig-next-app/src/components/DemoHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { HeaderWrapper } from './HeaderWrapper'
import { TABS } from './HeaderButton'
import { HeaderTabs } from './HeaderTabs'
import type { generateLogoLink } from '@/utils/generate-logo-link'
import { MarkdownPageProps } from '@/utils/generate-props-for-markdown-page'

export const DemoHeader = observer(
({
Expand All @@ -19,10 +20,12 @@ export const DemoHeader = observer(
owner,
repo,
logo,
allMarkdown,
}: {
opened: boolean
setOpened: Dispatch<SetStateAction<boolean>>
state: PortalState
allMarkdown: MarkdownPageProps['allMarkdown']
sandbox?: boolean
hasDocumentation: boolean
demos: string[]
Expand All @@ -32,8 +35,12 @@ export const DemoHeader = observer(
logo: ReturnType<typeof generateLogoLink>
}) => {
return (
<HeaderWrapper hasLightAndDarkLogo={typeof logo !== 'string'}>
<HeaderWrapper
allMarkdown={allMarkdown}
hasLightAndDarkLogo={typeof logo !== 'string'}
>
<LayoutHeader
allMarkdown={allMarkdown}
logo={logo}
breakpoint="sm"
opened={opened}
Expand All @@ -42,6 +49,7 @@ export const DemoHeader = observer(
/>
<HeaderTabs
hasLightAndDarkLogo={typeof logo !== 'string'}
allMarkdown={allMarkdown}
hasDocumentation={hasDocumentation}
demos={demos}
owner={owner}
Expand Down
4 changes: 4 additions & 0 deletions generator/konfig-next-app/src/components/DemoPortal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import type { generateLogoLink } from '@/utils/generate-logo-link'
import { useNavbarStyles } from '@/utils/use-navbar-styles'
import { NavbarSectionLabel } from './NavbarSectionLabel'
import { navbarLinkColor } from './NavbarLink'
import { MarkdownPageProps } from '@/utils/generate-props-for-markdown-page'

type DemosInput = Demo[]

Expand Down Expand Up @@ -172,13 +173,15 @@ export const DemoPortal = observer(
owner,
repo,
logo,
allMarkdown,
}: {
state: PortalState
sandbox?: boolean
refreshSandbox?: () => void
hasDocumentation: boolean
omitOwnerAndRepo: boolean
owner: string
allMarkdown: MarkdownPageProps['allMarkdown']
repo: string
logo: ReturnType<typeof generateLogoLink>
}) => {
Expand Down Expand Up @@ -315,6 +318,7 @@ export const DemoPortal = observer(
repo={repo}
omitOwnerAndRepo={omitOwnerAndRepo}
hasDocumentation={hasDocumentation}
allMarkdown={allMarkdown}
demos={state.demos.map((demo) => demo.id)}
opened={opened}
setOpened={setOpened}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { navbarOffsetBreakpoint } from '@/utils/navbar-offset-breakpoint'
import { HeaderTabs } from './HeaderTabs'
import { TABS } from './HeaderButton'
import type { generateLogoLink } from '@/utils/generate-logo-link'
import { MarkdownPageProps } from '@/utils/generate-props-for-markdown-page'

export function DocumentationHeader({
opened,
Expand All @@ -15,6 +16,7 @@ export function DocumentationHeader({
owner,
repo,
logo,
allMarkdown,
}: {
opened: boolean
setOpened: Dispatch<SetStateAction<boolean>>
Expand All @@ -24,10 +26,15 @@ export function DocumentationHeader({
owner: string
repo: string
logo: ReturnType<typeof generateLogoLink>
allMarkdown: MarkdownPageProps['allMarkdown']
}) {
return (
<HeaderWrapper hasLightAndDarkLogo={typeof logo !== 'string'}>
<HeaderWrapper
allMarkdown={allMarkdown}
hasLightAndDarkLogo={typeof logo !== 'string'}
>
<LayoutHeader
allMarkdown={allMarkdown}
breakpoint={navbarOffsetBreakpoint}
opened={opened}
setOpened={setOpened}
Expand All @@ -42,6 +49,7 @@ export function DocumentationHeader({
demos={demos}
currentTab={TABS.documentation}
omitOwnerAndRepo={omitOwnerAndRepo}
allMarkdown={allMarkdown}
/>
</HeaderWrapper>
)
Expand Down
3 changes: 2 additions & 1 deletion generator/konfig-next-app/src/components/HeaderButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ export const TABS = {
sdks: 'SDKs',
} as const

export type TabType = typeof TABS
export type Tab = (typeof TABS)[keyof typeof TABS]

const ICONS = {
export const ICONS = {
[TABS.documentation]: IconBook,
[TABS.reference]: IconCode,
[TABS.demos]: IconTerminal,
Expand Down
161 changes: 79 additions & 82 deletions generator/konfig-next-app/src/components/HeaderTabs.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import {
Box,
Flex,
Group,
MediaQuery,
Menu,
useMantineTheme,
} from '@mantine/core'
import { Box, Flex, Group, Menu, clsx, useMantineTheme } from '@mantine/core'
import { HeaderTab } from './HeaderTab'
import { useBasePath } from '@/utils/use-base-path'
import { HeaderButton, TABS, Tab } from './HeaderButton'
import { IconMenu } from '@tabler/icons-react'
import Link from 'next/link'
import { getClickableStyles } from '@/utils/get-clickable-styles'
import { Search } from './Search'
import { MarkdownPageProps } from '@/utils/generate-props-for-markdown-page'

export function HeaderTabs({
currentTab,
Expand All @@ -20,6 +15,7 @@ export function HeaderTabs({
hasDocumentation,
omitOwnerAndRepo,
owner,
allMarkdown,
repo,
hasLightAndDarkLogo,
}: {
Expand All @@ -31,6 +27,7 @@ export function HeaderTabs({
repo: string
hasLightAndDarkLogo: boolean
omitOwnerAndRepo?: boolean
allMarkdown: MarkdownPageProps['allMarkdown']
}) {
const docsPath = useDocsPath({ omitOwnerAndRepo })
const referencePath = useReferencePath({ omitOwnerAndRepo })
Expand All @@ -51,84 +48,83 @@ export function HeaderTabs({
const theme = useMantineTheme()
return (
<Box h="45%">
<MediaQuery largerThan="xs" styles={{ display: 'none' }}>
<Box w="100%" h="100%">
<Menu
shadow="xl"
// opened={true}
withinPortal={true}
styles={{
dropdown: {
...getClickableStyles(theme),
},
}}
offset={5}
width="95%"
radius="sm"
>
<Menu.Target>
<Flex
px="lg"
style={{ cursor: 'pointer' }}
h="100%"
align="center"
justify="space-between"
>
<HeaderButton
hasLightDarkMode={hasLightAndDarkLogo}
tab={currentTab}
/>
<IconMenu
color={
hasLightAndDarkLogo
? theme.colorScheme === 'dark'
? theme.white
: theme.black
: theme.white
}
size="0.9rem"
/>
</Flex>
</Menu.Target>
<MediaQuery largerThan="xs" styles={{ display: 'none' }}>
<Menu.Dropdown>
{Object.values(TABS)
.filter((tab) => tab !== currentTab)
.map((tab) => {
if (tab === TABS.documentation && !hasDocumentation) {
return null
}
if (tab === TABS.demos && demos.length === 0) {
return null
}
return (
<Menu.Item key={tab}>
<Link
style={{ textDecoration: 'none', color: 'inherit' }}
target={tab === TABS.sdks ? '_blank' : undefined}
href={linkForTab(tab)}
>
<HeaderButton
hasLightDarkMode={hasLightAndDarkLogo}
noColor
tab={tab}
/>
</Link>
</Menu.Item>
)
})}
</Menu.Dropdown>
</MediaQuery>
</Menu>
</Box>
</MediaQuery>
<MediaQuery smallerThan="xs" styles={{ display: 'none' }}>
<Box className="sm:hidden" w="100%" h="100%">
<Menu
shadow="xl"
// opened={true}
withinPortal={true}
styles={{
dropdown: {
...getClickableStyles(theme),
},
}}
offset={5}
width="95%"
radius="sm"
>
<Menu.Target>
<Flex
px="lg"
style={{ cursor: 'pointer' }}
h="100%"
align="center"
justify="space-between"
>
<HeaderButton
hasLightDarkMode={hasLightAndDarkLogo}
tab={currentTab}
/>
<IconMenu
color={
hasLightAndDarkLogo
? theme.colorScheme === 'dark'
? theme.white
: theme.black
: theme.white
}
size="0.9rem"
/>
</Flex>
</Menu.Target>
<Menu.Dropdown className="sm:hidden">
{Object.values(TABS)
.filter((tab) => tab !== currentTab)
.map((tab) => {
if (tab === TABS.documentation && !hasDocumentation) {
return null
}
if (tab === TABS.demos && demos.length === 0) {
return null
}
return (
<Menu.Item key={tab}>
<Link
style={{ textDecoration: 'none', color: 'inherit' }}
target={tab === TABS.sdks ? '_blank' : undefined}
href={linkForTab(tab)}
>
<HeaderButton
hasLightDarkMode={hasLightAndDarkLogo}
noColor
tab={tab}
/>
</Link>
</Menu.Item>
)
})}
</Menu.Dropdown>
</Menu>
</Box>
<div
className={clsx(
'h-full hidden sm:flex items-center justify-between px-3'
)}
>
<Group
h="100%"
style={{
alignItems: 'flex-end',
}}
px="sm"
noWrap
spacing={0}
>
Expand Down Expand Up @@ -166,7 +162,8 @@ export function HeaderTabs({
link={linkForTab(TABS.sdks)}
/>
</Group>
</MediaQuery>
<Search />
</div>
</Box>
)
}
Expand Down
12 changes: 10 additions & 2 deletions generator/konfig-next-app/src/components/HeaderWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { Header, useMantineTheme } from '@mantine/core'
import { PropsWithChildren } from 'react'
import { TITLE_OFFSET_PX } from './DemoTitle'
import { MarkdownPageProps } from '@/utils/generate-props-for-markdown-page'
import { SpotlightProvider } from './SpotlightProvider'

export function HeaderWrapper({
children,
hasLightAndDarkLogo,
}: PropsWithChildren<{ hasLightAndDarkLogo: boolean }>) {
allMarkdown,
}: PropsWithChildren<{
hasLightAndDarkLogo: boolean
allMarkdown: MarkdownPageProps['allMarkdown']
}>) {
const theme = useMantineTheme()
return (
<Header
Expand All @@ -21,7 +27,9 @@ export function HeaderWrapper({
}}
height={TITLE_OFFSET_PX}
>
{children}
<SpotlightProvider allMarkdown={allMarkdown}>
{children}
</SpotlightProvider>
</Header>
)
}
Loading

0 comments on commit a0417ce

Please sign in to comment.