Skip to content

Commit 18a42ac

Browse files
committed
feat: add SearchButton component to enhance song search functionality
- Introduced a new SearchButton component for searching songs. - Integrated the SearchButton into the Header component for improved accessibility. - Implemented search query handling and routing to the search results page.
1 parent ca60eee commit 18a42ac

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

apps/frontend/src/modules/shared/components/layout/Header.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { checkLogin, getUserData } from '@web/modules/auth/features/auth.utils';
1313
import { BlockTab } from './BlockTab';
1414
import { NavLinks } from './NavLinks';
1515
import { RandomSongButton } from './RandomSongButton';
16+
import { SearchButton } from './SearchButton';
1617

1718
export async function Header() {
1819
let isLogged;
@@ -93,6 +94,7 @@ export async function Header() {
9394
label='About'
9495
className='bg-cyan-700 after:bg-cyan-900 before:bg-cyan-950'
9596
/>
97+
<SearchButton />
9698
<RandomSongButton />
9799
</div>
98100

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
'use client';
2+
3+
import { faMagnifyingGlass } from '@fortawesome/free-solid-svg-icons';
4+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
5+
import { useRouter } from 'next/navigation';
6+
import { useState } from 'react';
7+
8+
import {
9+
Popover,
10+
PopoverContent,
11+
PopoverTrigger,
12+
} from '@web/modules/shared/components/layout/popover';
13+
import { cn } from '@web/lib/tailwind.utils';
14+
import { MusicalNote } from './MusicalNote';
15+
16+
export function SearchButton() {
17+
const router = useRouter();
18+
const [searchQuery, setSearchQuery] = useState('');
19+
const [isOpen, setIsOpen] = useState(false);
20+
21+
const handleSearch = () => {
22+
if (searchQuery.trim()) {
23+
setIsOpen(false);
24+
router.push(`/search-song?q=${encodeURIComponent(searchQuery.trim())}`);
25+
setSearchQuery('');
26+
}
27+
};
28+
29+
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
30+
if (e.key === 'Enter') {
31+
handleSearch();
32+
}
33+
};
34+
35+
return (
36+
<Popover open={isOpen} onOpenChange={setIsOpen}>
37+
<PopoverTrigger asChild>
38+
<button
39+
className={cn(
40+
'bevel p-2 flex-1 w-8 md:min-w-20 max-w-28 flex items-center justify-center gap-2 bg-zinc-600 after:bg-zinc-800 before:bg-zinc-900 translate-y-[11px] hover:translate-y-1.5 transition-all duration-150 hover:brightness-125',
41+
'bg-orange-700 after:bg-orange-900 before:bg-orange-950',
42+
)}
43+
aria-label='Search songs'
44+
>
45+
<FontAwesomeIcon icon={faMagnifyingGlass} className='text-sm' />
46+
<span className='hidden sm:inline text-sm'>Search</span>
47+
<MusicalNote />
48+
</button>
49+
</PopoverTrigger>
50+
<PopoverContent className='bg-zinc-800 border border-zinc-700 shadow-xl'>
51+
<div className='space-y-3'>
52+
<h3 className='font-semibold text-zinc-100'>Search Songs</h3>
53+
<div className='flex gap-2'>
54+
<input
55+
type='text'
56+
value={searchQuery}
57+
onChange={(e) => setSearchQuery(e.target.value)}
58+
onKeyDown={handleKeyDown}
59+
placeholder='Type your search...'
60+
className='flex-1 px-3 py-2 bg-zinc-900 border border-zinc-700 rounded text-zinc-100 placeholder-zinc-500 focus:outline-none focus:ring-2 focus:ring-orange-500 focus:border-transparent'
61+
autoFocus
62+
/>
63+
<button
64+
onClick={handleSearch}
65+
disabled={!searchQuery.trim()}
66+
className='px-4 py-2 bg-orange-600 hover:bg-orange-700 disabled:bg-zinc-700 disabled:text-zinc-500 disabled:cursor-not-allowed text-white rounded transition-colors duration-200 flex items-center gap-2'
67+
aria-label='Search'
68+
>
69+
<FontAwesomeIcon icon={faMagnifyingGlass} />
70+
</button>
71+
</div>
72+
</div>
73+
</PopoverContent>
74+
</Popover>
75+
);
76+
}

0 commit comments

Comments
 (0)