Commit Graph

3 Commits

Author SHA1 Message Date
Jakob Wennberg a3326a0296 perf(nav): hover-intent prefetch for the dashboard nav + 30 s client router cache (#1943)
* perf(nav): prefetch dashboard routes on hover intent, not on viewport

DashboardNav renders ~45 links, all dynamic routes with a loading
boundary, so Next prefetched every one of them as soon as the nav mounted.
Each prefetch is a full request through the auth proxy (Supabase Auth
round trip, active-company RPC, MFA check) whose only payload is the
shared loading skeleton; prod logs showed 1,000 to 1,300 such hits per nav
route per day.

NavLink wraps next/link with prefetch={false} and an explicit
router.prefetch on mouseenter/focus/touchstart (Link's own hover prefetch
is disabled together with viewport prefetch, so the warm-up must be
explicit). The link to the current route and non-routes are skipped
(shouldWarmNavRoute, tested). A source-shape test pins that DashboardNav
has no bare next/link left.

Cost: an un-hovered click shows the route's loading skeleton ~50-100 ms
later than before; the skeleton is all a dynamic prefetch ever carried.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* perf(router): keep dynamic routes in the client router cache for 30 s

experimental.staleTimes.dynamic was 0: every back/forward or repeated nav
click re-requested the RSC payload through the auth proxy. 30 s covers the
click-around pattern the customer described while the 16 router.refresh()
sites after mutations keep the pages that must not go stale fresh.
Separate commit so it can be dropped on its own if stale numbers are
reported.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 14:01:37 +02:00
Jakob Wennberg c5b7716f74 revert(nav): keep company switching in the bottom user block only (#1775)
Reverts #1765, which mounted the CompanySwitcher at the top of the
expanded desktop sidebar. Seen live, the top slot is the wrong home for
it: the sidebar head stays brand + collapse control, and the nav starts
directly below it. Switching keeps its single home in the bottom user
block (UserMenu flyout), which is also what the collapsed 64px rail and
every existing muscle memory already use. The mobile sheet's switcher is
untouched.

The logo title tooltip and the source-shape regression test go back with
it: both shipped inside the same commit and both exist only to pin the
top placement.

DECISIONS.md records that #1664's "one-click from the top" framing is
declined rather than merely unimplemented, so the issue does not get
re-opened into the same PR.

Reverts 72181e49bd


Claude-Session: https://claude.ai/code/session_01LcwpT82qwHhtTAFeU47Ay1

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-20 22:15:03 +02:00
Mattsson 72181e49bd feat(nav): one-click company switching at the top of the sidebar (#1664) (#1765)
Company switching had moved into a nested flyout in the bottom-of-sidebar
user popover: avatar, then Byt foretag, then the company. Three clicks per
switch is painful for consultants who hop between companies constantly.

Mount the existing one-click CompanySwitcher (already live in the mobile
sheet, same performCompanySwitch path) at the top of the expanded desktop
sidebar, pinned above the nav scroll container and outside the
data-ph-unmask navs so the company name stays masked in replays. The
user-menu flyout remains as the secondary path; the collapsed 64px rail
keeps switching via the UserMenu avatar. Also label the brand logo link
with a native title tooltip so it is not an unlabeled square.

Pinned by a source-shape regression test, the same pattern as the
JournalEntryList copy affordance: the repo does not render components in
tests.

Closes #1664

Signed-off-by: Emil <emilmattsson14@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-20 21:30:57 +02:00