Skip to content

Commit

Permalink
Merge pull request #125 from timlrx/search-improvements
Browse files Browse the repository at this point in the history
Search improvements
  • Loading branch information
timlrx authored Jul 30, 2023
2 parents fa0e1eb + 24f4554 commit f21911d
Show file tree
Hide file tree
Showing 11 changed files with 179 additions and 175 deletions.
7 changes: 7 additions & 0 deletions .changeset/gold-dingos-breathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'pliny': patch
---

Improve kbar styling
Simplify kbar component
Add new KBarButton and AlgoliaButton wrapper which toggles their respective modals on click event
11 changes: 11 additions & 0 deletions .changeset/pre.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"mode": "pre",
"tag": "beta",
"initialVersions": {
"@pliny/config": "0.0.0",
"pliny": "0.1.0"
},
"changesets": [
"gold-dingos-breathe"
]
}
8 changes: 8 additions & 0 deletions packages/pliny/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# pliny

## 0.1.1-beta.0

### Patch Changes

- 306917e: Improve kbar styling
Simplify kbar component
Add new KBarButton and AlgoliaButton wrapper which toggles their respective modals on click event

## 0.1.0

### Minor Changes
Expand Down
6 changes: 5 additions & 1 deletion packages/pliny/add-use-client.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ import globby from 'globby'
const chunkPaths = await globby('chunk*')
for (const path of chunkPaths) {
const data = fs.readFileSync(path, 'utf8')
if (/useState|useEffect|useRef|useCallback|useMemo|useTheme|useRouter/.test(data)) {
if (
/useState|useEffect|useRef|useCallback|useContext|useMemo|useTheme|useRouter|useRegisterActions|useMatches|useKBar/.test(
data
)
) {
console.log(path)
const insert = Buffer.from('"use client"\n')
fs.writeFileSync(path, insert + data)
Expand Down
4 changes: 2 additions & 2 deletions packages/pliny/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "pliny",
"description": "Main entry point for pliny components",
"homepage": "https://github.com/timlrx/pliny",
"version": "0.1.0",
"version": "0.1.1-beta.0",
"type": "module",
"exports": {
"./*": "./*",
Expand Down Expand Up @@ -32,7 +32,7 @@
"github-slugger": "^1.4.0",
"image-size": "1.0.0",
"js-yaml": "4.1.0",
"kbar": "0.1.0-beta.40",
"kbar": "0.1.0-beta.41",
"next-contentlayer": "^0.3.4",
"next-themes": "^0.2.1",
"remark": "^14.0.2",
Expand Down
20 changes: 20 additions & 0 deletions packages/pliny/src/search/AlgoliaButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { DetailedHTMLProps, HTMLAttributes, useContext } from 'react'
import { AlgoliaSearchContext } from './Algolia'

/**
* Button wrapper component that triggers the Algolia modal on click.
*
* @return {*}
*/
export const AlgoliaButton = ({
children,
...rest
}: DetailedHTMLProps<HTMLAttributes<HTMLButtonElement>, HTMLButtonElement>) => {
const { query } = useContext(AlgoliaSearchContext)

return (
<button {...rest} onClick={() => query.toggle()}>
{children}
</button>
)
}
52 changes: 8 additions & 44 deletions packages/pliny/src/search/KBar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { useState, useEffect, useCallback, FC, ReactNode, useMemo } from 'react'
import { useState, useEffect, FC, ReactNode } from 'react'
import type { Action } from 'kbar'
import { KBarProvider } from 'kbar'
import { useRouter } from 'next/navigation.js'
import { KBarModal as KBarModalType } from './KBarModal'
import { KBarModal } from './KBarModal'
import { CoreContent, MDXDocument } from '../utils/contentlayer'
import { formatDate } from '../utils/formatDate'

Expand All @@ -15,8 +16,6 @@ export interface KBarConfig {
kbarConfig: KBarSearchProps
}

let KBarModal: typeof KBarModalType | null = null

/**
* Command palette like search component with kbar - `ctrl-k` to open the palette.
* To toggle the modal or search from child components, use the search context:
Expand All @@ -36,28 +35,9 @@ export const KBarSearchProvider: FC<{
const router = useRouter()
const { searchDocumentsPath, defaultActions } = kbarConfig
const [searchActions, setSearchActions] = useState<Action[]>([])
const [modalLoaded, setModalLoaded] = useState(false)
const [dataLoaded, setDataLoaded] = useState(false)

const importDocSearchModalIfNeeded = useCallback(() => {
if (KBarModal) {
return Promise.resolve()
}
return Promise.all([import('./KBarModal')]).then(([{ KBarModal: Modal }]) => {
KBarModal = Modal
})
}, [])

useEffect(() => {
const handleKeyDown = (event) => {
if (event.ctrlKey && event.key === 'k') {
event.preventDefault()
importDocSearchModalIfNeeded().then(() => {
setModalLoaded(true)
window.removeEventListener('keydown', handleKeyDown)
})
}
}
const mapPosts = (posts: CoreContent<MDXDocument>[]) => {
const startingActions = Array.isArray(defaultActions)
? defaultActions
Expand Down Expand Up @@ -94,31 +74,15 @@ export const KBarSearchProvider: FC<{
setSearchActions(actions)
setDataLoaded(true)
}
if (!modalLoaded) {
window.addEventListener('keydown', handleKeyDown)
}
if (!dataLoaded) {
fetchData()
}
return () => {
/*removes event listener on cleanup*/
window.removeEventListener('keydown', handleKeyDown)
}
}, [importDocSearchModalIfNeeded, modalLoaded, dataLoaded, router, searchDocumentsPath])
}, [defaultActions, dataLoaded, router, searchDocumentsPath])

