From a6b9e22f4ecaecbc0e52e783c2c018df09ab4dda Mon Sep 17 00:00:00 2001 From: Reid Barber Date: Tue, 4 Nov 2025 10:26:18 -0600 Subject: [PATCH 01/10] fix llms.txt link --- packages/dev/s2-docs/pages/react-aria/getting-started.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dev/s2-docs/pages/react-aria/getting-started.mdx b/packages/dev/s2-docs/pages/react-aria/getting-started.mdx index 37f581a7c33..ec814548f3d 100644 --- a/packages/dev/s2-docs/pages/react-aria/getting-started.mdx +++ b/packages/dev/s2-docs/pages/react-aria/getting-started.mdx @@ -73,7 +73,7 @@ If you're building a full component library, download a pre-built [Storybook](ht ### Working with AI -Use the menu at the top of each page in the docs to open or copy it into your favorite AI assistant. We also have an [MCP server](mcp.html) which can be used directly in your IDE, and [llms.txt](../llms.txt) which can help AI agents navigate the docs. +Use the menu at the top of each page in the docs to open or copy it into your favorite AI assistant. We also have an [MCP server](mcp.html) which can be used directly in your IDE, and [llms.txt](llms.txt) which can help AI agents navigate the docs. ## Build a component from scratch From 07019a7dfc96c72539cd035addfe727b5044a478 Mon Sep 17 00:00:00 2001 From: Reid Barber Date: Tue, 4 Nov 2025 10:28:36 -0600 Subject: [PATCH 02/10] hide mobile ToC if there is just one section --- packages/dev/s2-docs/src/Layout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dev/s2-docs/src/Layout.tsx b/packages/dev/s2-docs/src/Layout.tsx index 7608a89d3f1..a4ea38f0230 100644 --- a/packages/dev/s2-docs/src/Layout.tsx +++ b/packages/dev/s2-docs/src/Layout.tsx @@ -216,7 +216,7 @@ export function Layout(props: PageProps & {children: ReactElement}) { })}>
0 ? : null} + toc={(currentPage.tableOfContents?.[0]?.children?.length ?? 0) > 1 ? : null} pages={pages} currentPage={currentPage} />
From 76a547aae783e2ef09be53bc0cbfd9fb24a9426c Mon Sep 17 00:00:00 2001 From: Reid Barber Date: Tue, 4 Nov 2025 10:45:52 -0600 Subject: [PATCH 03/10] add copy feedback to icons search --- packages/dev/s2-docs/src/IconSearchView.tsx | 70 ++++++++++++++++----- 1 file changed, 56 insertions(+), 14 deletions(-) diff --git a/packages/dev/s2-docs/src/IconSearchView.tsx b/packages/dev/s2-docs/src/IconSearchView.tsx index fae26461399..e8ea0b9c4d7 100644 --- a/packages/dev/s2-docs/src/IconSearchView.tsx +++ b/packages/dev/s2-docs/src/IconSearchView.tsx @@ -2,6 +2,7 @@ 'use client'; import {Autocomplete, GridLayout, ListBox, ListBoxItem, Size, useFilter, Virtualizer} from 'react-aria-components'; +import CheckmarkCircle from '@react-spectrum/s2/icons/CheckmarkCircle'; import Close from '@react-spectrum/s2/icons/Close'; import {Content, Heading, IllustratedMessage, pressScale, SearchField, Skeleton, Text} from '@react-spectrum/s2'; import {focusRing, iconStyle, style} from '@react-spectrum/s2/style' with {type: 'macro'}; @@ -10,7 +11,7 @@ import {iconAliases} from './iconAliases.js'; import icons from '/packages/@react-spectrum/s2/s2wf-icons/*.svg'; // eslint-disable-next-line monorepo/no-internal-import import NoSearchResults from '@react-spectrum/s2/illustrations/linear/NoSearchResults'; -import React, {useCallback, useMemo, useRef} from 'react'; +import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; export const iconList = Object.keys(icons).map(name => ({id: name.replace(/^S2_Icon_(.*?)(Size\d+)?_2.*/, '$1'), icon: icons[name].default})); @@ -42,19 +43,34 @@ const itemStyle = style({ cursor: 'default' }); -let handleCopyImport = (id: string) => { - navigator.clipboard.writeText(`import ${id} from '@react-spectrum/s2/icons/${id}';`).then(() => { - // noop - }).catch(() => { - // noop - }); -}; - interface IconSearchViewProps { filteredItems: typeof iconList } export function IconSearchView({filteredItems}: IconSearchViewProps) { + let [copiedId, setCopiedId] = useState(null); + let timeout = useRef | null>(null); + + useEffect(() => { + return () => { + if (timeout.current) { + clearTimeout(timeout.current); + } + }; + }, []); + + let handleCopyImport = useCallback((id: string) => { + if (timeout.current) { + clearTimeout(timeout.current); + } + navigator.clipboard.writeText(`import ${id} from '@react-spectrum/s2/icons/${id}';`).then(() => { + setCopiedId(id); + timeout.current = setTimeout(() => setCopiedId(null), 2000); + }).catch(() => { + // noop + }); + }, []); + return ( ( @@ -69,18 +86,18 @@ export function IconSearchView({filteredItems}: IconSearchViewProps) { Try a different search term. )}> - {item => } + {item => } ); } -function IconItem({item}) { +function IconItem({item, isCopied = false}: {item: typeof iconList[number], isCopied?: boolean}) { let Icon = item.icon; let ref = useRef(null); return ( - + {isCopied ? : }
- {item.id} + {isCopied ? 'Copied!' : item.id}
); @@ -175,6 +192,30 @@ export function IconCards() { // also compare for substrings in the icon's actual name return textValue != null && contains(textValue, inputValue); }, [contains]); + + let [copiedId, setCopiedId] = useState(null); + let timeout = useRef | null>(null); + + useEffect(() => { + return () => { + if (timeout.current) { + clearTimeout(timeout.current); + } + }; + }, []); + + let handleCopyImport = useCallback((id: string) => { + if (timeout.current) { + clearTimeout(timeout.current); + } + navigator.clipboard.writeText(`import ${id} from '@react-spectrum/s2/icons/${id}';`).then(() => { + setCopiedId(id); + timeout.current = setTimeout(() => setCopiedId(null), 2000); + }).catch(() => { + // noop + }); + }, []); + return (
@@ -185,6 +226,7 @@ export function IconCards() { items={iconList} layout="grid" className={style({height: 440, width: '100%', maxHeight: '100%', overflow: 'auto', scrollPaddingY: 4})} + dependencies={[copiedId]} renderEmptyState={() => ( @@ -192,7 +234,7 @@ export function IconCards() { Try a different search term. )}> - {item => } + {item => }
From fd96de97ba87b7eead77812a3d7ba82321711e06 Mon Sep 17 00:00:00 2001 From: Reid Barber Date: Tue, 4 Nov 2025 11:07:15 -0600 Subject: [PATCH 04/10] add message to press icon items to copy --- packages/dev/s2-docs/src/IconSearchView.tsx | 93 ++++++++++++--------- 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/packages/dev/s2-docs/src/IconSearchView.tsx b/packages/dev/s2-docs/src/IconSearchView.tsx index e8ea0b9c4d7..b719fdbfc48 100644 --- a/packages/dev/s2-docs/src/IconSearchView.tsx +++ b/packages/dev/s2-docs/src/IconSearchView.tsx @@ -9,7 +9,8 @@ import {focusRing, iconStyle, style} from '@react-spectrum/s2/style' with {type: import {iconAliases} from './iconAliases.js'; // @ts-ignore import icons from '/packages/@react-spectrum/s2/s2wf-icons/*.svg'; -// eslint-disable-next-line monorepo/no-internal-import + +import InfoCircle from '@react-spectrum/s2/icons/InfoCircle'; import NoSearchResults from '@react-spectrum/s2/illustrations/linear/NoSearchResults'; import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; @@ -72,23 +73,29 @@ export function IconSearchView({filteredItems}: IconSearchViewProps) { }, []); return ( - - handleCopyImport(item.toString())} - items={filteredItems} - layout="grid" - className={style({width: '100%', scrollPaddingY: 4})} - dependencies={[copiedId]} - renderEmptyState={() => ( - - - No results - Try a different search term. - - )}> - {item => } - - + <> +
+ + Press an item to copy its import statement +
+ + handleCopyImport(item.toString())} + items={filteredItems} + layout="grid" + className={style({width: '100%', scrollPaddingY: 4})} + dependencies={[copiedId]} + renderEmptyState={() => ( + + + No results + Try a different search term. + + )}> + {item => } + + + ); } @@ -217,27 +224,33 @@ export function IconCards() { }, []); return ( - -
- - - handleCopyImport(item.toString())} - items={iconList} - layout="grid" - className={style({height: 440, width: '100%', maxHeight: '100%', overflow: 'auto', scrollPaddingY: 4})} - dependencies={[copiedId]} - renderEmptyState={() => ( - - - No results - Try a different search term. - - )}> - {item => } - - -
-
+ <> + +
+ +
+ + Press an item to copy its import statement +
+ + handleCopyImport(item.toString())} + items={iconList} + layout="grid" + className={style({height: 440, width: '100%', maxHeight: '100%', overflow: 'auto', scrollPaddingY: 4})} + dependencies={[copiedId]} + renderEmptyState={() => ( + + + No results + Try a different search term. + + )}> + {item => } + + +
+
+ ); } From 609054927456f51fdb2aca34acba27831dba424a Mon Sep 17 00:00:00 2001 From: Reid Barber Date: Tue, 4 Nov 2025 11:16:20 -0600 Subject: [PATCH 05/10] lint --- packages/dev/s2-docs/src/IconSearchView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dev/s2-docs/src/IconSearchView.tsx b/packages/dev/s2-docs/src/IconSearchView.tsx index b719fdbfc48..113b16daa2b 100644 --- a/packages/dev/s2-docs/src/IconSearchView.tsx +++ b/packages/dev/s2-docs/src/IconSearchView.tsx @@ -9,8 +9,8 @@ import {focusRing, iconStyle, style} from '@react-spectrum/s2/style' with {type: import {iconAliases} from './iconAliases.js'; // @ts-ignore import icons from '/packages/@react-spectrum/s2/s2wf-icons/*.svg'; - import InfoCircle from '@react-spectrum/s2/icons/InfoCircle'; +// eslint-disable-next-line monorepo/no-internal-import import NoSearchResults from '@react-spectrum/s2/illustrations/linear/NoSearchResults'; import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; From ba5c2d756bd965e66317873bf1c9a6573ea141bc Mon Sep 17 00:00:00 2001 From: Reid Barber Date: Tue, 4 Nov 2025 11:30:52 -0600 Subject: [PATCH 06/10] fix llms.txt link to open in new tab --- packages/dev/s2-docs/pages/react-aria/getting-started.mdx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/dev/s2-docs/pages/react-aria/getting-started.mdx b/packages/dev/s2-docs/pages/react-aria/getting-started.mdx index ec814548f3d..22218e209a9 100644 --- a/packages/dev/s2-docs/pages/react-aria/getting-started.mdx +++ b/packages/dev/s2-docs/pages/react-aria/getting-started.mdx @@ -9,6 +9,7 @@ import {ShadcnCommand} from '../../src/ShadcnCommand'; import {StarterKits} from '../../src/StarterKits'; import docs from 'docs:react-aria-components'; import '../../tailwind/tailwind.css'; +import {Link} from '@react-spectrum/s2'; export const section = 'Getting started'; export const tags = ['introduction', 'installation']; @@ -73,7 +74,7 @@ If you're building a full component library, download a pre-built [Storybook](ht ### Working with AI -Use the menu at the top of each page in the docs to open or copy it into your favorite AI assistant. We also have an [MCP server](mcp.html) which can be used directly in your IDE, and [llms.txt](llms.txt) which can help AI agents navigate the docs. +Use the menu at the top of each page in the docs to open or copy it into your favorite AI assistant. We also have an [MCP server](mcp.html) which can be used directly in your IDE, and lms.txt which can help AI agents navigate the docs. ## Build a component from scratch From 7f70e99fa32223b38a87a21fd2b959ed780b0cd8 Mon Sep 17 00:00:00 2001 From: Reid Barber Date: Tue, 4 Nov 2025 12:41:25 -0600 Subject: [PATCH 07/10] remove Archived releases header link --- packages/dev/s2-docs/src/ReleasesList.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/dev/s2-docs/src/ReleasesList.tsx b/packages/dev/s2-docs/src/ReleasesList.tsx index 2f97c78e46b..2874614d850 100644 --- a/packages/dev/s2-docs/src/ReleasesList.tsx +++ b/packages/dev/s2-docs/src/ReleasesList.tsx @@ -19,12 +19,7 @@ export function ReleasesList({pages}: {pages: Page[]}) {

{renderHTMLfromMarkdown(release.exports?.description, {})}

))} -
-
-

