Skip to content

Add Ctrl+F search to projects page - #1541

Open
skyfallwastaken wants to merge 1 commit into
mainfrom
add-projects-ctrl-f-search
Open

Add Ctrl+F search to projects page#1541
skyfallwastaken wants to merge 1 commit into
mainfrom
add-projects-ctrl-f-search

Conversation

@skyfallwastaken

Copy link
Copy Markdown
Member

Summary of the problem

The projects page has an inline filter but does not support the familiar browser find workflow for quickly navigating project matches.

Describe your changes

Adds a compact Chrome-style Ctrl+F and Cmd+F overlay while preserving the existing search bar. Both controls share the same query, show match counts, support previous and next navigation and highlight matching project name text in yellow.

Screenshots / Media

https://ampcode.com/user-content/artifacts/db724bd693d7b8ea9ca6da2e8f715b691cd0723a31fcdb14c7cb399276102116-file.webm

Copilot AI lite review requested due to automatic review settings August 10, 2026 09:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@greptile-apps

greptile-apps Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds a shared project filter with a Ctrl/Cmd+F overlay, match navigation, active-card styling, and highlighted project-name matches.

  • Binds the existing inline filter and new find overlay to one query.
  • Adds virtualized previous/next match navigation.
  • Splits matching project names into highlighted and unhighlighted segments.
  • Adds a system test for the primary keyboard-search workflow.

Confidence Score: 4/5

The stale active-match index should be fixed before merging because interval changes can leave the search overlay and project selection inconsistent.

Preserved-state interval navigation can replace the matching project set without constraining the retained match index; Unicode highlighting and effect-driven reset logic also warrant non-blocking corrections.

Files Needing Attention: app/javascript/pages/Projects/Index.svelte; app/javascript/pages/Projects/components/ProjectCard.svelte

Important Files Changed

Filename Overview
app/javascript/pages/Projects/Index.svelte Adds the find overlay and match navigation, but the active index can become stale when preserved-state interval navigation replaces project data.
app/javascript/pages/Projects/components/ProjectCard.svelte Adds match highlighting, with a Unicode offset mismatch when locale lowercasing changes string length.
test/system/projects_test.rb Covers opening, filtering, highlighting, and closing the new search overlay for an ASCII query.
Prompt To Fix All With AI
### Issue 1
app/javascript/pages/Projects/Index.svelte:184-187
**Match index becomes stale**

When a user selects a later match and changes to an interval with fewer matching projects, the preserved `currentMatchIndex` remains outside the updated result set, causing an impossible count such as 4/2 and leaving no project selected.

### Issue 2
app/javascript/pages/Projects/components/ProjectCard.svelte:62-76
**Lowercasing invalidates highlight offsets**

If a project name contains a character whose locale-lowercased representation has a different UTF-16 length, match offsets calculated from `normalizedName` no longer align with `project.name`, producing incorrectly highlighted or omitted text.

### Issue 3
app/javascript/pages/Projects/Index.svelte:184-187
**Effect derives navigation state**

This effect reads `searchQuery` solely to reset `currentMatchIndex`, splitting query-update behavior between implicit reactive execution and explicit handlers. Reset the index at the query update boundary instead so the navigation state remains explicit and maintainable.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "Add Ctrl+F search to projects page" | Re-trigger Greptile

Comment on lines +184 to +187
$effect(() => {
searchQuery;
currentMatchIndex = 0;
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Match index becomes stale

When a user selects a later match and changes to an interval with fewer matching projects, the preserved currentMatchIndex remains outside the updated result set, causing an impossible count such as 4/2 and leaving no project selected.

Knowledge Base Used: Frontend App (Inertia.js + Svelte)

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/javascript/pages/Projects/Index.svelte
Line: 184-187

Comment:
**Match index becomes stale**

When a user selects a later match and changes to an interval with fewer matching projects, the preserved `currentMatchIndex` remains outside the updated result set, causing an impossible count such as 4/2 and leaving no project selected.

**Knowledge Base Used:** [Frontend App (Inertia.js + Svelte)](https://app.greptile.com/mahadk/-/custom-context/knowledge-base/hackclub/hackatime/-/docs/frontend-app.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment on lines +62 to +76
const normalizedName = project.name.toLocaleLowerCase();
const normalizedQuery = query.toLocaleLowerCase();
let cursor = 0;
let matchStart = normalizedName.indexOf(normalizedQuery);

while (matchStart >= 0) {
if (matchStart > cursor) {
parts.push({
text: project.name.slice(cursor, matchStart),
highlighted: false,
});
}
const matchEnd = matchStart + query.length;
parts.push({
text: project.name.slice(matchStart, matchEnd),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Lowercasing invalidates highlight offsets

If a project name contains a character whose locale-lowercased representation has a different UTF-16 length, match offsets calculated from normalizedName no longer align with project.name, producing incorrectly highlighted or omitted text.

Knowledge Base Used: Frontend App (Inertia.js + Svelte)

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/javascript/pages/Projects/components/ProjectCard.svelte
Line: 62-76

Comment:
**Lowercasing invalidates highlight offsets**

If a project name contains a character whose locale-lowercased representation has a different UTF-16 length, match offsets calculated from `normalizedName` no longer align with `project.name`, producing incorrectly highlighted or omitted text.

**Knowledge Base Used:** [Frontend App (Inertia.js + Svelte)](https://app.greptile.com/mahadk/-/custom-context/knowledge-base/hackclub/hackatime/-/docs/frontend-app.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment on lines +184 to +187
$effect(() => {
searchQuery;
currentMatchIndex = 0;
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Effect derives navigation state

This effect reads searchQuery solely to reset currentMatchIndex, splitting query-update behavior between implicit reactive execution and explicit handlers. Reset the index at the query update boundary instead so the navigation state remains explicit and maintainable.

Rule Used: What: Don't use effects to derive state that can b... (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/javascript/pages/Projects/Index.svelte
Line: 184-187

Comment:
**Effect derives navigation state**

This effect reads `searchQuery` solely to reset `currentMatchIndex`, splitting query-update behavior between implicit reactive execution and explicit handlers. Reset the index at the query update boundary instead so the navigation state remains explicit and maintainable.

**Rule Used:** What: Don't use effects to derive state that can b... ([source](https://app.greptile.com/mahadk/-/custom-context?memory=8569b05b-35ae-4e04-9b00-50fe1f992c68))

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@skyfallwastaken skyfallwastaken added the Needs TLC This PR is good, but it needs some additional work label Aug 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Needs TLC This PR is good, but it needs some additional work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants