Sidebar redesign, dropdown fixes, and soft-delete UI #57

Merged
uz1mani merged 50 commits from staging into main 2026-03-19 00:08:16 +00:00
15 changed files with 1798 additions and 432 deletions
Showing only changes of commit dd76aed157 - Show all commits

View File

@@ -56,17 +56,17 @@ export default function NotificationCenter({ anchor = 'bottom', variant = 'defau
const dropdownRef = useRef<HTMLDivElement>(null)
const panelRef = useRef<HTMLDivElement>(null)
const buttonRef = useRef<HTMLButtonElement>(null)
const [fixedPos, setFixedPos] = useState<{ left: number; top: number } | null>(null)
const [fixedPos, setFixedPos] = useState<{ left: number; top?: number; bottom?: number } | null>(null)
const updatePosition = useCallback(() => {
if (anchor === 'right' && buttonRef.current) {
const rect = buttonRef.current.getBoundingClientRect()
let top = rect.top
if (panelRef.current) {
const maxTop = window.innerHeight - panelRef.current.offsetHeight - 8
top = Math.min(top, Math.max(8, maxTop))
const left = rect.right + 8
if (rect.top > window.innerHeight / 2) {
setFixedPos({ left, bottom: window.innerHeight - rect.bottom })
} else {
setFixedPos({ left, top: rect.top })
}
setFixedPos({ left: rect.right + 8, top })
}
}, [anchor])
@@ -100,17 +100,9 @@ export default function NotificationCenter({ anchor = 'bottom', variant = 'defau
if (open) {
fetchNotifications()
updatePosition()
requestAnimationFrame(() => updatePosition())
}
}, [open, updatePosition])
// Recalculate position after content changes (notifications load, loading state)
useEffect(() => {
if (open && anchor === 'right') {
requestAnimationFrame(() => updatePosition())
}
}, [notifications, loading, open, anchor, updatePosition])
// * Poll unread count in background (when authenticated)
useEffect(() => {
fetchUnreadCount()
@@ -214,10 +206,10 @@ export default function NotificationCenter({ anchor = 'bottom', variant = 'defau
aria-label="Notifications"
className={`bg-white dark:bg-neutral-900 border border-neutral-200 dark:border-neutral-700 rounded-xl shadow-xl overflow-hidden z-[100] ${
anchor === 'right'
? 'fixed w-96 origin-top-left'
? `fixed w-96 ${fixedPos?.bottom !== undefined ? 'origin-bottom-left' : 'origin-top-left'}`
: 'fixed left-4 right-4 top-16 sm:absolute sm:left-auto sm:right-0 sm:top-full sm:mt-2 sm:w-96'
}`}
style={anchor === 'right' && fixedPos ? { left: fixedPos.left, top: fixedPos.top } : undefined}
style={anchor === 'right' && fixedPos ? { left: fixedPos.left, top: fixedPos.top, bottom: fixedPos.bottom } : undefined}
>
<div className="flex items-center justify-between px-4 py-3 border-b border-neutral-200 dark:border-neutral-700">
<h3 className="font-semibold text-neutral-900 dark:text-white">Notifications</h3>