Skip to content

feat: add command palette and dialog components#3

Merged
markvalenzuela72 merged 3 commits into
mainfrom
feature/global-search
Jul 9, 2026
Merged

feat: add command palette and dialog components#3
markvalenzuela72 merged 3 commits into
mainfrom
feature/global-search

Conversation

@markvalenzuela72

@markvalenzuela72 markvalenzuela72 commented Jul 9, 2026

Copy link
Copy Markdown
Owner
  • Implemented Command, CommandDialog, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandSeparator, CommandItem, and CommandShortcut components for a command palette UI.
  • Created Dialog, DialogTrigger, DialogPortal, DialogClose, DialogOverlay, DialogContent, DialogHeader, DialogFooter, DialogTitle, and DialogDescription components for a dialog UI.
  • Added searchCoins function to fetch coin search results from the API.
  • Updated package.json and package-lock.json to include new dependencies: cmdk, react-use, and swr.
  • Modified SearchCoin interface to make data and price_change_percentage_24h optional.

Summary by CodeRabbit

  • New Features
    • Added a searchable coin finder modal (including Cmd/Ctrl+K) with trending suggestions and navigation to coin detail pages.
    • Added an exchange listings section with recent market info (pair, USD price, and last traded time).
    • Introduced reusable command-palette and dialog UI components to support the new search experience.
  • Bug Fixes
    • Improved coin details loading robustness when network/platform information is missing.
    • Made search result handling more resilient to optional/missing fields.
  • Style
    • Refined search/modal, command palette, and exchange table styling for clearer interaction and layout.

- Implemented Command, CommandDialog, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandSeparator, CommandItem, and CommandShortcut components for a command palette UI.
- Created Dialog, DialogTrigger, DialogPortal, DialogClose, DialogOverlay, DialogContent, DialogHeader, DialogFooter, DialogTitle, and DialogDescription components for a dialog UI.
- Added searchCoins function to fetch coin search results from the API.
- Updated package.json and package-lock.json to include new dependencies: cmdk, react-use, and swr.
- Modified SearchCoin interface to make data and price_change_percentage_24h optional.
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a coin search modal with trending and debounced search, wires it into the header, and adds exchange listings plus a safer coin-detail network derivation. Supporting UI primitives, API helpers, styling, types, and dependencies are updated.

Changes

Search Modal Feature

Layer / File(s) Summary
Dialog and Command UI primitives
components/ui/dialog.tsx, components/ui/command.tsx
Adds reusable dialog and command-palette wrappers with styled Radix/cmdk components and optional close controls.
Search and trending coin API helpers
lib/coingecko.actions.ts, type.d.ts, package.json
Adds searchCoins, makes search result fields more optional, and installs cmdk, react-use, and swr.
SearchModal component logic and rendering
components/SearchModal.tsx
Implements the modal, SWR data loading, keyboard shortcut, query handling, coin selection navigation, and trending/search result rendering.
Header integration and search modal styling
components/header.tsx, app/globals.css
Replaces the header placeholder with SearchModal and updates modal trigger/item styling for hover and selected states.

Exchange Listings and Coin Page Fixes

Layer / File(s) Summary
Exchange listings table and coin page fix
components/LiveDataWrapper.tsx, app/coins/[id]/page.tsx, app/globals.css
Adds the exchange listings table, renders recent tickers, guards the GeckoTerminal URL split, and adjusts exchange-table layout styling.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding command palette and dialog components.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/global-search

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

app/coins/[id]/page.tsx

Oops! Something went wrong! :(

ESLint: 9.39.4

TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Object'
| property 'configs' -> object with constructor 'Object'
| property 'flat' -> object with constructor 'Object'
| ...
| property 'plugins' -> object with constructor 'Object'
--- property 'react' closes the circle
Referenced from: /.eslintrc
at JSON.stringify ()
at /node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2255:45
at Array.map ()
at ConfigValidator.formatErrors (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2246:23)
at ConfigValidator.validateConfigSchema (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2277:84)
at ConfigArrayFactory._normalizeConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3123:19)
at ConfigArrayFactory._loadConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3088:21)
at ConfigArrayFactory._loadExtendedShareableConfig (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3393:21)
at ConfigArrayFactory._loadExtends (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3261:25)
at ConfigArrayFactory._normalizeObjectConfigDataBody (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3199:25)
(node:2) ESLintRCWarning: You are using an eslintrc configuration file, which is deprecated and support will be removed in v10.0.0. Please migrate to an eslint.config.js file. See https://eslint.org/docs/latest/use/configure/migration-guide for details. An eslintrc configuration file is used because you have the ESLINT_USE_FLAT_CONFIG environment variable set to false. If you want to use an eslint.config.js file, remove the environment variable. If you want to find the location of the eslintrc configuration file, use the --debug flag.
(Use node --trace-warnings ... to show where the warning was created)

