Added formatLabel prop to XAxis component. When viewing Today (hour
or minute interval), X-axis shows "2:00 PM" instead of "Mar 22".
Tooltip shows time for intra-day, date for multi-day.
Integrated 21st.dev AreaChart component with animated crosshair,
spring-based tooltip, and date ticker. Uses brand orange for the
line/fill with dark-only CSS variables.
Replace binary on/off coloring with 6 opacity levels (transparent,
0.15, 0.35, 0.60, 0.82, solid) based on percentage of max visitors.
Zero-traffic cells are now visually empty. Adds a GitHub-style
"Less → More" legend strip below the grid.
Instead of measuring panel height with unreliable RAF timing, use
CSS bottom positioning when the button is in the lower half of the
viewport. The dropdown grows upward, no measurement needed.
The dropdown position was only clamped on initial render when the panel
was empty. After async notifications loaded and the panel grew taller,
the position was never recalculated. Add an effect that re-clamps when
notifications or loading state changes.
Apply viewport clamping to NotificationCenter dropdown positioning
and bump @ciphera-net/ui to 0.2.15 which clamps AppLauncher and
UserMenu dropdowns the same way.
Bump @ciphera-net/ui to 0.2.14 which portals AppLauncher and UserMenu
dropdowns via createPortal when anchor="right". Apply the same fix to
NotificationCenter. This escapes the sidebar's backdrop-filter
containing block that was clipping all fixed-positioned dropdowns.
- Add relative z-10 to sidebar aside to fix dropdowns (AppSwitcher,
Notifications, UserMenu) rendering behind content area due to
backdrop-blur-xl creating a stacking context
- Move Site Settings from bottom utility section into Infrastructure
nav group where it logically belongs
- Remove ThemeToggle from sidebar (available in user settings)
- Rename Settings to Site Settings for clarity
Use variant='sidebar' for ThemeToggle, NotificationCenter, and
compact UserMenu so they render with the same icon+label layout
as nav items. Fixed dropdown positioning uses fixed to escape
sidebar overflow:hidden.
Use left-aligned rows with fading labels for theme, notifications,
and profile — matching the nav items pattern. Fix app switcher
alignment at top to match logo row.
Move theme toggle, notifications, app switcher, and user profile from
the top header bar into the sidebar. App switcher at the top (scope
switch), utilities at the bottom. Header now only shows on mobile for
the hamburger menu.
With ssr:false, the sidebar rendered nothing in server HTML, so the
content area took full width and page content (site name "Ciphera")
appeared in the sidebar zone. Now the dynamic import has a loading
placeholder — a 64px div with matching border/background that reserves
the sidebar space in the server HTML. Content area never occupies the
sidebar zone. Sidebar replaces the placeholder on client mount.
The sidebar now uses next/dynamic with ssr:false, meaning it renders
NOTHING in the server HTML. No DOM content = no possible flash of
"Ci" or any text during SSR-to-hydration gap. The sidebar only mounts
on the client where localStorage is immediately available, so
collapsed state is correct from the very first render.