Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .jules/palette.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 2024-05-24 - Semantic HTML and ARIA Labels for Icon Buttons
**Learning:** Found a pattern in this app's custom UI components (like `Navbar.tsx`) where interactive icon-only elements were either missing `aria-label`s or built using non-semantic `div` elements instead of `<button>`, causing poor screen reader experiences and missing keyboard focus outlines (`focus-visible`).
**Action:** Always ensure interactive components like triggers and icon buttons use semantic `<button>` tags, accept and set `aria-label` (and `title` for hover tooltips), and include `focus-visible:outline-none focus-visible:ring-2` to guarantee keyboard accessibility.
17 changes: 11 additions & 6 deletions src/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,18 @@ export default function Navbar() {
</div>

<div className="flex items-center gap-8">
<div className="hidden md:flex items-center gap-3 px-4 py-2 rounded-full bg-white/5 border border-white/5 text-slate-400 hover:text-white hover:bg-white/10 transition-all cursor-pointer group">
<button
aria-label="Search Commands"
className="hidden md:flex items-center gap-3 px-4 py-2 rounded-full bg-white/5 border border-white/5 text-slate-400 hover:text-white hover:bg-white/10 transition-all cursor-pointer group focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500"
>
<Search className="w-4 h-4 group-hover:scale-110 transition-transform" />
<span className="text-xs font-bold tracking-wider">SEARCH COMMANDS</span>
<span className="text-[10px] bg-white/10 px-1.5 py-0.5 rounded border border-white/10 font-mono">⌘K</span>
</div>
</button>

<div className="flex items-center gap-4">
<IconButton icon={<Bell className="w-5 h-5" />} />
<IconButton icon={<User className="w-5 h-5" />} />
<IconButton icon={<Bell className="w-5 h-5" />} ariaLabel="Notifications" />
<IconButton icon={<User className="w-5 h-5" />} ariaLabel="User Profile" />
<div className="h-8 w-[1px] bg-white/10 mx-2" />
<div className="flex items-center gap-3 px-4 py-2 rounded-xl bg-emerald-500/10 border border-emerald-500/20 group cursor-pointer">
<div className="w-2 h-2 rounded-full bg-emerald-500 animate-pulse shadow-[0_0_10px_rgba(16,185,129,0.5)]" />
Expand All @@ -62,12 +65,14 @@ function NavLink({ href, label }: { href: string, label: string }) {
);
}

function IconButton({ icon }: { icon: React.ReactNode }) {
function IconButton({ icon, ariaLabel }: { icon: React.ReactNode, ariaLabel: string }) {
return (
<motion.button
whileHover={{ scale: 1.1, y: -2 }}
whileTap={{ scale: 0.9 }}
className="p-2.5 rounded-xl bg-white/5 border border-white/5 text-slate-400 hover:text-white hover:bg-white/10 transition-all"
aria-label={ariaLabel}
title={ariaLabel}
className="p-2.5 rounded-xl bg-white/5 border border-white/5 text-slate-400 hover:text-white hover:bg-white/10 transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500"
>
{icon}
</motion.button>
Expand Down