type.d.ts

Oops! Something went wrong! :(

ESLint: 9.39.4

TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Object'
| property 'configs' -> object with constructor 'Object'
| property 'flat' -> object with constructor 'Object'
| ...
| property 'plugins' -> object with constructor 'Object'
--- property 'react' closes the circle
Referenced from: /.eslintrc
at JSON.stringify ()
at /node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2255:45
at Array.map ()
at ConfigValidator.formatErrors (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2246:23)
at ConfigValidator.validateConfigSchema (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2277:84)
at ConfigArrayFactory._normalizeConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3123:19)
at ConfigArrayFactory._loadConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3088:21)
at ConfigArrayFactory._loadExtendedShareableConfig (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3393:21)
at ConfigArrayFactory._loadExtends (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3261:25)
at ConfigArrayFactory._normalizeObjectConfigDataBody (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3199:25)
(node:2) ESLintRCWarning: You are using an eslintrc configuration file, which is deprecated and support will be removed in v10.0.0. Please migrate to an eslint.config.js file. See https://eslint.org/docs/latest/use/configure/migration-guide for details. An eslintrc configuration file is used because you have the ESLINT_USE_FLAT_CONFIG environment variable set to false. If you want to use an eslint.config.js file, remove the environment variable. If you want to find the location of the eslintrc configuration file, use the --debug flag.
(Use node --trace-warnings ... to show where the warning was created)


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
components/SearchModal.tsx (1)

44-52: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Move getTrendingCoins to lib/coingecko.actions.ts for consistency.

getTrendingCoins is an API helper that calls fetcher from a 'use server' module, yet it's defined and exported from this 'use client' component file. searchCoins lives in lib/coingecko.actions.ts — both functions follow the same pattern and should coexist there. This improves reusability and keeps API logic centralized.

♻️ Proposed refactor

Move getTrendingCoins to lib/coingecko.actions.ts:

+export async function getTrendingCoins(): Promise<TrendingCoin[]> {
+  const res = await fetcher<{ coins: TrendingCoin[] }>(
+    '/search/trending',
+    undefined,
+    300,
+  );
+  return res.coins;
+}

Then in SearchModal.tsx, import it alongside searchCoins:

-import { fetcher, searchCoins } from '`@/lib/coingecko.actions`';
+import { searchCoins, getTrendingCoins } from '`@/lib/coingecko.actions`';

And remove the local definition and the fetcher import.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@components/SearchModal.tsx` around lines 44 - 52, Move getTrendingCoins out
of SearchModal and into lib/coingecko.actions.ts so it lives alongside
searchCoins and the other server-side API helpers. Update SearchModal.tsx to
import getTrendingCoins from that module, remove the local function definition,
and drop any now-unused fetcher import so the client component only consumes the
action.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@components/LiveDataWrapper.tsx`:
- Around line 65-70: The cell renderer in LiveDataWrapper.tsx is rendering the
exchange name as plain text and leaving Link self-closing, which creates an
empty anchor. Update the cell logic so the exchange name from
exchange.market.name is rendered as the child of Link, using exchange.trade_url
as the destination, and keep the fallback text only when the name is missing.
This should be fixed in the cell renderer inside LiveDataWrapper’s column
definition so the displayed exchange label becomes clickable.

