Conversation
Signed-off-by: prxt6529 <prxt@6529.io>
WalkthroughThe pull request unifies header search results by introducing ALL and PAGES categories, implementing page ranking and per-category previews with view-all controls, adding new UI components (HeaderSearchTabToggle, HeaderSearchModalPfp), removing HeaderSearchModalItemHighlight, refactoring test mocks across multiple test files, and updating related hooks and test suites to support the new multi-category search orchestration. Changes
Sequence DiagramsequenceDiagram
actor User
participant SearchModal as HeaderSearchModal
participant FetchOrch as Multi-Category<br/>Orchestration
participant PageCatalog as Page Catalog<br/>& Ranking
participant APIs as API Queries<br/>(Profiles, NFTs, Waves)
participant UI as Results UI
User->>SearchModal: Enter search query
activate SearchModal
SearchModal->>SearchModal: Trim & debounce query
SearchModal->>FetchOrch: Determine enabled categories<br/>(ALL / specific)
activate FetchOrch
rect rgb(220, 240, 255)
note right of FetchOrch: Evaluate shouldSearchPages,<br/>shouldSearchDefault, etc.
end
par Parallel Fetches
FetchOrch->>APIs: Fetch profiles (if enabled)
FetchOrch->>APIs: Fetch NFTs (if enabled)
FetchOrch->>APIs: Fetch Waves (if enabled)
FetchOrch->>PageCatalog: Search page catalog (if enabled)
end
APIs-->>FetchOrch: Results data
PageCatalog-->>SearchModal: Ranked pages (with priority)
rect rgb(240, 255, 240)
note right of SearchModal: Compute resultsByCategory<br/>& per-category previews
end
deactivate FetchOrch
SearchModal->>UI: Render grouped previews<br/>with "View all" per category
UI-->>User: Display categorized results<br/>(ALL / PAGES / PROFILES / NFTS / WAVES)
User->>UI: Click category tab or "View all"
UI->>SearchModal: Update selected category
SearchModal->>UI: Render full results for category
UI-->>User: Display full result set
deactivate SearchModal
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Areas requiring extra attention:
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
components/common/TabToggle.tsx (1)
10-16: Remove inline code comments in TS/TSX files.Guideline: no comments in code for .ts/.tsx. Drop these inline comments.
- readonly fullWidth?: boolean; // New prop to control width + readonly fullWidth?: boolean; @@ - fullWidth = false, // Default to false for backwards compatibility + fullWidth = false,As per coding guidelines.
Also applies to: 23-24
🧹 Nitpick comments (8)
components/common/TabToggle.tsx (1)
31-39: Add aria-orientation and button type for proper tabs a11y.Expose orientation to AT and prevent unintended form submits.
- <div className={containerClasses} role="tablist"> + <div + className={containerClasses} + role="tablist" + aria-orientation={isVertical ? "vertical" : "horizontal"} + >- <button + <button + type="button"hooks/useSidebarSections.ts (1)
189-196: Make SidebarPageEntry fields readonly for safer usage.Prevents accidental mutation downstream; aligns with readonly-first style used for props.
-export interface SidebarPageEntry { - name: string; - href: string; - section: string; - subsection?: string; - icon?: ComponentType<{ className?: string }>; -} +export interface SidebarPageEntry { + readonly name: string; + readonly href: string; + readonly section: string; + readonly subsection?: string; + readonly icon?: ComponentType<{ className?: string }>; +}hooks/useWaves.ts (2)
81-82: Also gate refetch timers when disabled.Avoid background intervals when disabled by passing false.
- enabled: enabled && !usePublicWaves, - refetchInterval, + enabled: enabled && !usePublicWaves, + refetchInterval: enabled ? refetchInterval : false, @@ - enabled: enabled && usePublicWaves, - refetchInterval, + enabled: enabled && usePublicWaves, + refetchInterval: enabled ? refetchInterval : false,Also applies to: 106-107
86-103: Optional: include limit in public query for parity.Public endpoint omits limit while auth includes it. If supported, add limit to waves-public requests for consistent pagination semantics.
components/header/header-search/HeaderSearchModal.tsx (1)
26-26: Icons: align with project guideline (FontAwesome for TSX).Heroicons (ChevronLeftIcon, XMarkIcon) are used here; the guideline specifies FontAwesome for icons in TSX.
Suggested change (example):
- import { ChevronLeftIcon, XMarkIcon } from "@heroicons/react/24/outline"; + import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + import { faChevronLeft, faXmark } from "@fortawesome/free-solid-svg-icons"; @@ - <ChevronLeftIcon className="tw-size-6 tw-flex-shrink-0" /> + <FontAwesomeIcon icon={faChevronLeft} className="tw-size-6 tw-flex-shrink-0" /> @@ - <XMarkIcon className="tw-size-5" /> + <FontAwesomeIcon icon={faXmark} className="tw-size-5" />As per coding guidelines.
Also applies to: 842-844, 887-889
components/header/header-search/HeaderSearchModalItem.tsx (2)
32-33: Replace heroicons fallback with FontAwesome to meet TSX icon guideline.Use a FontAwesome fallback icon instead of DocumentTextIcon.
- import { DocumentTextIcon } from "@heroicons/react/24/outline"; + import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + import { faFileLines } from "@fortawesome/free-regular-svg-icons"; @@ - } else if (isPage()) { - const page = getPage(); - const Icon = page.icon ?? DocumentTextIcon; - return ( - <div className="tw-flex tw-h-10 tw-w-10 tw-items-center tw-justify-center tw-rounded-lg tw-bg-iron-900"> - <Icon className="tw-h-5 tw-w-5 tw-text-iron-200" /> - </div> - ); + } else if (isPage()) { + const page = getPage(); + const FallbackIcon = ({ className }: { className?: string }) => ( + <FontAwesomeIcon icon={faFileLines} className={className} /> + ); + const Icon = page.icon ?? FallbackIcon; + return ( + <div className="tw-flex tw-h-10 tw-w-10 tw-items-center tw-justify-center tw-rounded-lg tw-bg-iron-900"> + <Icon className="tw-h-5 tw-w-5 tw-text-iron-200" /> + </div> + );As per coding guidelines.
Also applies to: 119-126
153-157: Guard against unknown NFT contracts to avoid runtime errors.collectionMap[nft.contract] may be undefined; current code would throw. Add a safe fallback.
- const collectionMap = getNftCollectionMap(); - return `${collectionMap[nft.contract].path}/${nft.id}`; + const collectionMap = getNftCollectionMap(); + const key = nft.contract?.toLowerCase?.() ?? ""; + const collection = collectionMap[key]; + const basePath = collection?.path ?? "/the-memes"; // choose an appropriate default + return `${basePath}/${nft.id}`;Also applies to: 196-200
__tests__/components/header/HeaderSearchModal.test.tsx (1)
233-242: Prefer userEvent over fireEvent for interactions.For closer user semantics and async behaviors, use userEvent instead of fireEvent where feasible (typing, clicks).
Based on learnings
Also applies to: 244-256, 258-306, 308-375, 383-389, 415-431
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
__tests__/components/HeaderSearchModal.test.tsx(0 hunks)__tests__/components/header/HeaderSearchModal.test.tsx(9 hunks)__tests__/components/header/HeaderSearchModalItem.test.tsx(1 hunks)__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx(3 hunks)codex/STATE.md(1 hunks)codex/tickets/TKT-0011.md(1 hunks)components/common/TabToggle.tsx(1 hunks)components/header/header-search/HeaderSearchModal.tsx(13 hunks)components/header/header-search/HeaderSearchModalItem.tsx(8 hunks)components/waves/Waves.tsx(1 hunks)hooks/useSidebarSections.ts(2 hunks)hooks/useWaves.ts(4 hunks)
💤 Files with no reviewable changes (1)
- tests/components/HeaderSearchModal.test.tsx
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before propsUse TypeScript across the codebase
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsxcomponents/waves/Waves.tsxhooks/useSidebarSections.ts__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsxhooks/useWaves.tscomponents/header/header-search/HeaderSearchModal.tsxcomponents/header/header-search/HeaderSearchModalItem.tsxcomponents/common/TabToggle.tsx__tests__/components/header/HeaderSearchModal.test.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursorrules)
**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for stylingUse React functional components with hooks for UI components
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsxcomponents/waves/Waves.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsxcomponents/header/header-search/HeaderSearchModal.tsxcomponents/header/header-search/HeaderSearchModalItem.tsxcomponents/common/TabToggle.tsx__tests__/components/header/HeaderSearchModal.test.tsx
__tests__/**
📄 CodeRabbit inference engine (tests/AGENTS.md)
Place Jest test suites under the
__tests__directory mirroring source folders (e.g., components, contexts, hooks, utils)
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx__tests__/components/header/HeaderSearchModal.test.tsx
__tests__/components/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Use
@testing-library/reactand@testing-library/user-eventfor React component tests
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx__tests__/components/header/HeaderSearchModal.test.tsx
**/__tests__/**
📄 CodeRabbit inference engine (AGENTS.md)
Place tests in
__tests__directories when organizing test suites
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx__tests__/components/header/HeaderSearchModal.test.tsx
**/*.test.tsx
📄 CodeRabbit inference engine (AGENTS.md)
When colocating tests with components, name them
ComponentName.test.tsx
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx__tests__/components/header/HeaderSearchModal.test.tsx
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Mock external dependencies and APIs in tests
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx__tests__/components/header/HeaderSearchModal.test.tsx
🧠 Learnings (2)
📚 Learning: 2025-10-23T06:36:34.105Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: AGENTS.md:0-0
Timestamp: 2025-10-23T06:36:34.105Z
Learning: Applies to **/*.test.{ts,tsx} : Mock external dependencies and APIs in tests
Applied to files:
__tests__/components/header/HeaderSearchModal.test.tsx
📚 Learning: 2025-09-28T12:33:07.561Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: __mocks__/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:07.561Z
Learning: Applies to __mocks__/**/__mocks__/**/*.{js,jsx,ts,tsx} : Mock only external dependencies or heavy functionality; avoid over-mocking internal logic
Applied to files:
__tests__/components/header/HeaderSearchModal.test.tsx
🧬 Code graph analysis (5)
__tests__/components/header/HeaderSearchModalItem.test.tsx (1)
components/header/header-search/HeaderSearchModalItem.tsx (1)
HeaderSearchModalItem(57-249)
hooks/useSidebarSections.ts (1)
components/navigation/navTypes.ts (1)
SidebarSection(38-47)
__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx (1)
hooks/useDeviceInfo.ts (1)
useDeviceInfo(22-78)
components/header/header-search/HeaderSearchModal.tsx (6)
hooks/useSidebarSections.ts (3)
SidebarPageEntry(189-195)useSidebarSections(7-180)mapSidebarSectionsToPages(197-222)components/app-wallets/AppWalletsContext.tsx (1)
useAppWallets(217-223)components/cookies/CookieConsentContext.tsx (1)
useCookieConsent(43-50)components/header/header-search/HeaderSearchModalItem.tsx (4)
PageSearchResult(43-49)NFTSearchResult(34-41)HeaderSearchModalItemType(51-55)HeaderSearchModalItem(57-249)helpers/navigation.helpers.ts (2)
getWaveHomeRoute(73-83)getWaveRoute(23-71)components/common/TabToggle.tsx (1)
TabToggle(18-60)
components/header/header-search/HeaderSearchModalItem.tsx (2)
entities/IProfile.ts (1)
CommunityMemberMinimal(301-312)generated/models/ApiWave.ts (1)
ApiWave(27-177)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (6)
components/waves/Waves.tsx (1)
176-179: Confirm non‑app DM flow with new activeView logic.Now non‑app renders VIEW unless viewMode is CREATE; DM opens via modal only. Verify this matches expected UX and add/adjust tests for:
- non‑app + CREATE_DM ⇒ WavesList visible + DM modal open
- non‑app + CREATE ⇒ CreateWave page
hooks/useWaves.ts (2)
118-125: State reset on disable is correct.Clears stale results when disabled; dependencies are complete.
26-27: Review comment is incorrect; no caller changes needed.The
enabledparameter is properly implemented with a sensible default oftrue. The hook correctly gates both queries with the enabled flag and resets waves when disabled. None of the three production callers—WavesListSearchResults,HeaderSearchModal, andBrainLeftSidebarSearchWaveDropdown—require passingenabled=falsebased on their search/modal contexts, and the suggestion to verify this is unfounded.Likely an incorrect or invalid review comment.
__tests__/components/header/HeaderSearchModalItem.test.tsx (1)
156-185: New PAGE item test covers href, title, breadcrumbs, icon — looks good.__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx (1)
60-78: Focus management test scaffolding and mocks are set up cleanly.Also applies to: 84-93, 134-140, 142-205
components/header/header-search/HeaderSearchModal.tsx (1)
466-467: Fix PAGES-only "Loading…" loop when there are no matches.The bug is confirmed. When
selectedCategory === PAGESwith no matches,isSearchingremains true indefinitely because it treats PAGES (synchronous) the same as async categories. This prevents the state machine from reachingNO_RESULTS. The proposed diff correctly fixes this by only treating PAGES as "searching" when it's not the selected category (i.e., still waiting for other async fetches).Apply the suggested diff at line 466-467:
- const isSearching = shouldSearchPages || hasActiveDebouncedSearch; + // Treat Pages as instant; only async categories keep the loader + const isSearching = + hasActiveDebouncedSearch || + (shouldSearchPages && selectedCategory !== CATEGORY.PAGES);This also resolves the state machine behavior at lines 693-705 (the dependency array in the useEffect) since
isSearchingis a dependency there.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (2)
components/header/header-search/HeaderSearchModal.tsx (1)
786-799: Use stable keys instead of random IDs to prevent remounts and lost selection/focusRandom keys remount items every render, breaking keyboard highlight and hurting perf. Derive deterministic keys per item type.
- import { getRandomObjectId } from "@/helpers/AllowlistToolHelpers"; + // (remove) @@ - const renderItem = (item: HeaderSearchModalItemType, index: number) => ( + const getItemKey = (item: HeaderSearchModalItemType): string => { + if (isPageResult(item)) return `page:${item.href}`; + if (isNftResult(item)) return `nft:${item.contract}:${item.id}`; + if (isProfileResult(item)) { + const p = item as CommunityMemberMinimal; + return `profile:${p.handle ?? p.wallet}`; + } + if (isWaveResult(item)) return `wave:${item.id}`; + return JSON.stringify(item); + }; + + const renderItem = (item: HeaderSearchModalItemType, index: number) => ( <div ref={index === selectedItemIndex ? activeElementRef : null} - key={getRandomObjectId()}> + key={getItemKey(item)}>Also applies to: 15-15
codex/tickets/TKT-0011.md (1)
26-29: Primary PR link successfully added.The placeholder has been replaced with the correct PR reference, addressing the previous review concern.
🧹 Nitpick comments (8)
components/common/TabToggle.tsx (3)
31-31: Add aria-orientation for vertical tablistsWhen vertical, expose orientation for assistive tech.
- <div className={containerClasses} role="tablist"> + <div + className={containerClasses} + role="tablist" + aria-orientation={isVertical ? "vertical" : "horizontal"}>
33-47: Expose stable tab IDs to enable aria-labelledby on the panelProvide ids for tabs so the panel can reference the active tab.
- <button + <button + id={`tab-${option.key}`} key={option.key}
10-16: Remove inline comments in TSX per repo guidelinesInline comments violate “Do not include any comments in the code” for .ts/.tsx. Please remove them.
- readonly fullWidth?: boolean; // New prop to control width + readonly fullWidth?: boolean; @@ - fullWidth = false, // Default to false for backwards compatibility + fullWidth = false,As per coding guidelines.
Also applies to: 22-24
components/header/header-search/HeaderSearchModalItem.tsx (1)
32-32: Use FontAwesome for icons in TSXDocumentTextIcon (Heroicons) violates the “Use FontAwesome for icons” guideline in TSX. Replace with your FontAwesome wrapper (or FaRegFileLines) for consistency.
Example:
- import { DocumentTextIcon } from "@heroicons/react/24/outline"; + import { FaRegFileLines } from "react-icons/fa6"; // or your common/icons wrapper @@ - const Icon = page.icon ?? DocumentTextIcon; + const Icon = page.icon ?? FaRegFileLines;As per coding guidelines.
Also applies to: 121-126
components/header/header-search/HeaderSearchModal.tsx (3)
914-921: Wire up tabs ↔ panel with aria-labelledbyNow that TabToggle assigns ids, have the tabpanel reference the active tab for better a11y.
- <div className="tw-pt-3 tw-px-4 md:tw-hidden"> + <div className="tw-pt-3 tw-px-4 md:tw-hidden"> <TabToggle options={tabOptions} activeKey={selectedCategory} onSelect={(k) => setSelectedCategory(k as CATEGORY)} /> </div> @@ - <div + <div ref={resultsPanelRef} id={HEADER_SEARCH_RESULTS_PANEL_ID} - role="tabpanel" + role="tabpanel" + aria-labelledby={`tab-${selectedCategory}`} className="tw-flex-1 ...Apply the same aria-labelledby addition to all role="tabpanel" instances in SUCCESS, LOADING, NO_RESULTS, ERROR, and INITIAL blocks.
Also applies to: 924-937, 940-947, 948-959, 960-970, 971-1007, 1008-1021
860-867: Remove JSX comments in TSXInline comments violate repo rule “Do not include any comments in the code.” Remove the “Back arrow mobile” comment.
As per coding guidelines.
244-277: Scope the non‑passive wheel handler to the scroll containerAttaching a passive:false wheel listener to window can degrade scroll perf and block page scroll unnecessarily. Attach it to resultsPanelRef instead; add/remove when the element mounts.
Would you like a patch that binds the wheel listener directly on resultsPanelRef and cleans up properly?
__tests__/components/header/HeaderSearchModal.test.tsx (1)
17-99: Test mocks properly configured.The mock setup for AppWallets, CookieConsent, Capacitor, and SidebarSections follows the established pattern and provides deterministic test data.
Consider extracting
defaultSidebarSections(lines 89-99) to a shared test utility, as it's duplicated inHeaderSearchModalFocus.test.tsx(lines 84-92). This would improve maintainability if the test data structure needs to change.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
__tests__/components/brain/content/input/BrainContentInput.test.tsx(4 hunks)__tests__/components/breadcrumb/Breadcrumb.test.tsx(3 hunks)__tests__/components/header/HeaderSearchModal.test.tsx(9 hunks)__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx(3 hunks)__tests__/components/user/layout/UserPageTabs.test.tsx(2 hunks)__tests__/hooks/useDeepLinkNavigation.test.ts(3 hunks)__tests__/hooks/useDeviceInfo.test.ts(3 hunks)codex/STATE.md(1 hunks)codex/tickets/TKT-0011.md(1 hunks)components/common/TabToggle.tsx(1 hunks)components/header/header-search/HeaderSearchModal.tsx(13 hunks)components/header/header-search/HeaderSearchModalItem.tsx(8 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- codex/STATE.md
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before propsUse TypeScript across the codebase
Files:
__tests__/components/brain/content/input/BrainContentInput.test.tsx__tests__/hooks/useDeepLinkNavigation.test.ts__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsxcomponents/common/TabToggle.tsx__tests__/components/breadcrumb/Breadcrumb.test.tsxcomponents/header/header-search/HeaderSearchModalItem.tsx__tests__/hooks/useDeviceInfo.test.ts__tests__/components/header/HeaderSearchModal.test.tsx__tests__/components/user/layout/UserPageTabs.test.tsxcomponents/header/header-search/HeaderSearchModal.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursorrules)
**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for stylingUse React functional components with hooks for UI components
Files:
__tests__/components/brain/content/input/BrainContentInput.test.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsxcomponents/common/TabToggle.tsx__tests__/components/breadcrumb/Breadcrumb.test.tsxcomponents/header/header-search/HeaderSearchModalItem.tsx__tests__/components/header/HeaderSearchModal.test.tsx__tests__/components/user/layout/UserPageTabs.test.tsxcomponents/header/header-search/HeaderSearchModal.tsx
__tests__/**
📄 CodeRabbit inference engine (tests/AGENTS.md)
Place Jest test suites under the
__tests__directory mirroring source folders (e.g., components, contexts, hooks, utils)
Files:
__tests__/components/brain/content/input/BrainContentInput.test.tsx__tests__/hooks/useDeepLinkNavigation.test.ts__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx__tests__/components/breadcrumb/Breadcrumb.test.tsx__tests__/hooks/useDeviceInfo.test.ts__tests__/components/header/HeaderSearchModal.test.tsx__tests__/components/user/layout/UserPageTabs.test.tsx
__tests__/components/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Use
@testing-library/reactand@testing-library/user-eventfor React component tests
Files:
__tests__/components/brain/content/input/BrainContentInput.test.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx__tests__/components/breadcrumb/Breadcrumb.test.tsx__tests__/components/header/HeaderSearchModal.test.tsx__tests__/components/user/layout/UserPageTabs.test.tsx
**/__tests__/**
📄 CodeRabbit inference engine (AGENTS.md)
Place tests in
__tests__directories when organizing test suites
Files:
__tests__/components/brain/content/input/BrainContentInput.test.tsx__tests__/hooks/useDeepLinkNavigation.test.ts__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx__tests__/components/breadcrumb/Breadcrumb.test.tsx__tests__/hooks/useDeviceInfo.test.ts__tests__/components/header/HeaderSearchModal.test.tsx__tests__/components/user/layout/UserPageTabs.test.tsx
**/*.test.tsx
📄 CodeRabbit inference engine (AGENTS.md)
When colocating tests with components, name them
ComponentName.test.tsx
Files:
__tests__/components/brain/content/input/BrainContentInput.test.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx__tests__/components/breadcrumb/Breadcrumb.test.tsx__tests__/components/header/HeaderSearchModal.test.tsx__tests__/components/user/layout/UserPageTabs.test.tsx
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Mock external dependencies and APIs in tests
Files:
__tests__/components/brain/content/input/BrainContentInput.test.tsx__tests__/hooks/useDeepLinkNavigation.test.ts__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx__tests__/components/breadcrumb/Breadcrumb.test.tsx__tests__/hooks/useDeviceInfo.test.ts__tests__/components/header/HeaderSearchModal.test.tsx__tests__/components/user/layout/UserPageTabs.test.tsx
🧠 Learnings (2)
📚 Learning: 2025-10-23T06:36:34.105Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: AGENTS.md:0-0
Timestamp: 2025-10-23T06:36:34.105Z
Learning: Applies to **/*.test.{ts,tsx} : Mock external dependencies and APIs in tests
Applied to files:
__tests__/hooks/useDeepLinkNavigation.test.ts__tests__/components/header/HeaderSearchModal.test.tsx
📚 Learning: 2025-09-28T12:33:07.561Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: __mocks__/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:07.561Z
Learning: Applies to __mocks__/**/__mocks__/**/*.{js,jsx,ts,tsx} : Mock only external dependencies or heavy functionality; avoid over-mocking internal logic
Applied to files:
__tests__/components/header/HeaderSearchModal.test.tsx
🧬 Code graph analysis (3)
__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx (1)
hooks/useDeviceInfo.ts (1)
useDeviceInfo(22-78)
components/header/header-search/HeaderSearchModalItem.tsx (2)
entities/IProfile.ts (1)
CommunityMemberMinimal(301-312)generated/models/ApiWave.ts (1)
ApiWave(27-177)
components/header/header-search/HeaderSearchModal.tsx (8)
hooks/useSidebarSections.ts (3)
SidebarPageEntry(189-195)useSidebarSections(7-180)mapSidebarSectionsToPages(197-222)components/header/header-search/HeaderSearchModalItem.tsx (4)
HeaderSearchModalItemType(51-55)PageSearchResult(43-49)NFTSearchResult(34-41)HeaderSearchModalItem(57-249)components/app-wallets/AppWalletsContext.tsx (1)
useAppWallets(217-223)components/cookies/CookieConsentContext.tsx (1)
useCookieConsent(43-50)services/api/common-api.ts (1)
commonApiFetch(18-45)generated/models/ApiWave.ts (1)
ApiWave(27-177)helpers/navigation.helpers.ts (2)
getWaveHomeRoute(73-83)getWaveRoute(23-71)components/common/TabToggle.tsx (1)
TabToggle(18-60)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (15)
__tests__/hooks/useDeviceInfo.test.ts (1)
5-6: LGTM: mock renaming is consistent and clearRenamed variable and usages improve clarity; behavior unchanged.
Also applies to: 31-37, 39-46
__tests__/components/user/layout/UserPageTabs.test.tsx (1)
13-17: LGTM: standardized capacitor mock usageConsistent mock pattern across tests; no behavior change.
Also applies to: 38-39, 61-66
components/header/header-search/HeaderSearchModal.tsx (1)
28-29: No changes needed — import style is correctThe current named import
import { FocusTrap } from "focus-trap-react"is the supported approach according to the package's README and type definitions. No changes required.__tests__/components/brain/content/input/BrainContentInput.test.tsx (1)
5-59: LGTM! Clean refactoring of mock naming.The rename from
useCapacitorMocktocapacitorMockis applied consistently throughout the file, and all test cases continue to function correctly.__tests__/components/breadcrumb/Breadcrumb.test.tsx (1)
6-36: LGTM! Consistent mock refactoring.The mock naming update is applied uniformly across all usages in this test file.
codex/tickets/TKT-0011.md (1)
24-24: Verify test suite status before closing the ticket.The acceptance criterion for passing tests remains unchecked. Based on the test additions in this PR, ensure
npm run test,npm run lint, andnpm run type-checkall pass before marking this ticket complete.__tests__/hooks/useDeepLinkNavigation.test.ts (1)
8-43: LGTM! Mock refactoring applied correctly.The
capacitorMockrename is consistently applied across mock declarations and implementations.__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx (2)
22-78: Well-structured test mock setup.The new mocks for AppWallets, CookieConsent, Capacitor, and SidebarSections are properly declared and wired. The preservation of
mapSidebarSectionsToPagesfrom the actual module (line 76) ensures the real mapping logic is tested.
84-140: Test setup properly updated for multi-category search.The default category change from
PROFILEStoALL(line 134) and the addition of concrete mock return values align with the unified search feature described in the PR objectives.__tests__/components/header/HeaderSearchModal.test.tsx (6)
101-201: Setup infrastructure properly extended for multi-category search.The additions to
SetupOptions(enabled flag, category types, sidebar sections) and the correspondingsetupfunction updates correctly support the unified search feature. The enabled flag handling (lines 169-181) appropriately uses explicit=== falseto distinguish disabled queries from those without the flag.
233-242: Clear search functionality properly tested.This test case correctly verifies that the clear button resets the search input.
244-256: Page results integration verified.The test correctly confirms that navigation pages appear in search results with the expected PAGE type.
258-306: Exact match prioritization correctly validated.This test thoroughly verifies that exact page title matches appear before partial matches, aligning with the ticket's acceptance criteria (TKT-0011).
308-375: Deterministic category ordering thoroughly tested.This comprehensive test validates that result categories are ordered by ascending count (Pages: 1, NFTs: 2, Profiles: 3, Waves: 4), fulfilling the ticket's acceptance criteria for category ordering.
391-431: Error handling and retry logic properly tested.The test correctly verifies that both profile and wave refetch functions are called on retry (line 430), consistent with the unified search refactor.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (3)
components/header/header-search/HeaderSearchModalItem.tsx (1)
155-158: Fix NFT collection map casing + add safe fallbackscollectionMap uses lowercased keys but indexing uses raw nft.contract. This can throw at runtime or generate wrong paths.
- const collectionMap = getNftCollectionMap(); - return `${collectionMap[nft.contract].path}/${nft.id}`; + const collectionMap = getNftCollectionMap(); + const key = String(nft.contract || "").toLowerCase(); + const entry = collectionMap[key]; + return entry ? `${entry.path}/${nft.id}` : `/${nft.contract}/${nft.id}`; @@ - const collectionMap = getNftCollectionMap(); - return `${collectionMap[nft.contract].title} #${nft.id}`; + const collectionMap = getNftCollectionMap(); + const key = String(nft.contract || "").toLowerCase(); + const entry = collectionMap[key]; + return `${entry?.title ?? "Unknown collection"} #${nft.id}`;Also applies to: 197-204
components/header/header-search/HeaderSearchModal.tsx (2)
786-799: Use stable keys; stop using random IDsRandom keys remount on every render, breaking focus/selection and perf.
-import { getRandomObjectId } from "@/helpers/AllowlistToolHelpers"; +// (removed) @@ - const renderItem = (item: HeaderSearchModalItemType, index: number) => ( + const getItemKey = (item: HeaderSearchModalItemType): string => { + if (isPageResult(item)) return `page:${item.href}`; + if (isNftResult(item)) return `nft:${item.contract}:${item.id}`; + if (isProfileResult(item)) { + const p = item as CommunityMemberMinimal; + return `profile:${p.handle ?? p.wallet}`; + } + if (isWaveResult(item)) return `wave:${item.id}`; + return JSON.stringify(item); + }; + + const renderItem = (item: HeaderSearchModalItemType, index: number) => ( <div ref={index === selectedItemIndex ? activeElementRef : null} - key={getRandomObjectId()}> + key={getItemKey(item)}> <HeaderSearchModalItem content={item} searchValue={debouncedValue} isSelected={index === selectedItemIndex} onHover={(state) => onHover(index, state)} onClose={onClose} /> </div> );Also applies to: 15-15
692-712: Fix state machine: allow NO_RESULTS when nothing is fetchingAs written, NO_RESULTS is unreachable while isSearching remains true. Only LOADING when any fetch is actually in-flight.
- if (anyFetching || isSearching) { + if (anyFetching) { setState(STATE.LOADING); return; } setState(STATE.NO_RESULTS); return;
🧹 Nitpick comments (5)
components/common/TabToggle.tsx (2)
31-31: Add aria-orientation to tablist for accessibilityExpose the axis to AT when vertical.
- <div className={containerClasses} role="tablist"> + <div + className={containerClasses} + role="tablist" + aria-orientation={isVertical ? "vertical" : "horizontal"}>
39-47: Provide visible focus state on tabsYou remove the outline but don’t add a replacement. Add focus-visible rings to keep keyboard navigation accessible.
- className={`tw-whitespace-nowrap tw-text-sm tw-font-medium tw-transition-all tw-duration-150 tw-relative focus:tw-outline-none tw-border-none tw-rounded-sm ${ + className={`tw-whitespace-nowrap tw-text-sm tw-font-medium tw-transition-all tw-duration-150 tw-relative focus:tw-outline-none focus-visible:tw-ring-2 focus-visible:tw-ring-primary-400 focus-visible:tw-ring-offset-2 focus-visible:tw-ring-offset-iron-950 tw-border-none tw-rounded-sm ${components/header/header-search/HeaderSearchModalItem.tsx (1)
32-32: Icons: switch to FontAwesome per codebase rulesCoding guidelines require FontAwesome in TSX. Replace DocumentTextIcon with a FA icon (e.g., faFileLines) or a local FA-based icon wrapper.
- import { DocumentTextIcon } from "@heroicons/react/24/outline"; + import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + import { faFileLines } from "@fortawesome/free-regular-svg-icons"; @@ - const Icon = page.icon ?? DocumentTextIcon; + const Icon = + page.icon ?? + (({ className }: { className?: string }) => ( + <FontAwesomeIcon icon={faFileLines} className={className} /> + ));Would you like me to provide a follow-up diff converting the other new Heroicons in this PR?
Also applies to: 121-125
components/header/header-search/HeaderSearchModal.tsx (2)
26-27: Icons: use FontAwesome in TSX (ChevronLeft, XMark)Replace Heroicons with FontAwesome equivalents to match project rules.
- import { ChevronLeftIcon, XMarkIcon } from "@heroicons/react/24/outline"; + import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + import { faChevronLeft, faXmark } from "@fortawesome/free-solid-svg-icons"; @@ - <ChevronLeftIcon className="tw-size-6 tw-flex-shrink-0" /> + <FontAwesomeIcon icon={faChevronLeft} className="tw-size-6 tw-flex-shrink-0" /> @@ - <XMarkIcon className="tw-size-5" /> + <FontAwesomeIcon icon={faXmark} className="tw-size-5" />Confirm if the app already includes FontAwesome; I can extend the diff to add deps if needed.
Also applies to: 910-912, 866-867
940-947: Announce results to assistive techAdd aria-live to the tabpanel container so changes are announced (success, loading, empty, error).
- role="tabpanel" + role="tabpanel" + aria-live="polite"Apply the same on the other tabpanel states for consistency.
Also applies to: 949-960, 961-971, 972-1008, 1010-1023
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
components/common/TabToggle.tsx(1 hunks)components/header/header-search/HeaderSearchModal.tsx(13 hunks)components/header/header-search/HeaderSearchModalItem.tsx(9 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before propsUse TypeScript across the codebase
Files:
components/common/TabToggle.tsxcomponents/header/header-search/HeaderSearchModalItem.tsxcomponents/header/header-search/HeaderSearchModal.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursorrules)
**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for stylingUse React functional components with hooks for UI components
Files:
components/common/TabToggle.tsxcomponents/header/header-search/HeaderSearchModalItem.tsxcomponents/header/header-search/HeaderSearchModal.tsx
🧬 Code graph analysis (2)
components/header/header-search/HeaderSearchModalItem.tsx (4)
entities/IProfile.ts (1)
CommunityMemberMinimal(301-312)generated/models/ApiWave.ts (1)
ApiWave(27-177)components/header/header-search/HeaderSearchModalItemHighlight.tsx (1)
HeaderSearchModalItemHighlight(4-21)helpers/Helpers.ts (1)
formatNumberWithCommas(102-119)
components/header/header-search/HeaderSearchModal.tsx (6)
hooks/useSidebarSections.ts (3)
SidebarPageEntry(189-195)useSidebarSections(7-180)mapSidebarSectionsToPages(197-222)components/header/header-search/HeaderSearchModalItem.tsx (4)
HeaderSearchModalItemType(51-55)PageSearchResult(43-49)NFTSearchResult(34-41)HeaderSearchModalItem(57-251)components/app-wallets/AppWalletsContext.tsx (1)
useAppWallets(217-223)components/cookies/CookieConsentContext.tsx (1)
useCookieConsent(43-50)helpers/navigation.helpers.ts (2)
getWaveHomeRoute(73-83)getWaveRoute(23-71)helpers/AllowlistToolHelpers.ts (1)
getRandomObjectId(46-48)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (3)
components/common/TabToggle.tsx (1)
14-16: Orientation prop addition looks goodClean addition with sensible defaults; layout switching via containerClasses is straightforward.
Also applies to: 22-29
components/header/header-search/HeaderSearchModalItem.tsx (1)
43-49: PAGE result pathway looks solidType, guards, media, path, and text branches are coherent and integrate cleanly.
Also applies to: 81-89, 119-126, 157-158, 185-187, 199-204
components/header/header-search/HeaderSearchModal.tsx (1)
28-28: No changes needed — import style is correct for installed versionThe codebase uses focus-trap-react v11.0.3, which exports FocusTrap as a named export. The import
import { FocusTrap } from "focus-trap-react";at line 28 is the correct and required style for this version. All instances in the codebase (ArtBlocksTokenCard.tsx, TermsOfServiceModal.tsx, and HeaderSearchModal.tsx) consistently use the named import, and no runtime errors will occur.
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
next.config.mjs (1)
115-126: Add dynamically resolved IPFS gateway hostname to images.domains allowlistThe current allowlist includes only the hardcoded "ipfs.6529.io", but resolveIpfsUrl constructs image URLs from IPFS_GATEWAY_ENDPOINT, which varies across environments (test: ipfs.test.6529.io, dev: ipfs.6529.io, fallback: ipfs.io). Images from mismatched gateways will be blocked by next/image. Extract the hostname from IPFS_GATEWAY_ENDPOINT and add it dynamically to the allowlist.
Apply the suggested diff to lines 115-126 in next.config.mjs within the sharedConfig function.
♻️ Duplicate comments (1)
components/header/header-search/HeaderSearchModalItem.tsx (1)
160-167: Guard collectionMap lookup and add safe fallbacks (prevents runtime crash)If nft.contract isn’t in the map, collectionMap[key] is undefined and the component throws. Normalize, guard, and fall back to a generic route/title.
- const collectionMap = getNftCollectionMap(); - const key = nft.contract.toLowerCase(); - return `${collectionMap[key].path}/${nft.id}`; + const collectionMap = getNftCollectionMap(); + const key = String(nft.contract || "").toLowerCase(); + const entry = collectionMap[key]; + return `${(entry?.path ?? `/collection/${key}`)}/${nft.id}`; @@ - const collectionMap = getNftCollectionMap(); - const key = nft.contract.toLowerCase(); - return `${collectionMap[key].title} #${nft.id}`; + const collectionMap = getNftCollectionMap(); + const key = String(nft.contract || "").toLowerCase(); + const entry = collectionMap[key]; + return `${(entry?.title ?? key)} #${nft.id}`;Optionally, hoist getNftCollectionMap to a top-level constant to avoid recomputation per render.
Also applies to: 206-214
🧹 Nitpick comments (4)
components/common/TabToggle.tsx (1)
36-54: Add aria-orientation and button type for accessibility and form safetyProvide correct semantics and prevent accidental form submit.
- return ( - <div className={containerClasses} role="tablist"> + return ( + <div className={containerClasses} role="tablist" aria-orientation={orientation}> {options.map((option) => ( <button key={option.key} + type="button" onClick={() => onSelect(option.key)} role="tab" aria-selected={activeKey === option.key} aria-controls={option.panelId}components/header/header-search/HeaderSearchModalPfp.tsx (1)
37-49: Fallback to placeholder if image fails to loadPrevent broken avatars by showing the level badge when the resolved URL 404s or is blocked.
-import { useResolvedIpfsUrl } from "@/hooks/useResolvedIpfsUrl"; +import { useResolvedIpfsUrl } from "@/hooks/useResolvedIpfsUrl"; +import { useState } from "react"; @@ export default function HeaderSearchModalPfp({ @@ }) { - const { data: resolved } = useResolvedIpfsUrl(src); + const { data: resolved } = useResolvedIpfsUrl(src); + const [failed, setFailed] = useState(false); @@ - if (!resolved) { + if (!resolved || failed) { return ( <div style={{ width: size, height: size }} className={`tw-rounded-full tw-flex tw-items-center tw-justify-center tw-text-sm tw-font-semibold ${levelColor}`}> {level} </div> ); } @@ <Image src={resolved} alt={alt ?? ""} width={size} height={size} className="tw-rounded-full tw-object-cover" + onError={() => setFailed(true)} />components/header/header-search/HeaderSearchModalItem.tsx (1)
18-21: Align icon usage with project guideline (FontAwesome over Heroicons)Replace
DocumentTextIconfrom Heroicons and custom icon components with FontAwesome equivalents to comply with coding guidelines for**/*.tsxfiles.Example minimal fallback replacement:
-import { DocumentTextIcon } from "@heroicons/react/24/outline"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faFileLines, faMessage, faWaveSquare } from "@fortawesome/free-solid-svg-icons"; @@ -const getMediaIcon = (Icon: ComponentType<{ className?: string }>) => { +const getMediaIcon = (Icon: ComponentType<{ className?: string }>) => { return ( <div className="tw-flex tw-h-10 tw-w-10 tw-items-center tw-justify-center tw-rounded-lg tw-bg-iron-900"> - <Icon className="tw-h-5 tw-w-5" /> + <Icon className="tw-h-5 tw-w-5" /> </div> ); }; @@ - const Icon = page.icon ?? DocumentTextIcon; - return getMediaIcon(Icon); + const DefaultPageIcon: ComponentType<{ className?: string }> = ({ className }) => ( + <FontAwesomeIcon icon={faFileLines} className={className ?? ""} /> + ); + const Icon = page.icon ?? DefaultPageIcon; + return getMediaIcon(Icon); @@ - if (isDm) { - return getMediaIcon(ChatBubbleIcon); - } - return getMediaIcon(WavesIcon); + if (isDm) { + const ChatIcon: ComponentType<{ className?: string }> = ({ className }) => ( + <FontAwesomeIcon icon={faMessage} className={className ?? ""} /> + ); + return getMediaIcon(ChatIcon); + } + const WaveIcon: ComponentType<{ className?: string }> = ({ className }) => ( + <FontAwesomeIcon icon={faWaveSquare} className={className ?? ""} /> + ); + return getMediaIcon(WaveIcon);Also applies to: 108-114, 123-127, 139-143
components/header/header-search/HeaderSearchModal.tsx (1)
221-223: Remove redundant map after type guard filter.The type guard filter already narrows the type to
string[], making the subsequent.map((value) => value)redundant.Apply this diff:
breadcrumbs: [entry.section, entry.subsection] .filter((value): value is string => !!value) - .map((value) => value), + ,
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
__tests__/components/header/HeaderSearchModalItem.test.tsx(3 hunks)codex/tickets/TKT-0011.md(1 hunks)components/common/TabToggle.tsx(1 hunks)components/header/header-search/HeaderSearchModal.tsx(13 hunks)components/header/header-search/HeaderSearchModalItem.tsx(7 hunks)components/header/header-search/HeaderSearchModalItemHighlight.tsx(0 hunks)components/header/header-search/HeaderSearchModalPfp.tsx(1 hunks)hooks/useResolvedIpfsUrl.ts(1 hunks)next.config.mjs(1 hunks)
💤 Files with no reviewable changes (1)
- components/header/header-search/HeaderSearchModalItemHighlight.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
- tests/components/header/HeaderSearchModalItem.test.tsx
- codex/tickets/TKT-0011.md
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before propsUse TypeScript across the codebase
Files:
hooks/useResolvedIpfsUrl.tscomponents/header/header-search/HeaderSearchModalPfp.tsxcomponents/header/header-search/HeaderSearchModalItem.tsxcomponents/header/header-search/HeaderSearchModal.tsxcomponents/common/TabToggle.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursorrules)
**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for stylingUse React functional components with hooks for UI components
Files:
components/header/header-search/HeaderSearchModalPfp.tsxcomponents/header/header-search/HeaderSearchModalItem.tsxcomponents/header/header-search/HeaderSearchModal.tsxcomponents/common/TabToggle.tsx
🧬 Code graph analysis (4)
hooks/useResolvedIpfsUrl.ts (1)
components/ipfs/IPFSContext.tsx (1)
resolveIpfsUrl(67-77)
components/header/header-search/HeaderSearchModalPfp.tsx (1)
hooks/useResolvedIpfsUrl.ts (1)
useResolvedIpfsUrl(4-11)
components/header/header-search/HeaderSearchModalItem.tsx (3)
entities/IProfile.ts (1)
CommunityMemberMinimal(301-312)generated/models/ApiWave.ts (1)
ApiWave(27-177)components/header/header-search/HeaderSearchModalPfp.tsx (1)
HeaderSearchModalPfp(12-52)
components/header/header-search/HeaderSearchModal.tsx (6)
hooks/useSidebarSections.ts (3)
SidebarPageEntry(189-195)useSidebarSections(7-180)mapSidebarSectionsToPages(197-222)components/header/header-search/HeaderSearchModalItem.tsx (4)
HeaderSearchModalItemType(48-52)PageSearchResult(40-46)NFTSearchResult(31-38)HeaderSearchModalItem(54-254)components/app-wallets/AppWalletsContext.tsx (1)
useAppWallets(217-223)components/cookies/CookieConsentContext.tsx (1)
useCookieConsent(43-50)helpers/navigation.helpers.ts (2)
getWaveHomeRoute(73-83)getWaveRoute(23-71)components/common/TabToggle.tsx (1)
TabToggle(18-62)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (6)
components/header/header-search/HeaderSearchModal.tsx (6)
4-8: Verify icon component usage against guidelines.The coding guidelines specify "Use FontAwesome for icons" for
.tsxfiles, but the code imports custom icon components (BellIcon, ChatBubbleIcon, DiscoverIcon, HomeIcon, WavesIcon) instead of FontAwesome.As per coding guidelines
Please confirm whether these custom icon components are approved exceptions or if FontAwesome equivalents should be used instead.
258-266: Custom wheel handling adds complexity; verify necessity.The manual wheel event handler prevents default scrolling and manually updates
resultsPanelRef.current.scrollBy(). This pattern is unusual and can interfere with browser scroll features (momentum scrolling, accessibility tools).Verify whether this custom wheel handling is necessary. If the goal is to prevent body scroll while modal is open, the
overflow: hiddenon body (line 253) already achieves that. If the intent is to control panel scrolling, consider whether the native overflow behavior is sufficient.If custom handling is required, document the specific use case in code (though note: TSX guidelines prohibit comments, so consider a separate documentation file).
436-491: Staged fetching orchestration is complex; verify correctness.The effects implementing staged fetching (NFTs → Profiles → Waves) add significant complexity. While this may optimize API load, the interdependencies between
allowProfileFetch,allowWaveFetch,nftsSettled,profilesSettled, andselectedCategorycreate intricate state transitions.Verify that all state paths work correctly:
- User searches, switches to ALL → should stage fetches
- User searches, switches to PROFILES → should fetch profiles immediately
- User searches, switches to WAVES → should fetch waves immediately
- User types while on ALL → should reset and restage
Consider adding unit tests for this state orchestration or simplifying to parallel fetches if the staging optimization isn't critical.
698-711: LGTM: State machine correctly handles NO_RESULTS condition.The state machine correctly shows NO_RESULTS when searches complete without results. The previous issue (always showing LOADING due to
isSearchingcheck) has been properly resolved by checking onlyanyFetching.
856-1053: LGTM: Modal structure and accessibility features are well-implemented.The modal correctly implements:
- Focus trap with proper fallback and initial focus
- Responsive layout with mobile/desktop variants
- State-based rendering with appropriate ARIA attributes
- Keyboard navigation support
- Clear visual feedback for all states
150-1054: Well-architected unified search with comprehensive category support.The component demonstrates solid engineering:
- Proper memoization of derived state to avoid unnecessary recalculations
- Comprehensive accessibility with focus management, ARIA attributes, and keyboard navigation
- Responsive design with mobile-first approach
- Good error boundaries and retry logic
- Debounced input for performance
The staged API fetching, while complex, appears intentional for load management. Consider documenting the rationale for this pattern in a separate ADR or design doc (since TSX guidelines prohibit comments).
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
__tests__/components/header/HeaderSearchModalItem.test.tsx (3)
93-123: Add QueryClientProvider wrapper for consistency.This test renders
HeaderSearchModalItemwithout aQueryClientProvider, while the profile test (lines 71-82) includes one. For consistency and to prevent future issues if the component or its children adopt React Query hooks, wrap this test with the provider as well.Consider creating a test helper function to reduce duplication:
const renderWithQueryClient = (ui: React.ReactElement) => { const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false }, mutations: { retry: false }, }, }); return render( <QueryClientProvider client={queryClient}> {ui} </QueryClientProvider> ); };Then use it consistently across all tests.
125-150: Add QueryClientProvider wrapper for consistency.Same as the NFT test, this test should wrap the component with
QueryClientProviderfor consistency with the profile test.
152-181: Add QueryClientProvider wrapper for consistency.Same as the NFT and Wave tests, this new page test should wrap the component with
QueryClientProviderfor consistency with the profile test.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
__tests__/components/header/HeaderSearchModalItem.test.tsx(4 hunks)__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx(7 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before propsUse TypeScript across the codebase
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursorrules)
**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for stylingUse React functional components with hooks for UI components
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx
__tests__/**
📄 CodeRabbit inference engine (tests/AGENTS.md)
Place Jest test suites under the
__tests__directory mirroring source folders (e.g., components, contexts, hooks, utils)
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx
__tests__/components/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Use
@testing-library/reactand@testing-library/user-eventfor React component tests
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx
**/__tests__/**
📄 CodeRabbit inference engine (AGENTS.md)
Place tests in
__tests__directories when organizing test suites
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx
**/*.test.tsx
📄 CodeRabbit inference engine (AGENTS.md)
When colocating tests with components, name them
ComponentName.test.tsx
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Mock external dependencies and APIs in tests
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx
🧠 Learnings (1)
📚 Learning: 2025-09-28T12:33:30.950Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:30.950Z
Learning: Applies to __tests__/components/**/*.{ts,tsx,js,jsx} : Use `testing-library/react` and `testing-library/user-event` for React component tests
Applied to files:
__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx
🧬 Code graph analysis (2)
__tests__/components/header/HeaderSearchModalItem.test.tsx (1)
components/header/header-search/HeaderSearchModalItem.tsx (1)
HeaderSearchModalItem(54-254)
__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx (1)
hooks/useDeviceInfo.ts (1)
useDeviceInfo(22-78)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (9)
__tests__/components/header/HeaderSearchModalItem.test.tsx (3)
49-54: LGTM: Simplified window.matchMedia mock.The updated
window.matchMediamock is cleaner and sufficient for testing hover behavior.
86-88: LGTM: Case-insensitive assertions improve test resilience.Using regex with the
/iflag makes these assertions more robust to text formatting variations.
152-181: LGTM: Comprehensive page item test coverage.The new test properly validates page item rendering, including href, title, breadcrumbs formatting, and icon presence.
__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx (6)
18-27: LGTM! Mock declarations properly typed and comprehensive.The added type annotations for existing mocks improve type safety, and the new mock declarations align with the expanded component dependencies for the unified search feature.
63-80: LGTM! Partial mocking pattern correctly preserves utility function.The approach of using
jest.requireActualto preservemapSidebarSectionsToPageswhile mocking theuseSidebarSectionshook is appropriate—it allows the real utility to be exercised in tests while maintaining control over hook return values.
86-96: LGTM! Minimal test fixture is appropriate.The
defaultSidebarSectionsprovides a minimal but complete structure for testing. Theicon: () => nullis acceptable since this test focuses on focus management rather than rendering behavior.
138-138: LGTM! Mock initialization aligns with unified search refactor.The switch from
"PROFILES"to"ALL"correctly reflects the new multi-category search default, and the deterministic mock values ensure consistent test behavior.Also applies to: 140-143
146-147: LGTM! Constant eliminates magic string.Introducing
PLACEHOLDER_TEXTcentralizes the placeholder text value and improves maintainability.
156-156: LGTM! Consistent usage of PLACEHOLDER_TEXT constant.All placeholder text lookups correctly reference the constant, ensuring consistency across the test.
Also applies to: 194-195, 201-201, 210-212
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
__tests__/components/header/HeaderSearchModalItem.test.tsx (2)
1-9: QueryClient configuration addressed; remove unuseduseRouterdeclaration.The addition of
QueryClientandQueryClientProviderimports properly addresses the past review feedback.However, line 9 declares
useRouterbut never connects it to ajest.mockcall. The component usesusePathnameanduseSearchParamsfromnext/navigation, notuseRouter. This declaration is unused and should be removed.Apply this diff:
const useHoverDirty = jest.fn(); -const useRouter = jest.fn();
91-108: Consider checking for the actual rendered handle value.The profile object has
handle: "alice"(line 92), which is what the component renders as the primary text (seegetPrimaryText()in the component code). However, the test checks for/Alice/i(lines 103-104), relying on case-insensitive matching.While the test passes correctly due to the case-insensitive regex, it would be clearer to check for the actual rendered value
"alice"to make the test expectations explicit.- expect(screen.getByText(/Alice/i)).toBeInTheDocument(); - expect(link.textContent).toMatch(/Alice/i); + expect(screen.getByText("alice")).toBeInTheDocument(); + expect(link.textContent).toContain("alice");
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
__tests__/components/header/HeaderSearchModalItem.test.tsx(2 hunks)hooks/useResolvedIpfsUrl.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- hooks/useResolvedIpfsUrl.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before propsUse TypeScript across the codebase
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursorrules)
**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for stylingUse React functional components with hooks for UI components
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx
__tests__/**
📄 CodeRabbit inference engine (tests/AGENTS.md)
Place Jest test suites under the
__tests__directory mirroring source folders (e.g., components, contexts, hooks, utils)
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx
__tests__/components/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Use
@testing-library/reactand@testing-library/user-eventfor React component tests
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx
**/__tests__/**
📄 CodeRabbit inference engine (AGENTS.md)
Place tests in
__tests__directories when organizing test suites
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx
**/*.test.tsx
📄 CodeRabbit inference engine (AGENTS.md)
When colocating tests with components, name them
ComponentName.test.tsx
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Mock external dependencies and APIs in tests
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx
🧬 Code graph analysis (1)
__tests__/components/header/HeaderSearchModalItem.test.tsx (2)
components/header/header-search/HeaderSearchModalItem.tsx (2)
HeaderSearchModalItemType(48-52)HeaderSearchModalItem(54-254)constants.ts (1)
MEMES_CONTRACT(6-6)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Analyze (actions)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (3)
__tests__/components/header/HeaderSearchModalItem.test.tsx (3)
51-58: LGTM!The
window.matchMediamock setup correctly simulates hover support and ensures test isolation withclearAllMocks.
60-85: LGTM! Past review feedback addressed.The
renderComponenthelper properly configures theQueryClientwithretry: falsefor both queries and mutations, which addresses the previous review feedback. Creating a newQueryClientinstance per test ensures proper test isolation.
149-168: LGTM! Comprehensive coverage of the new PageSearchResult type.The new test case properly validates the rendering of page items, including:
- Correct href construction
- Title display in primary text
- Breadcrumbs rendering in secondary text (using the bullet separator)
- Custom icon rendering
The test structure aligns well with the
PageSearchResulttype and the component's page-handling logic.
There was a problem hiding this comment.
Actionable comments posted: 5
♻️ Duplicate comments (3)
components/header/header-search/HeaderSearchModal.tsx (3)
78-94: Avoid duplicating primary navigation; derive from the canonical source.PRIMARY_NAVIGATION_PAGES can drift from header/sidebar config. Prefer building Pages from useSidebarSections (or a shared exported nav).
780-799: Use stable keys without index suffix to prevent remounts.Index in keys causes remounts and lost focus/selection on list updates. Remove :index.
- const getItemKey = ( - item: HeaderSearchModalItemType, - index: number - ): string => { + const getItemKey = (item: HeaderSearchModalItemType): string => { if (isPageResult(item)) { - return `page:${item.href}:${index}`; + return `page:${item.href}`; } if (isNftResult(item)) { - return `nft:${item.contract}:${item.id}:${index}`; + return `nft:${item.contract}:${item.id}`; } if (isProfileResult(item)) { const base = (item.handle ?? item.wallet ?? "profile").toLowerCase(); - return `profile:${base}:${index}`; + return `profile:${base}`; } if (isWaveResult(item)) { - return `wave:${item.id}:${index}`; + return `wave:${item.id}`; } - return `result:${index}`; + return JSON.stringify(item); }; @@ - const renderItem = (item: HeaderSearchModalItemType, index: number) => ( + const renderItem = (item: HeaderSearchModalItemType, index: number) => ( <div ref={index === selectedItemIndex ? activeElementRef : null} - key={getItemKey(item, index)}> + key={getItemKey(item)}> <HeaderSearchModalItemAlso applies to: 800-812
650-653: Fix Enter-key NFT routing: not all NFTs are Memes.Build the path from contract mapping (same logic as item component) with fallback; don’t hard-code /the-memes.
+import { + GRADIENT_CONTRACT, + MEMELAB_CONTRACT, + MEMES_CONTRACT, +} from "@/constants"; +import { NEXTGEN_CORE, NEXTGEN_CHAIN_ID } from "@/components/nextGen/nextgen_contracts"; @@ - if (isNftResult(item)) { - router.push(`/the-memes/${item.id}`); - onClose(); - return; - } + if (isNftResult(item)) { + const map: Record<string, string> = { + [MEMES_CONTRACT.toLowerCase()]: "/the-memes", + [MEMELAB_CONTRACT.toLowerCase()]: "/meme-lab", + [GRADIENT_CONTRACT.toLowerCase()]: "/6529-gradient", + [NEXTGEN_CORE[NEXTGEN_CHAIN_ID].toLowerCase()]: "/nextgen/token", + }; + const key = String(item.contract || "").toLowerCase(); + const base = map[key] ?? `/nft/${key}`; + router.push(`${base}/${item.id}`); + onClose(); + return; + }
🧹 Nitpick comments (3)
__tests__/components/header/HeaderSearchModalItem.test.tsx (1)
74-90: Minor: prefer userEvent for clicks for realism.Switch fireEvent.click to userEvent.click for interaction fidelity; keep current assertions.
Also applies to: 113-137, 151-157, 172-178
components/header/header-search/HeaderSearchModalItem.tsx (1)
84-103: Optional: hoist getNftCollectionMap outside the component.Avoid re-creating the map on every render; move to a module-level const.
components/header/header-search/HeaderSearchModal.tsx (1)
240-272: Optional: extend scroll lock to touch devices.Add touchmove listener to route scrolls to resultsPanel for iOS.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
__tests__/components/header/HeaderSearchModalItem.test.tsx(3 hunks)__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx(7 hunks)codex/STATE.md(1 hunks)codex/tickets/TKT-0015.md(1 hunks)components/common/TabToggle.tsx(1 hunks)components/header/header-search/HeaderSearchModal.tsx(12 hunks)components/header/header-search/HeaderSearchModalItem.tsx(7 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- codex/STATE.md
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before propsUse TypeScript across the codebase
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsxcomponents/header/header-search/HeaderSearchModalItem.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsxcomponents/common/TabToggle.tsxcomponents/header/header-search/HeaderSearchModal.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursorrules)
**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for stylingUse React functional components with hooks for UI components
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsxcomponents/header/header-search/HeaderSearchModalItem.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsxcomponents/common/TabToggle.tsxcomponents/header/header-search/HeaderSearchModal.tsx
__tests__/**
📄 CodeRabbit inference engine (tests/AGENTS.md)
Place Jest test suites under the
__tests__directory mirroring source folders (e.g., components, contexts, hooks, utils)
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx
__tests__/components/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Use
@testing-library/reactand@testing-library/user-eventfor React component tests
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx
**/__tests__/**
📄 CodeRabbit inference engine (AGENTS.md)
Place tests in
__tests__directories when organizing test suites
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx
**/*.test.tsx
📄 CodeRabbit inference engine (AGENTS.md)
When colocating tests with components, name them
ComponentName.test.tsx
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Mock external dependencies and APIs in tests
Files:
__tests__/components/header/HeaderSearchModalItem.test.tsx__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx
🧠 Learnings (1)
📚 Learning: 2025-09-28T12:33:30.950Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:30.950Z
Learning: Applies to __tests__/components/**/*.{ts,tsx,js,jsx} : Use `testing-library/react` and `testing-library/user-event` for React component tests
Applied to files:
__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx
🧬 Code graph analysis (4)
__tests__/components/header/HeaderSearchModalItem.test.tsx (2)
components/header/header-search/HeaderSearchModalItem.tsx (2)
HeaderSearchModalItemType(45-49)HeaderSearchModalItem(51-251)constants.ts (1)
MEMES_CONTRACT(6-6)
components/header/header-search/HeaderSearchModalItem.tsx (3)
entities/IProfile.ts (1)
CommunityMemberMinimal(301-312)generated/models/ApiWave.ts (1)
ApiWave(27-177)components/header/header-search/HeaderSearchModalPfp.tsx (1)
HeaderSearchModalPfp(12-52)
__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx (1)
hooks/useDeviceInfo.ts (1)
useDeviceInfo(22-78)
components/header/header-search/HeaderSearchModal.tsx (7)
hooks/useSidebarSections.ts (3)
SidebarPageEntry(189-195)useSidebarSections(7-180)mapSidebarSectionsToPages(197-222)components/header/header-search/HeaderSearchModalItem.tsx (4)
HeaderSearchModalItemType(45-49)PageSearchResult(37-43)NFTSearchResult(28-35)HeaderSearchModalItem(51-251)components/app-wallets/AppWalletsContext.tsx (1)
useAppWallets(217-223)components/cookies/CookieConsentContext.tsx (1)
useCookieConsent(43-50)entities/IProfile.ts (1)
CommunityMemberMinimal(301-312)helpers/navigation.helpers.ts (2)
getWaveHomeRoute(73-83)getWaveRoute(23-71)components/common/TabToggle.tsx (1)
TabToggle(18-65)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (3)
__tests__/components/header/header-search/HeaderSearchModalFocus.test.tsx (1)
64-75: Tests read well and are deterministic.Mocks and placeholder constant make focus tests stable. No issues.
Also applies to: 88-99, 150-161, 196-206
components/header/header-search/HeaderSearchModalItem.tsx (1)
160-162: Guard collectionMap lookups to prevent runtime crash; also address icon library compliance.Accessing
collectionMap[key]without fallback will crash if contract is unknown. Additionally,DocumentTextIconviolates the FontAwesome guideline for.tsxfiles.Lines 160–161 and 204–205: Add defensive guards for collectionMap access with sensible fallbacks (e.g., abbreviated contract address). Replace
DocumentTextIconimport with a FontAwesome icon.Confirm that the fallback paths you use (if referencing
/nft/routes) exist in your routing configuration.codex/tickets/TKT-0015.md (1)
36-37: Clarify the status of "queued regressions" before merging.The final log entry mentions "queued regressions for follow-up validation once the suite stabilises." This phrasing is ambiguous—it's unclear whether these are:
- Known failing tests that should be fixed before merge, or
- Preventative regression checks deferred to a follow-up PR.
If regressions exist, they should either be resolved in this PR or linked/tracked as explicit follow-up issues rather than left pending. If these are planned follow-up validations, update the log entry to be more explicit about what will be validated and when.
|
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
components/header/share/HeaderShare.tsx (1)
84-85: Use FontAwesome for the QR/share icon.Replace Heroicons ShareIcon per TSX guideline.
-import { ShareIcon } from "@heroicons/react/24/outline"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faQrcode } from "@fortawesome/free-solid-svg-icons"; @@ - <ShareIcon className="tw-h-6 tw-w-6 tw-flex-shrink-0" /> + <FontAwesomeIcon icon={faQrcode} className="tw-h-6 tw-w-6 tw-flex-shrink-0" />
♻️ Duplicate comments (6)
components/header/header-search/HeaderSearchModal.tsx (4)
79-95: Avoid duplicating primary navigation (staleness risk).PRIMARY_NAVIGATION_PAGES hardcodes nav; derive from the canonical nav source used by the header/sidebar.
I can wire this to the shared navigation config or hook you’re using for the header.
26-27: Replace Heroicons and inline SVG with FontAwesome (TSX guideline).Swap ChevronLeft/X and the search glyph to FontAwesome.
-import { ChevronLeftIcon, XMarkIcon } from "@heroicons/react/24/outline"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faChevronLeft, faXmark, faMagnifyingGlass } from "@fortawesome/free-solid-svg-icons"; @@ - <ChevronLeftIcon className="tw-size-6 tw-flex-shrink-0" /> + <FontAwesomeIcon icon={faChevronLeft} className="tw-size-6 tw-flex-shrink-0" /> @@ - <svg - className="tw-pointer-events-none tw-absolute tw-left-4 tw-top-3.5 tw-h-5 tw-w-5 tw-text-iron-300" - viewBox="0 0 20 20" - fill="currentColor" - aria-hidden="true"> - <path - fillRule="evenodd" - d="M9 3.5a5.5 5.5 0 100 11 5.5 5.5 0 000-11zM2 9a7 7 0 1112.452 4.391l3.328 3.329a.75.75 0 11-1.06 1.06l-3.329-3.328A7 7 0 012 9z" - clipRule="evenodd" - /> - </svg> + <FontAwesomeIcon + icon={faMagnifyingGlass} + className="tw-pointer-events-none tw-absolute tw-left-4 tw-top-3.5 tw-h-5 tw-w-5 tw-text-iron-300" + /> @@ - <XMarkIcon className="tw-size-5" /> + <FontAwesomeIcon icon={faXmark} className="tw-size-5" />Also applies to: 889-890, 892-903, 929-935
655-658: Add NFT collection fallback in Enter-key navigation.Unknown contracts will throw on collectionMap[key].path; guard and fall back to a safe route.
- const collectionMap = getNftCollectionMap(); - const key = item.contract.toLowerCase(); - router.push(`${collectionMap[key].path}/${item.id}`); + const collectionMap = getNftCollectionMap(); + const key = String(item.contract ?? "").toLowerCase(); + const col = collectionMap[key]; + router.push(col?.path ? `${col.path}/${item.id}` : `/${item.contract}/${item.id}`);
879-882: Add role="dialog" to the modal container for a11y.Currently only aria-modal/aria-labelledby are set; add role="dialog".
- <div - ref={modalRef} - aria-modal="true" - aria-labelledby="header-search-input" + <div + ref={modalRef} + role="dialog" + aria-modal="true" + aria-labelledby="header-search-input"components/header/header-search/HeaderSearchModalItem.tsx (2)
20-20: Replace Heroicons with FontAwesome (TSX guideline).Use FontAwesome instead of DocumentTextIcon for the default Page icon.
-import { DocumentTextIcon } from "@heroicons/react/24/outline"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faFileLines } from "@fortawesome/free-regular-svg-icons"; @@ - const page = getPage(); - const Icon = page.icon ?? DocumentTextIcon; - return getMediaIcon(Icon); + const page = getPage(); + const Icon = + page.icon ?? + ((props: { className?: string }) => ( + <FontAwesomeIcon icon={faFileLines} className={props.className} /> + )); + return getMediaIcon(Icon);Also applies to: 121-123
159-162: Add safe fallback for NFT collection lookups (avoid crash on unknown contract).Indexing collectionMap[key] without existence checks can throw. Normalize and fall back for path/title.
- const collectionMap = getNftCollectionMap(); - const key = nft.contract.toLowerCase(); - return `${collectionMap[key].path}/${nft.id}`; + const collectionMap = getNftCollectionMap(); + const key = String(nft.contract ?? "").toLowerCase(); + const col = collectionMap[key]; + return col?.path ? `${col.path}/${nft.id}` : `/${nft.contract}/${nft.id}`; @@ - const collectionMap = getNftCollectionMap(); - const key = nft.contract.toLowerCase(); - return `${collectionMap[key].title} #${nft.id}`; + const collectionMap = getNftCollectionMap(); + const key = String(nft.contract ?? "").toLowerCase(); + const col = collectionMap[key]; + return `${col?.title ?? nft.contract} #${nft.id}`;Also applies to: 203-206
🧹 Nitpick comments (2)
components/header/share/HeaderShare.tsx (1)
510-539: Prefer react-query for fetching version manifests (caching/retries).Move S3 YAML fetches into useQuery + Promise.all to leverage caching, retries, and error states.
I can provide a minimal refactor using useQuery with staleTime and error UI if you want.
components/header/header-search/HeaderSearchModal.tsx (1)
299-316: Gate NFT query by category to reduce load.Only fetch NFTs when relevant (ALL or NFTS), consistent with profiles/waves gating.
- }, useQuery<NFTSearchResult[], Error>({ + }, useQuery<NFTSearchResult[], Error>({ @@ - enabled: shouldSearchNfts, + enabled: + shouldSearchNfts && + (selectedCategory === CATEGORY.ALL || selectedCategory === CATEGORY.NFTS),
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
__tests__/components/header/share/HeaderShare.test.tsx(2 hunks)components/header/header-search/HeaderSearchModal.tsx(12 hunks)components/header/header-search/HeaderSearchModalItem.tsx(6 hunks)components/header/header-search/HeaderSearchTabToggle.tsx(1 hunks)components/header/share/HeaderShare.tsx(3 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before propsUse TypeScript across the codebase
Files:
__tests__/components/header/share/HeaderShare.test.tsxcomponents/header/header-search/HeaderSearchTabToggle.tsxcomponents/header/header-search/HeaderSearchModal.tsxcomponents/header/share/HeaderShare.tsxcomponents/header/header-search/HeaderSearchModalItem.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursorrules)
**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for stylingUse React functional components with hooks for UI components
Files:
__tests__/components/header/share/HeaderShare.test.tsxcomponents/header/header-search/HeaderSearchTabToggle.tsxcomponents/header/header-search/HeaderSearchModal.tsxcomponents/header/share/HeaderShare.tsxcomponents/header/header-search/HeaderSearchModalItem.tsx
__tests__/**
📄 CodeRabbit inference engine (tests/AGENTS.md)
Place Jest test suites under the
__tests__directory mirroring source folders (e.g., components, contexts, hooks, utils)
Files:
__tests__/components/header/share/HeaderShare.test.tsx
__tests__/components/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Use
@testing-library/reactand@testing-library/user-eventfor React component tests
Files:
__tests__/components/header/share/HeaderShare.test.tsx
**/__tests__/**
📄 CodeRabbit inference engine (AGENTS.md)
Place tests in
__tests__directories when organizing test suites
Files:
__tests__/components/header/share/HeaderShare.test.tsx
**/*.test.tsx
📄 CodeRabbit inference engine (AGENTS.md)
When colocating tests with components, name them
ComponentName.test.tsx
Files:
__tests__/components/header/share/HeaderShare.test.tsx
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Mock external dependencies and APIs in tests
Files:
__tests__/components/header/share/HeaderShare.test.tsx
🧠 Learnings (1)
📚 Learning: 2025-09-28T12:29:11.651Z
Learnt from: CR
PR: 6529-Collections/6529seize-frontend#0
File: .cursorrules:0-0
Timestamp: 2025-09-28T12:29:11.651Z
Learning: Applies to **/*.tsx : Use FontAwesome for icons
Applied to files:
components/header/header-search/HeaderSearchModal.tsxcomponents/header/header-search/HeaderSearchModalItem.tsx
🧬 Code graph analysis (2)
components/header/header-search/HeaderSearchModal.tsx (6)
hooks/useSidebarSections.ts (3)
SidebarPageEntry(189-195)useSidebarSections(7-180)mapSidebarSectionsToPages(197-222)components/header/header-search/HeaderSearchModalItem.tsx (5)
HeaderSearchModalItemType(45-49)PageSearchResult(37-43)NFTSearchResult(28-35)getNftCollectionMap(51-70)HeaderSearchModalItem(72-251)components/app-wallets/AppWalletsContext.tsx (1)
useAppWallets(217-223)components/cookies/CookieConsentContext.tsx (1)
useCookieConsent(43-50)helpers/navigation.helpers.ts (2)
getWaveHomeRoute(73-83)getWaveRoute(23-71)components/header/header-search/HeaderSearchTabToggle.tsx (1)
HeaderSearchTabToggle(18-65)
components/header/header-search/HeaderSearchModalItem.tsx (5)
entities/IProfile.ts (1)
CommunityMemberMinimal(301-312)generated/models/ApiWave.ts (1)
ApiWave(27-177)constants.ts (3)
MEMES_CONTRACT(6-6)MEMELAB_CONTRACT(12-12)GRADIENT_CONTRACT(11-11)components/nextGen/nextgen_contracts.ts (2)
NEXTGEN_CORE(54-59)NEXTGEN_CHAIN_ID(29-29)components/header/header-search/HeaderSearchModalPfp.tsx (1)
HeaderSearchModalPfp(12-52)
🔇 Additional comments (1)
__tests__/components/header/share/HeaderShare.test.tsx (1)
318-319: Tests updated for “6529 Desktop” — looks good.Label assertions align with component changes.
Also applies to: 340-343



Summary by CodeRabbit
Release Notes
New Features
Improvements