diff --git a/src/components/Search.js b/src/components/Search.js
index 8251a5d32..e52a1c917 100644
--- a/src/components/Search.js
+++ b/src/components/Search.js
@@ -11,6 +11,14 @@ const INDEX_NAME = 'tailwindcss'
const API_KEY = '5fc87cef58bb80203d2207578309fab6'
const APP_ID = 'KNPXZI5B0M'
+function isTailwindUIURL(url) {
+ return url.startsWith('https://tailwindui.com')
+}
+
+function isExternalURL(url) {
+ return url.startsWith('https://')
+}
+
const SearchContext = createContext()
export function SearchProvider({ children }) {
@@ -40,6 +48,22 @@ export function SearchProvider({ children }) {
onClose,
})
+ useEffect(() => {
+ // Prepend "Components" to Tailwind UI results that are shown in the "recent" view
+ if (!isOpen) {
+ let key = `__DOCSEARCH_RECENT_SEARCHES__${INDEX_NAME}`
+ try {
+ let data = JSON.parse(window.localStorage.getItem(key))
+ for (let item of data) {
+ if (isTailwindUIURL(item.url) && !item.hierarchy.lvl1.startsWith('Components')) {
+ item.hierarchy.lvl1 = `Components / ${item.hierarchy.lvl1}`
+ }
+ }
+ window.localStorage.setItem(key, JSON.stringify(data))
+ } catch {}
+ }
+ }, [isOpen])
+
return (
<>
@@ -57,59 +81,97 @@ export function SearchProvider({ children }) {
{isOpen &&
createPortal(
- {
+ let link = event.target.closest('a')
+ if (!link) return
+ if (isExternalURL(link.href) && link.target !== '_blank') {
+ event.preventDefault()
+ window.open(link.href, '_blank')
+ }
}}
- placeholder="Search documentation"
- onClose={onClose}
- indexName={INDEX_NAME}
- apiKey={API_KEY}
- appId={APP_ID}
- navigator={{
- navigate({ itemUrl }) {
- setIsOpen(false)
- router.push(itemUrl)
- },
- }}
- hitComponent={Hit}
- transformItems={(items) => {
- return items.map((item, index) => {
- // We transform the absolute URL into a relative URL to
- // leverage Next's preloading.
- const a = document.createElement('a')
- a.href = item.url
-
- const hash = a.hash === '#content-wrapper' || a.hash === '#header' ? '' : a.hash
-
- if (item.hierarchy?.lvl0) {
- item.hierarchy.lvl0 = item.hierarchy.lvl0.replace(/&/g, '&')
- }
-
- if (item._highlightResult?.hierarchy?.lvl0?.value) {
- item._highlightResult.hierarchy.lvl0.value =
- item._highlightResult.hierarchy.lvl0.value.replace(/&/g, '&')
- }
-
- return {
- ...item,
- url: `${a.pathname}${hash}`,
- __is_result: () => true,
- __is_parent: () => item.type === 'lvl1' && items.length > 1 && index === 0,
- __is_child: () =>
- item.type !== 'lvl1' &&
- items.length > 1 &&
- items[0].type === 'lvl1' &&
- index !== 0,
- __is_first: () => index === 1,
- __is_last: () => index === items.length - 1 && index !== 0,
- }
- })
- }}
- />,
+ >
+ {
+ return items.map((item, index) => {
+ // We transform the absolute URL into a relative URL to
+ // leverage Next's preloading.
+ const a = document.createElement('a')
+ a.href = item.url
+
+ const hash = a.hash === '#content-wrapper' || a.hash === '#header' ? '' : a.hash
+
+ if (item.hierarchy?.lvl0) {
+ item.hierarchy.lvl0 = item.hierarchy.lvl0.replace(/&/g, '&')
+ }
+
+ if (item._highlightResult?.hierarchy?.lvl0?.value) {
+ item._highlightResult.hierarchy.lvl0.value =
+ item._highlightResult.hierarchy.lvl0.value.replace(/&/g, '&')
+ }
+
+ let isTailwindUI = isTailwindUIURL(item.url)
+
+ return {
+ ...item,
+ hierarchy: {
+ ...item.hierarchy,
+ ...(isTailwindUI
+ ? { lvl1: `${item.product} / ${item.product_category}` }
+ : {}),
+ },
+ url: isTailwindUI ? item.url.split('#')[0] : `${a.pathname}${hash}`,
+ __is_result: () => true,
+ __is_parent: () => item.type === 'lvl1' && items.length > 1 && index === 0,
+ __is_child: () =>
+ item.type !== 'lvl1' &&
+ items.length > 1 &&
+ items[0].type === 'lvl1' &&
+ index !== 0,
+ __is_first: () => index === 1,
+ __is_last: () => index === items.length - 1 && index !== 0,
+ __is_tailwindui: () => isTailwindUI,
+ }
+ })
+ }}
+ />
+
,
document.body
)}
>
@@ -120,12 +182,14 @@ function Hit({ hit, children }) {
return (
{children}
diff --git a/src/css/docsearch.css b/src/css/docsearch.css
index 698036e83..410f78729 100644
--- a/src/css/docsearch.css
+++ b/src/css/docsearch.css
@@ -267,6 +267,8 @@
.DocSearch-Hit-action {
@apply w-6 h-6;
+ background-repeat: no-repeat;
+ background-position: center;
background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m11 9 3 3-3 3' stroke='%23475569' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
@@ -523,3 +525,19 @@
.DocSearch-Hit-action + .DocSearch-Hit-action {
@apply ml-3 pl-3 border-l border-slate-200 dark:border-slate-200/5;
}
+
+.DocSearch-Hit--TailwindUI .DocSearch-Hit-icon {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'%3E%3Cpath d='m6 9 6-3 6 3v6l-6 3-6-3V9Z' fill='%23e0e7ff' /%3E%3Cpath d='m6 9 6 3v7l-6-3V9Z' fill='%23a5b4fc' /%3E%3Cpath d='m18 9-6 3v7l6-3V9Z' fill='%23818cf8' /%3E%3C/svg%3E");
+}
+
+.DocSearch-Hit[aria-selected='true'] .DocSearch-Hit--TailwindUI .DocSearch-Hit-icon {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'%3E%3Cpath d='m6 9 6-3 6 3v6l-6 3-6-3V9Z' fill='%23fff' fill-opacity='.5' /%3E%3Cpath d='m6 9 6 3v7l-6-3V9Z' fill='%23fff' fill-opacity='.6' /%3E%3Cpath d='m18 9-6 3v7l6-3V9Z' fill='%23fff' /%3E%3C/svg%3E");
+}
+
+.DocSearch-Hit--TailwindUI .DocSearch-Hit-action {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' fill='none'%3E%3Cpath stroke='%23475569' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 1h3m0 0v3m0-3L5 5M3.5 1H3a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-.5'/%3E%3C/svg%3E");
+}
+
+.DocSearch-Hit[aria-selected='true'] .DocSearch-Hit--TailwindUI .DocSearch-Hit-action {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' fill='none'%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 1h3m0 0v3m0-3L5 5M3.5 1H3a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-.5'/%3E%3C/svg%3E");
+}