return (
<>
{modalLoaded && KBarModal ? (
<KBarModal
actions={searchActions}
searchDocumentsPath={searchDocumentsPath}
isLoading={!dataLoaded}
>
{children}
</KBarModal>
) : (
children
)}
</>
<KBarProvider actions={defaultActions}>
<KBarModal actions={searchActions} isLoading={!dataLoaded} />
{children}
</KBarProvider>
)
}
20 changes: 20 additions & 0 deletions packages/pliny/src/search/KBarButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { DetailedHTMLProps, HTMLAttributes } from 'react'
import { useKBar } from 'kbar'

/**
* Button wrapper component that triggers the KBar modal on click.
*
* @return {*}
*/
export const KBarButton = ({
children,
...rest
}: DetailedHTMLProps<HTMLAttributes<HTMLButtonElement>, HTMLButtonElement>) => {
const { query } = useKBar()

return (
<button {...rest} onClick={() => query.toggle()}>
{children}
</button>
)
}
106 changes: 93 additions & 13 deletions packages/pliny/src/search/KBarModal.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,97 @@
import { FC, ReactNode } from 'react'
import { KBarProvider, Action } from 'kbar'
import { Portal } from './KBarPortal'
import {
KBarPortal,
KBarSearch,
KBarAnimator,
KBarPositioner,
KBarResults,
useMatches,
Action,
useRegisterActions,
} from 'kbar'

export const KBarModal = ({ actions, isLoading }: { actions: Action[]; isLoading: boolean }) => {
useRegisterActions(actions, [actions])

export const KBarModal: FC<{
children: ReactNode
actions: Action[]
searchDocumentsPath: string
isLoading: boolean
}> = ({ actions, children, isLoading }) => {
return (
<KBarProvider actions={actions}>
<Portal isLoading={isLoading} />
{children}
</KBarProvider>
<KBarPortal>
<KBarPositioner className="bg-gray-300/50 p-4 backdrop-blur backdrop-filter dark:bg-black/50">
<KBarAnimator className="w-full max-w-xl">
<div className="overflow-hidden rounded-2xl border border-gray-100 bg-gray-50 dark:border-gray-800 dark:bg-gray-900">
<div className="flex items-center space-x-4 p-4">
<span className="block w-5">
<svg
className="text-gray-400 dark:text-gray-300"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
/>
</svg>
</span>
<KBarSearch className="h-8 w-full bg-transparent text-slate-600 placeholder-slate-400 focus:outline-none dark:text-slate-200 dark:placeholder-slate-500" />
<span className="inline-block whitespace-nowrap rounded border border-slate-400/70 px-1.5 align-middle font-medium leading-4 tracking-wide text-slate-500 [font-size:10px] dark:border-slate-600 dark:text-slate-400">
ESC
</span>
</div>
{!isLoading && <RenderResults />}
{isLoading && (
<div className="block border-t border-gray-100 px-4 py-8 text-center text-gray-400 dark:border-gray-800 dark:text-gray-600">
Loading...
</div>
)}
</div>
</KBarAnimator>
</KBarPositioner>
</KBarPortal>
)
}

const RenderResults = () => {
const { results } = useMatches()

if (results.length) {
return (
<KBarResults
items={results}
onRender={({ item, active }) => (
<div>
{typeof item === 'string' ? (
<div className="pt-3">
<div className="block border-t border-gray-100 px-4 pb-2 pt-6 text-xs font-semibold uppercase text-primary-600 dark:border-gray-800">
{item}
</div>
</div>
) : (
<div
className={`block cursor-pointer px-4 py-2 ${
active
? 'bg-primary-600 text-gray-100'
: 'text-gray-700 dark:text-gray-100 bg-transparent'
}`}
>
{item.subtitle && (
<div className={`${active ? 'text-gray-200' : 'text-gray-400'} text-xs`}>
{item.subtitle}
</div>
)}
<div>{item.name}</div>
</div>
)}
</div>
)}
/>
)
} else {
return (
<div className="block border-t border-gray-100 px-4 py-8 text-center text-gray-400 dark:border-gray-800 dark:text-gray-600">
No results for your search...
</div>
)
}
}
Loading

0 comments on commit f21911d

Please sign in to comment.