diff --git a/src/components/os/Launcher.tsx b/src/components/os/Launcher.tsx index 236ccf3..d563c06 100644 --- a/src/components/os/Launcher.tsx +++ b/src/components/os/Launcher.tsx @@ -1,4 +1,5 @@ import { useEffect, useMemo, useRef, useState } from 'react'; +import { X } from 'lucide-react'; import { type AppManifest } from '../../apps/registry'; import { renderIcon } from '../../apps/iconUtils'; import { useAllApps } from '../../hooks/useAllApps'; @@ -88,6 +89,19 @@ export function Launcher({ open, onClose }: Props) { spellCheck={false} maxLength={100} // Security: prevent DoS via extremely long input strings /> + {query && ( + + )} Esc diff --git a/src/components/os/apps/BlogApp.tsx b/src/components/os/apps/BlogApp.tsx index a0c0450..63cb894 100644 --- a/src/components/os/apps/BlogApp.tsx +++ b/src/components/os/apps/BlogApp.tsx @@ -1,4 +1,5 @@ -import { useEffect, useMemo, useState } from 'react'; +import { useEffect, useMemo, useState, useRef } from 'react'; +import { X } from 'lucide-react'; import { relativeTime } from '../../../hooks/useProjects'; type BlogPost = { @@ -25,6 +26,7 @@ export default function BlogApp() { const [payload, setPayload] = useState(null); const [error, setError] = useState(null); const [query, setQuery] = useState(''); + const inputRef = useRef(null); useEffect(() => { let cancelled = false; @@ -71,6 +73,7 @@ export default function BlogApp() {
setQuery(e.target.value)} placeholder="Filter by title, tag, or summary" @@ -78,6 +81,19 @@ export default function BlogApp() { aria-label="Filter posts" maxLength={100} // Security: prevent DoS via extremely long input strings /> + {query && ( + + )}
diff --git a/src/components/os/apps/ProjectsApp.tsx b/src/components/os/apps/ProjectsApp.tsx index 4ad173b..a64191b 100644 --- a/src/components/os/apps/ProjectsApp.tsx +++ b/src/components/os/apps/ProjectsApp.tsx @@ -1,9 +1,11 @@ -import { useMemo, useState } from 'react'; +import { useMemo, useState, useRef } from 'react'; +import { X } from 'lucide-react'; import { useProjects, relativeTime } from '../../../hooks/useProjects'; export default function ProjectsApp() { const { payload, error } = useProjects(); const [query, setQuery] = useState(''); + const inputRef = useRef(null); const filtered = useMemo(() => { if (!payload) return []; @@ -35,6 +37,7 @@ export default function ProjectsApp() {
setQuery(e.target.value)} placeholder="Filter by name, language, or description" @@ -42,6 +45,19 @@ export default function ProjectsApp() { aria-label="Filter projects" maxLength={100} // Security: prevent DoS via extremely long input strings /> + {query && ( + + )}