Task 18: Add command palette (Ctrl+K)

- Create CommandPalette.tsx with overlay, search input, grouped results,
  keyboard navigation (arrows, Enter, Escape), and footer hints
- Rebuild search.ts with PaletteItem model: 24 entries across 6 sections
  (Experience, Core Skills, Active Projects, Achievements, Education,
  Quick Actions) matching concept HTML structure
- Fuzzy search via fuse.js with weighted keys (title, subtitle, keywords)
- Wire into DashboardLayout with global Ctrl+K listener and TopBar click
- Action system: scroll-to-tile, expand-item, external links, download CV
- Add data-tile-id to all Card/tile components for scroll targeting
- CSS animations: palette-overlay-in, palette-modal-in with
  prefers-reduced-motion support
- Maintain backward-compatible legacy exports for ClinicalSidebar
  (will be removed in Task 21)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-13 17:54:31 +00:00
parent acee97a579
commit aafdeba93e
13 changed files with 836 additions and 80 deletions
+3 -1
View File
@@ -4,9 +4,10 @@ interface CardProps {
children: React.ReactNode
full?: boolean // spans both grid columns
className?: string
tileId?: string // data-tile-id for command palette scroll targeting
}
export function Card({ children, full, className }: CardProps) {
export function Card({ children, full, className, tileId }: CardProps) {
const [isHovered, setIsHovered] = React.useState(false)
const baseStyles: React.CSSProperties = {
@@ -25,6 +26,7 @@ export function Card({ children, full, className }: CardProps) {
<div
style={baseStyles}
className={className}
data-tile-id={tileId}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>