-
Notifications
You must be signed in to change notification settings - Fork 0
Enhanced Cmd+K UI with intelligent autocomplete and type-ahead filtering #2
base: main
Are you sure you want to change the base?
Conversation
- Add modern, professional suggestion panel design with gradient header - Implement full keyboard navigation (up/down arrows, Enter, Escape) - Expand CSS properties list with 20+ additional common properties - Add visual selection indicators and smooth transitions - Include keyboard shortcuts footer in suggestion panel - Add debugging logs to troubleshoot keyboard navigation - Improve suggestion panel positioning and auto-scroll support - Auto-save inserted suggestions to storage 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Remove premature state reset that was causing selectedSuggestionIndex to be -1 - Add comprehensive debugging to track state changes - Improve bounds checking for arrow key navigation - Prevent state reset when recreating suggestion panel 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Implement smart filtering: prefix match → contains match → fuzzy match - Add visual highlighting of matching characters in suggestions - Sort suggestions by relevance (exact prefix first, then by position) - Support abbreviations (e.g., "ani" matches "animation") - Enhanced footer with type filtering hint - Preserve highlighting during keyboard navigation Examples: - "ani" → animation, animation-delay, animation-duration - "back" → background, background-color, background-image - "marg" → margin, margin-top, margin-right, etc. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Remove panel closure on typing events that was preventing type-ahead - Refactor suggestion logic into reusable functions - Add updateSuggestionsFromCurrentText() for real-time updates - Use setTimeout to wait for text changes before updating suggestions - Add detailed logging for debugging type-ahead behavior Now typing "ani" will show animation properties and continue filtering as you type\! 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Create updateSuggestionPanelContent() to update existing panel instead of recreating - Add proper auto-hide timer management with resetAutoHideTimer() - Increase auto-hide timeout to 15 seconds for better type-ahead experience - Clear and reset timer when panel content updates - Add comprehensive logging for debugging panel lifecycle - Preserve panel state while actively typing and filtering Now typing will smoothly filter suggestions without panel flickering or premature closure\! 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Add comprehensive section on Enhanced Autocomplete System in CLAUDE.md - Document smart filtering modes (prefix, contains, fuzzy matching) - Detail keyboard navigation and type-ahead functionality - Update popup instructions with enhanced Cmd+K tips - Revise project descriptions to highlight intelligent auto-completion - Remove outdated preset system references - Add visual features and auto-positioning details Documentation now accurately reflects the professional VS Code-like autocomplete experience. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Add "Recent Major Changes" section documenting preset removal and autocomplete addition - Update version to 1.1.0 to reflect significant feature changes - Enhance keywords with intelligent-autocomplete, type-ahead, syntax-highlighting - Document rationale for removing presets in favor of professional CSS editing - Note performance improvement from removing 125 lines of preset code - Emphasize shift from preset-based to flexible custom CSS approach Documentation now comprehensively covers evolution from v1.0 to v1.1. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
WalkthroughThe update enhances the Chrome extension's CSS editor by introducing an advanced intelligent auto-completion system with type-ahead filtering, real-time linting, code formatting, and a live preview. The preset system is removed, focusing on a professional code editing experience. Documentation, metadata, and user interface instructions are updated accordingly. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Editor (popup.js)
participant SuggestionPanel
User->>Editor: Types in CSS editor
Editor->>Editor: Detects trigger (Cmd+K/Ctrl+K/Ctrl+Space)
Editor->>SuggestionPanel: Show property suggestions (filtered & sorted)
User->>SuggestionPanel: Navigates suggestions (Arrow keys)
User->>SuggestionPanel: Selects suggestion (Enter)
SuggestionPanel->>Editor: Inserts property, updates CSS
Editor->>SuggestionPanel: Auto-hides after inactivity
Poem
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
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 (4)
popup.html (1)
288-291: Use semantic tags for key combosFor shortcut legends we usually wrap keystrokes in to improve accessibility and keep styling consistent across browsers:
- <code>Ctrl/Cmd+K</code> + <kbd>Ctrl/Cmd</kbd><kbd>K</kbd>Same for the other keys.
popup.js (3)
623-637: Refresh the property list
grid-gapis deprecated in favour ofgap; other modern properties (e.g.,place-items,aspect-ratio) are missing.Consider:
- 'grid-gap', + 'gap', 'place-items', 'aspect-ratio',Keeping the list current improves lint accuracy and autocomplete usefulness.
650-697: Minor: simplify filtering withstartsWith/ includes / fuzzyweightsThe custom sort works, but readability would improve by mapping each candidate to a weight (0-prefix, 1-contains, 2-fuzzy) then sorting by that tuple plus
localeCompare. This avoids the tripleifladder and is easier to tweak.
924-931: Panel placement isn’t caret-awarePositioning relative to the textarea’s top-left can place the panel far from the typing point when the editor is scrolled. Using a hidden mirror element or
selectionStartwithgetClientRects()will allow positioning at the caret for a VS-Code-like feel.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
CLAUDE.md(3 hunks)package.json(2 hunks)popup.html(1 hunks)popup.js(2 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
popup.js
[error] 270-270: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 836-836: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 984-985: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (2)
package.json (1)
3-5: Metadata update looks goodVersion bump and richer description align with the feature set.
CLAUDE.md (1)
46-86: Docs LGTMThe new sections clearly document behaviour and shortcuts.
| // Handle suggestion panel navigation | ||
| const activeSuggestionPanel = document.getElementById('suggestion-panel'); | ||
| if (activeSuggestionPanel && activeSuggestionPanel.parentNode) { | ||
| console.log('Suggestion panel is active, handling key:', e.key); | ||
|
|
||
| if (e.key === 'ArrowDown') { | ||
| e.preventDefault(); | ||
| e.stopPropagation(); | ||
| console.log('ArrowDown: current index:', selectedSuggestionIndex, 'max:', currentSuggestions.length - 1); | ||
| selectedSuggestionIndex = Math.min(selectedSuggestionIndex + 1, currentSuggestions.length - 1); | ||
| console.log('Moving down to index:', selectedSuggestionIndex); | ||
| updateSuggestionSelection(); | ||
| return; | ||
| } | ||
|
|
||
| if (e.key === 'ArrowUp') { | ||
| e.preventDefault(); | ||
| e.stopPropagation(); | ||
| console.log('ArrowUp: current index:', selectedSuggestionIndex, 'min: 0'); | ||
| selectedSuggestionIndex = Math.max(selectedSuggestionIndex - 1, 0); | ||
| console.log('Moving up to index:', selectedSuggestionIndex); | ||
| updateSuggestionSelection(); | ||
| return; | ||
| } | ||
|
|
||
| if (e.key === 'Enter') { | ||
| e.preventDefault(); | ||
| e.stopPropagation(); | ||
| if (selectedSuggestionIndex >= 0 && selectedSuggestionIndex < currentSuggestions.length) { | ||
| const selectedSuggestion = currentSuggestions[selectedSuggestionIndex]; | ||
| console.log('Inserting suggestion:', selectedSuggestion); | ||
| insertSuggestion(selectedSuggestion, currentWord); | ||
| closeSuggestionPanel(); | ||
| } | ||
| return; | ||
| } | ||
|
|
||
| if (e.key === 'Escape') { | ||
| e.preventDefault(); | ||
| e.stopPropagation(); | ||
| closeSuggestionPanel(); | ||
| return; | ||
| } | ||
|
|
||
| // For typing keys, update suggestions instead of closing panel | ||
| if (e.key.length === 1 || e.key === 'Backspace' || e.key === 'Delete') { | ||
| console.log('Text modification key pressed:', e.key, '- will update suggestions after text changes'); | ||
| // Don't close panel, let the input event handler update suggestions | ||
| // Use setTimeout to wait for the text to actually change | ||
| setTimeout(() => { | ||
| updateSuggestionsFromCurrentText(); | ||
| }, 10); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Arrow-key navigation can select an item that isn’t rendered
selectedSuggestionIndex is clamped to currentSuggestions.length - 1, but the panel only renders the first 12 items (slice(0, 12)). Navigating ↓ past index 11 leaves no DOM element to highlight, causing updateSuggestionSelection() to scroll nothing and leaves the UI out of sync with the item inserted on Enter.
- selectedSuggestionIndex = Math.min(selectedSuggestionIndex + 1, currentSuggestions.length - 1);
+ const maxVisible = Math.min(currentSuggestions.length, 12) - 1;
+ selectedSuggestionIndex = Math.min(selectedSuggestionIndex + 1, maxVisible);You’ll need similar logic for ↑ and when rebuilding the list.
📝 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.
| // Handle suggestion panel navigation | |
| const activeSuggestionPanel = document.getElementById('suggestion-panel'); | |
| if (activeSuggestionPanel && activeSuggestionPanel.parentNode) { | |
| console.log('Suggestion panel is active, handling key:', e.key); | |
| if (e.key === 'ArrowDown') { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| console.log('ArrowDown: current index:', selectedSuggestionIndex, 'max:', currentSuggestions.length - 1); | |
| selectedSuggestionIndex = Math.min(selectedSuggestionIndex + 1, currentSuggestions.length - 1); | |
| console.log('Moving down to index:', selectedSuggestionIndex); | |
| updateSuggestionSelection(); | |
| return; | |
| } | |
| if (e.key === 'ArrowUp') { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| console.log('ArrowUp: current index:', selectedSuggestionIndex, 'min: 0'); | |
| selectedSuggestionIndex = Math.max(selectedSuggestionIndex - 1, 0); | |
| console.log('Moving up to index:', selectedSuggestionIndex); | |
| updateSuggestionSelection(); | |
| return; | |
| } | |
| if (e.key === 'Enter') { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| if (selectedSuggestionIndex >= 0 && selectedSuggestionIndex < currentSuggestions.length) { | |
| const selectedSuggestion = currentSuggestions[selectedSuggestionIndex]; | |
| console.log('Inserting suggestion:', selectedSuggestion); | |
| insertSuggestion(selectedSuggestion, currentWord); | |
| closeSuggestionPanel(); | |
| } | |
| return; | |
| } | |
| if (e.key === 'Escape') { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| closeSuggestionPanel(); | |
| return; | |
| } | |
| // For typing keys, update suggestions instead of closing panel | |
| if (e.key.length === 1 || e.key === 'Backspace' || e.key === 'Delete') { | |
| console.log('Text modification key pressed:', e.key, '- will update suggestions after text changes'); | |
| // Don't close panel, let the input event handler update suggestions | |
| // Use setTimeout to wait for the text to actually change | |
| setTimeout(() => { | |
| updateSuggestionsFromCurrentText(); | |
| }, 10); | |
| } | |
| } | |
| // Handle suggestion panel navigation | |
| const activeSuggestionPanel = document.getElementById('suggestion-panel'); | |
| if (activeSuggestionPanel && activeSuggestionPanel.parentNode) { | |
| console.log('Suggestion panel is active, handling key:', e.key); | |
| if (e.key === 'ArrowDown') { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| console.log('ArrowDown: current index:', selectedSuggestionIndex, 'max:', currentSuggestions.length - 1); | |
| + const maxVisible = Math.min(currentSuggestions.length, 12) - 1; | |
| + selectedSuggestionIndex = Math.min(selectedSuggestionIndex + 1, maxVisible); | |
| - selectedSuggestionIndex = Math.min(selectedSuggestionIndex + 1, currentSuggestions.length - 1); | |
| console.log('Moving down to index:', selectedSuggestionIndex); | |
| updateSuggestionSelection(); | |
| return; | |
| } | |
| if (e.key === 'ArrowUp') { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| console.log('ArrowUp: current index:', selectedSuggestionIndex, 'min: 0'); | |
| selectedSuggestionIndex = Math.max(selectedSuggestionIndex - 1, 0); | |
| console.log('Moving up to index:', selectedSuggestionIndex); | |
| updateSuggestionSelection(); | |
| return; | |
| } | |
| // … rest of the handler unchanged … | |
| } |
🧰 Tools
🪛 Biome (1.9.4)
[error] 270-270: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🤖 Prompt for AI Agents
In popup.js between lines 268 and 321, the selectedSuggestionIndex is clamped to
currentSuggestions.length - 1, but the suggestion panel only renders the first
12 items, causing the index to exceed the rendered items and break UI
synchronization. To fix this, clamp selectedSuggestionIndex to the minimum of
currentSuggestions.length - 1 and 11 (the max rendered index) for both ArrowDown
and ArrowUp key handling. Also, ensure that when rebuilding the suggestion list,
the selectedSuggestionIndex is adjusted similarly to stay within the rendered
range.
Summary
Major UI enhancement to the CSS property autocomplete system, transforming it into a professional VS Code-like experience with intelligent filtering and full keyboard navigation.
✨ New Features
"back"→ background properties"size"→ font-size, background-size"ani"→ animation properties🗑️ Simplified Architecture
📚 Documentation Updates
🔧 Technical Improvements
Test Plan
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation
Chores