Archived releases

-
-

For all previous releases or React Spectrum v3, see the Archived releases page.

-
+

For all previous releases or React Spectrum v3, see the Archived releases page.

); } From 7e4bd5719b4a93f6e3c520e64a439cb0e56a2c79 Mon Sep 17 00:00:00 2001 From: Reid Barber Date: Tue, 4 Nov 2025 12:45:59 -0600 Subject: [PATCH 08/10] fix overflow on useDrop page --- packages/dev/s2-docs/pages/react-aria/useDrop.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/dev/s2-docs/pages/react-aria/useDrop.mdx b/packages/dev/s2-docs/pages/react-aria/useDrop.mdx index 1f7e1c93c53..ce1dbeeebb8 100644 --- a/packages/dev/s2-docs/pages/react-aria/useDrop.mdx +++ b/packages/dev/s2-docs/pages/react-aria/useDrop.mdx @@ -198,7 +198,7 @@ function DropTarget() { ); } return ( -
+
{contents}
); @@ -309,7 +309,7 @@ function DropTarget() { onDrop: onEvent }); return ( -
    +
      {events.map((e, i) =>
    • {e}
    • )}
    ); From 9f3373cd20462df2db7f37ba73f6ca549ab1fe2c Mon Sep 17 00:00:00 2001 From: Reid Barber Date: Tue, 4 Nov 2025 13:53:28 -0600 Subject: [PATCH 09/10] increase text size for info message --- packages/dev/s2-docs/src/IconSearchView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/dev/s2-docs/src/IconSearchView.tsx b/packages/dev/s2-docs/src/IconSearchView.tsx index 113b16daa2b..cd6d240e062 100644 --- a/packages/dev/s2-docs/src/IconSearchView.tsx +++ b/packages/dev/s2-docs/src/IconSearchView.tsx @@ -76,7 +76,7 @@ export function IconSearchView({filteredItems}: IconSearchViewProps) { <>
    - Press an item to copy its import statement + Press an item to copy its import statement
    - Press an item to copy its import statement + Press an item to copy its import statement
    Date: Tue, 4 Nov 2025 14:25:58 -0600 Subject: [PATCH 10/10] dedupe icons search code where possible --- packages/dev/s2-docs/pages/s2/Icons.mdx | 4 +- .../s2-docs/scripts/generateMarkdownDocs.mjs | 6 +- packages/dev/s2-docs/src/IconSearchView.tsx | 190 +++++++++--------- packages/dev/s2-docs/src/SearchMenu.tsx | 20 +- 4 files changed, 100 insertions(+), 120 deletions(-) diff --git a/packages/dev/s2-docs/pages/s2/Icons.mdx b/packages/dev/s2-docs/pages/s2/Icons.mdx index 3c1d22a6f70..b0728970116 100644 --- a/packages/dev/s2-docs/pages/s2/Icons.mdx +++ b/packages/dev/s2-docs/pages/s2/Icons.mdx @@ -1,7 +1,7 @@ import {Layout} from '../../src/Layout'; import {InstallCommand} from '../../src/InstallCommand'; import {Command} from '../../src/Command'; -import {IconCards} from '../../src/IconSearchView'; +import {IconsPageSearch} from '../../src/IconSearchView'; import {IconColors} from '../../src/IconColors'; import {IconSizes} from '../../src/IconSizes'; import {InlineAlert, Heading, Content} from '@react-spectrum/s2'; @@ -24,7 +24,7 @@ import Edit from "@react-spectrum/s2/icons/Edit"; ## Available icons - + ## API diff --git a/packages/dev/s2-docs/scripts/generateMarkdownDocs.mjs b/packages/dev/s2-docs/scripts/generateMarkdownDocs.mjs index f9238c5299a..3f2d14d5c2c 100644 --- a/packages/dev/s2-docs/scripts/generateMarkdownDocs.mjs +++ b/packages/dev/s2-docs/scripts/generateMarkdownDocs.mjs @@ -727,13 +727,13 @@ function remarkDocsComponentsToMarkdown() { } // Render an unordered list of icon names. - if (name === 'IconCards') { + if (name === 'IconsPageSearch') { const iconList = getIconNames(); const listMarkdown = iconList.length ? iconList.map(iconName => `- ${iconName}`).join('\n') : '> Icon list could not be generated.'; - const iconCardsNode = unified().use(remarkParse).parse(listMarkdown); - parent.children.splice(index, 1, ...iconCardsNode.children); + const iconListNode = unified().use(remarkParse).parse(listMarkdown); + parent.children.splice(index, 1, ...iconListNode.children); return index; } diff --git a/packages/dev/s2-docs/src/IconSearchView.tsx b/packages/dev/s2-docs/src/IconSearchView.tsx index cd6d240e062..da720249066 100644 --- a/packages/dev/s2-docs/src/IconSearchView.tsx +++ b/packages/dev/s2-docs/src/IconSearchView.tsx @@ -16,6 +16,85 @@ import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; export const iconList = Object.keys(icons).map(name => ({id: name.replace(/^S2_Icon_(.*?)(Size\d+)?_2.*/, '$1'), icon: icons[name].default})); +export function useIconFilter() { + let {contains} = useFilter({sensitivity: 'base'}); + return useCallback((textValue: string, inputValue: string) => { + // Check for alias matches + for (const alias of Object.keys(iconAliases)) { + if (contains(alias, inputValue) && iconAliases[alias].includes(textValue)) { + return true; + } + } + // Also compare for substrings in the icon's actual name + return textValue != null && contains(textValue, inputValue); + }, [contains]); +} + +export function useCopyImport() { + let [copiedId, setCopiedId] = useState(null); + let timeout = useRef | null>(null); + + useEffect(() => { + return () => { + if (timeout.current) { + clearTimeout(timeout.current); + } + }; + }, []); + + let handleCopyImport = useCallback((id: string) => { + if (timeout.current) { + clearTimeout(timeout.current); + } + navigator.clipboard.writeText(`import ${id} from '@react-spectrum/s2/icons/${id}';`).then(() => { + setCopiedId(id); + timeout.current = setTimeout(() => setCopiedId(null), 2000); + }).catch(() => { + // noop + }); + }, []); + + return {copiedId, handleCopyImport}; +} + +function CopyInfoMessage() { + return ( +
    + + Press an item to copy its import statement +
    + ); +} + +interface IconListBoxProps { + items: typeof iconList, + copiedId: string | null, + onAction: (item: string) => void, + listBoxClassName?: string +} + +function IconListBox({items, copiedId, onAction, listBoxClassName}: IconListBoxProps) { + return ( + + onAction(item.toString())} + items={items} + layout="grid" + className={listBoxClassName || style({width: '100%', scrollPaddingY: 4})} + dependencies={[copiedId]} + renderEmptyState={() => ( + + + No results + Try a different search term. + + )}> + {item => } + + + ); +} + const itemStyle = style({ ...focusRing(), size: 'full', @@ -49,52 +128,12 @@ interface IconSearchViewProps { } export function IconSearchView({filteredItems}: IconSearchViewProps) { - let [copiedId, setCopiedId] = useState(null); - let timeout = useRef | null>(null); - - useEffect(() => { - return () => { - if (timeout.current) { - clearTimeout(timeout.current); - } - }; - }, []); - - let handleCopyImport = useCallback((id: string) => { - if (timeout.current) { - clearTimeout(timeout.current); - } - navigator.clipboard.writeText(`import ${id} from '@react-spectrum/s2/icons/${id}';`).then(() => { - setCopiedId(id); - timeout.current = setTimeout(() => setCopiedId(null), 2000); - }).catch(() => { - // noop - }); - }, []); + let {copiedId, handleCopyImport} = useCopyImport(); return ( <> -
    - - Press an item to copy its import statement -
    - - handleCopyImport(item.toString())} - items={filteredItems} - layout="grid" - className={style({width: '100%', scrollPaddingY: 4})} - dependencies={[copiedId]} - renderEmptyState={() => ( - - - No results - Try a different search term. - - )}> - {item => } - - + + ); } @@ -187,68 +226,21 @@ export function IconSearchSkeleton() { ); } -export function IconCards() { - let {contains} = useFilter({sensitivity: 'base'}); - let filter = useCallback((textValue, inputValue) => { - // check if we're typing part of a category alias - for (const alias of Object.keys(iconAliases)) { - if (contains(alias, inputValue) && iconAliases[alias].includes(textValue)) { - return true; - } - } - // also compare for substrings in the icon's actual name - return textValue != null && contains(textValue, inputValue); - }, [contains]); - - let [copiedId, setCopiedId] = useState(null); - let timeout = useRef | null>(null); - - useEffect(() => { - return () => { - if (timeout.current) { - clearTimeout(timeout.current); - } - }; - }, []); - - let handleCopyImport = useCallback((id: string) => { - if (timeout.current) { - clearTimeout(timeout.current); - } - navigator.clipboard.writeText(`import ${id} from '@react-spectrum/s2/icons/${id}';`).then(() => { - setCopiedId(id); - timeout.current = setTimeout(() => setCopiedId(null), 2000); - }).catch(() => { - // noop - }); - }, []); +export function IconsPageSearch() { + let filter = useIconFilter(); + let {copiedId, handleCopyImport} = useCopyImport(); return ( <>
    -
    - - Press an item to copy its import statement -
    - - handleCopyImport(item.toString())} - items={iconList} - layout="grid" - className={style({height: 440, width: '100%', maxHeight: '100%', overflow: 'auto', scrollPaddingY: 4})} - dependencies={[copiedId]} - renderEmptyState={() => ( - - - No results - Try a different search term. - - )}> - {item => } - - + +
    diff --git a/packages/dev/s2-docs/src/SearchMenu.tsx b/packages/dev/s2-docs/src/SearchMenu.tsx index 6e735004f03..54c60e986b7 100644 --- a/packages/dev/s2-docs/src/SearchMenu.tsx +++ b/packages/dev/s2-docs/src/SearchMenu.tsx @@ -1,18 +1,17 @@ 'use client'; import {ActionButton, Content, Heading, IllustratedMessage, SearchField, Tag, TagGroup} from '@react-spectrum/s2'; -import {Autocomplete, Dialog, Key, OverlayTriggerStateContext, Provider, Separator as RACSeparator, useFilter} from 'react-aria-components'; +import {Autocomplete, Dialog, Key, OverlayTriggerStateContext, Provider, Separator as RACSeparator} from 'react-aria-components'; import Close from '@react-spectrum/s2/icons/Close'; import {ComponentCardView} from './ComponentCardView'; import {getLibraryFromPage, getLibraryFromUrl} from './library'; -import {iconAliases} from './iconAliases.js'; -import {iconList, IconSearchSkeleton} from './IconSearchView'; +import {iconList, IconSearchSkeleton, useIconFilter} from './IconSearchView'; import {type Library, TAB_DEFS} from './constants'; // eslint-disable-next-line monorepo/no-internal-import import NoSearchResults from '@react-spectrum/s2/illustrations/linear/NoSearchResults'; // @ts-ignore import {Page} from '@parcel/rsc'; -import React, {CSSProperties, lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState} from 'react'; +import React, {CSSProperties, lazy, Suspense, useEffect, useMemo, useRef, useState} from 'react'; import {SelectableCollectionContext} from '../../../react-aria-components/src/RSPContexts'; import {style} from '@react-spectrum/s2/style' with { type: 'macro' }; import {Tab, TabList, TabPanel, Tabs} from './Tabs'; @@ -141,18 +140,7 @@ export function SearchMenu(props: SearchMenuProps) { const [selectedSectionId, setSelectedSectionId] = useState(() => currentPage.exports?.section?.toLowerCase() || 'components'); const prevSearchWasEmptyRef = useRef(true); - // Icon filter function - const {contains} = useFilter({sensitivity: 'base'}); - const iconFilter = useCallback((textValue, inputValue) => { - // check if we're typing part of a category alias - for (const alias of Object.keys(iconAliases)) { - if (contains(alias, inputValue) && iconAliases[alias].includes(textValue)) { - return true; - } - } - // also compare for substrings in the icon's actual name - return textValue != null && contains(textValue, inputValue); - }, [contains]); + const iconFilter = useIconFilter(); const filteredIcons = useMemo(() => { if (!searchValue.trim()) {