In `@components/SearchModal.tsx`:
- Around line 77-85: Handle SWR failures explicitly in SearchModal’s useSWR
calls by destructuring error for both the search and trending-coins requests,
instead of relying on an empty array fallback alone. Update the derived state
and render logic so isNoResults only applies when there is no error, and show an
error message/state when searchCoins (and the trending fetch) fails. Use the
existing SearchModal render conditions and the useSWR hooks as the main places
to wire this in.
- Around line 24-43: Disable cmdk’s client-side filtering for the server-driven
search flow in SearchModal so results are not hidden by mismatched CommandItem
values. Update CommandDialog to accept and forward a shouldFilter prop, and set
shouldFilter to false when rendering SearchModal; keep SearchItem using coin.id
as its value/onSelect target, but ensure cmdk no longer filters those items
against the typed query.

---

Nitpick comments:
In `@components/SearchModal.tsx`:
- Around line 44-52: Move getTrendingCoins out of SearchModal and into
lib/coingecko.actions.ts so it lives alongside searchCoins and the other
server-side API helpers. Update SearchModal.tsx to import getTrendingCoins from
that module, remove the local function definition, and drop any now-unused
fetcher import so the client component only consumes the action.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e3fe5b53-9292-4c79-8115-cc1b5cd4765a

📥 Commits

Reviewing files that changed from the base of the PR and between 5ba1884 and 1373d62.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (10)
  • app/coins/[id]/page.tsx
  • app/globals.css
  • components/LiveDataWrapper.tsx
  • components/SearchModal.tsx
  • components/header.tsx
  • components/ui/command.tsx
  • components/ui/dialog.tsx
  • lib/coingecko.actions.ts
  • package.json
  • type.d.ts

Comment thread components/LiveDataWrapper.tsx
Comment thread components/SearchModal.tsx
Comment thread components/SearchModal.tsx Outdated
@vercel

vercel Bot commented Jul 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
coin-pulse Ready Ready Preview, Comment Jul 9, 2026 12:16pm

@markvalenzuela72 markvalenzuela72 merged commit e725c2a into main Jul 9, 2026
2 of 3 checks passed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
type.d.ts (1)

293-293: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove commented-out hasMorePages instead of leaving dead code.

The downstream consumer CoinsPagination only uses currentPage and totalPages, so hasMorePages is confirmed unused. Commented-out code clutters the interface definition — remove the line entirely.

🧹 Proposed fix
 interface Pagination {
   currentPage: number;
   totalPages: number;
-  // hasMorePages: boolean;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@type.d.ts` at line 293, Remove the commented-out hasMorePages field from the
pagination type definition in the type.d.ts interface instead of leaving dead
code behind. Keep the interface focused on the actually used properties, and
ensure CoinsPagination continues to rely only on currentPage and totalPages.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/coins/`[id]/page.tsx:
- Line 25: Remove the დარჩ debug logging from the coin page and ensure
`app/coins/[id]/page.tsx` no longer calls `console.log(coinOHLCData)` in the
page render flow. Update the `Page` component (or the relevant data-fetching
path that builds `coinOHLCData`) so it simply returns the page data without
writing the OHLC payload to the server console.

---

Nitpick comments:
In `@type.d.ts`:
- Line 293: Remove the commented-out hasMorePages field from the pagination type
definition in the type.d.ts interface instead of leaving dead code behind. Keep
the interface focused on the actually used properties, and ensure
CoinsPagination continues to rely only on currentPage and totalPages.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f6d4df76-5cf9-42f1-b6f5-c21e973dbfc5

📥 Commits

Reviewing files that changed from the base of the PR and between 72eb405 and e829a7a.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (2)
  • app/coins/[id]/page.tsx
  • type.d.ts

Comment thread app/coins/[id]/page.tsx
}),
]);

console.log(coinOHLCData);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove debug console.log before merge.

console.log(coinOHLCData) is a debug artifact that should not be shipped to production. It will log potentially large OHLC arrays to the server console on every coin page request.

🧹 Proposed fix
-  console.log(coinOHLCData);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
console.log(coinOHLCData);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/coins/`[id]/page.tsx at line 25, Remove the დარჩ debug logging from the
coin page and ensure `app/coins/[id]/page.tsx` no longer calls
`console.log(coinOHLCData)` in the page render flow. Update the `Page` component
(or the relevant data-fetching path that builds `coinOHLCData`) so it simply
returns the page data without writing the OHLC payload to the server console.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant