fix(nav): numeric inbox badge with active-state contrast
Show the unread count as a number on the collapsed nav rail (not just a dot), and invert the badge colours on the active row so it isn't an accent-on-accent red blob; centre the number on the circle.
This commit is contained in:
parent
ed4194a8d3
commit
00d07b9153
1 changed files with 40 additions and 24 deletions
|
|
@ -147,31 +147,47 @@ export default function NavSidebar({
|
||||||
"w-full flex items-center gap-3 rounded-lg px-2.5 py-2 text-sm transition";
|
"w-full flex items-center gap-3 rounded-lg px-2.5 py-2 text-sm transition";
|
||||||
const name = me.display_name ?? me.email.split("@")[0];
|
const name = me.display_name ?? me.email.split("@")[0];
|
||||||
|
|
||||||
const renderItem = ({ page: p, icon: Icon, label, badge }: NavItem) => (
|
const renderItem = ({ page: p, icon: Icon, label, badge }: NavItem) => {
|
||||||
<button
|
const active = page === p;
|
||||||
key={p}
|
// On the active row the background is the accent colour, so a same-accent badge would be
|
||||||
onClick={() => setPage(p)}
|
// red-on-red. Invert it there (light pill, accent-coloured number) for clean contrast.
|
||||||
title={collapsed ? label : undefined}
|
const badgeColor = active ? "bg-accent-fg text-accent" : "bg-accent text-accent-fg";
|
||||||
aria-current={page === p ? "page" : undefined}
|
const show = !!badge && badge > 0;
|
||||||
className={`${rowBase} ${collapsed ? "justify-center px-0" : ""} relative ${
|
return (
|
||||||
page === p ? "bg-accent text-accent-fg" : "text-muted hover:text-fg hover:bg-card"
|
<button
|
||||||
}`}
|
key={p}
|
||||||
>
|
onClick={() => setPage(p)}
|
||||||
<span className="relative shrink-0">
|
title={collapsed ? label : undefined}
|
||||||
<Icon className="w-[18px] h-[18px]" />
|
aria-current={active ? "page" : undefined}
|
||||||
{/* Collapsed rail: a small dot on the icon; expanded: a numeric pill at the row end. */}
|
className={`${rowBase} ${collapsed ? "justify-center px-0" : ""} relative ${
|
||||||
{!!badge && badge > 0 && collapsed && (
|
active ? "bg-accent text-accent-fg" : "text-muted hover:text-fg hover:bg-card"
|
||||||
<span className="absolute -top-1 -right-1 w-2 h-2 rounded-full bg-accent ring-2 ring-bg" />
|
}`}
|
||||||
)}
|
>
|
||||||
</span>
|
<span className="relative shrink-0">
|
||||||
{!collapsed && <span className="truncate">{label}</span>}
|
<Icon className="w-[18px] h-[18px]" />
|
||||||
{!!badge && badge > 0 && !collapsed && (
|
{/* Collapsed rail: a numeric badge centred on a circle at the icon corner; the ring
|
||||||
<span className="ml-auto min-w-[18px] h-[18px] px-1 rounded-full bg-accent text-accent-fg text-[11px] font-semibold inline-flex items-center justify-center tabular-nums">
|
matches the row background so it reads cleanly whether the row is active or not. */}
|
||||||
{badge > 99 ? "99+" : badge}
|
{show && collapsed && (
|
||||||
|
<span
|
||||||
|
className={`absolute -top-2 -right-2 min-w-[16px] h-4 px-1 rounded-full text-[10px] font-bold leading-none grid place-items-center ring-2 ${badgeColor} ${
|
||||||
|
active ? "ring-accent" : "ring-bg"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{badge > 9 ? "9+" : badge}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
)}
|
{!collapsed && <span className="truncate">{label}</span>}
|
||||||
</button>
|
{show && !collapsed && (
|
||||||
);
|
<span
|
||||||
|
className={`ml-auto min-w-[18px] h-[18px] px-1.5 rounded-full text-[11px] font-semibold leading-none inline-flex items-center justify-center tabular-nums ${badgeColor}`}
|
||||||
|
>
|
||||||
|
{badge > 99 ? "99+" : badge}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav
|
<nav
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue