Skip to content

feat: sidebar structure — header-pinned collapse, rail parity, identity footer - #42

Merged
ditto-m[bot] merged 2 commits into
mainfrom
sidebar-1133
Aug 1, 2026
Merged

feat: sidebar structure — header-pinned collapse, rail parity, identity footer#42
ditto-m[bot] merged 2 commits into
mainfrom
sidebar-1133

Conversation

@ditto-m

@ditto-m ditto-m Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Sidebar structure pass against the reference UI (planning#1133): the desktop
collapse affordance, rail parity, the identity footer, and where the
notification bell/theme toggle live all move. Presentation + placement, not
new state — existing props/behavior are unchanged, new capability arrives
via new optional props.

  • Collapse control — the rail-collapse toggle moves from a separate row
    floating below the brand into the sidebar header, pinned to the trailing
    edge and vertically aligned with the app name/icon. Collapsed rail: the
    app name/icon hide and the toggle becomes the sole visible header
    control — the top item of the rail.
  • Rail parity — section captions (secondarySections captions,
    secondaryCaption) collapse to a subtle 1px divider instead of vanishing
    outright (a second-or-later secondarySections group otherwise has no
    border of its own and loses all separation once collapsed). Expanded
    captions get a quieter treatment (--etu-fw-medium, more space above).
  • Identity footer<UserMenu variant="full"> is the new canonical
    <Sidebar footer> control: a single full-width avatar + name + email
    row opening the same popover. New themeToggle={{ appKey }} adds a
    light/dark row to the popover (backed by getTheme/setTheme); new
    badges adds role/permission pills under the name.
  • Bell and theme placement — the theme toggle moved out of the sidebar
    footer into the UserMenu popover. <NotificationBell variant="row"> is
    a new full-width sidebar-row presentation, mounted via a new
    SidebarItem.render escape hatch; it reuses .etu-sidebar-item* classes
    so it inherits rail-collapse (icon-only, badge → dot) for free. Its
    desktop popover renders through a portal to <body> so it isn't clipped
    by the sidebar's own overflow: auto at any rail width, including the
    64px collapsed column. New SidebarItem.badge gives any plain nav row a
    trailing indicator that degrades to a dot on the collapsed rail. On
    mobile (sidebar hidden < 720px) the bell mounts in
    <NavigationBar trailing> instead. NotificationBell itself is not
    deprecated — only the footer-icon-cluster placement is; nothing in the
    showcase mounts it there.
  • Showcase dogfoods the new structure end-to-end (identity footer, bell as
    a nav row + mobile trailing edge, theme row inside the popover) and adds
    a notification-bell registry entry (pre-existing gap — the component
    had no registry entry before this PR).

Full behavioral-change list: CHANGELOG.md 0.43.0, "Behavioral notes for 0.43".

Test plan

  • pnpm typecheck && pnpm build && pnpm test
  • pnpm --filter @etamong-playground/ui-showcase build
  • CI=1 pnpm e2e — 13/13 passing, including two new specs (mobile bell
    on NavigationBar trailing, and rail-collapsed bell badge-dot +
    portaled popover)
  • Manually screenshotted the built showcase (vite preview) at
    1280×900 expanded, 1280×900 collapsed/rail, and 390×844 mobile, in
    both themes; iterated once after catching that the pre-existing
    "notifications" (toast/dialog) nav item and the new bell row both
    used a bell glyph and read as a duplicate destination — the toast
    page now uses a distinct message-square icon

Closes etamong-playground/planning#1133

ditto-m Bot added 2 commits August 1, 2026 14:49
…ty footer

Bump 0.42.1 -> 0.43.0.

- Collapse toggle moves from a floating row below the brand into the
  sidebar header, pinned to the trailing edge; collapsed rail keeps it as
  the sole top-of-rail control.
- Section captions collapse to a subtle divider instead of vanishing, and
  drop to a quieter font-weight/spacing treatment when expanded.
- UserMenu variant="full" is the canonical identity footer (avatar + name +
  email), with new themeToggle and badges props — the theme toggle now
  lives inside the popover instead of a loose footer icon.
- NotificationBell gets a variant="row" sidebar presentation (mounted via
  the new SidebarItem.render escape hatch) with a portal-based popover so
  it isn't clipped by the sidebar's own overflow, plus SidebarItem.badge
  for unread counts that degrade to a dot on the collapsed rail. Bell
  convention: nav row on desktop/rail, NavigationBar trailing on mobile —
  never the footer, never paired with the theme toggle.
- Showcase dogfoods all of the above; e2e updated for the moved theme
  toggle and extended to cover the mobile bell + rail-collapsed badge dot
  and portaled popover.

Closes etamong-playground/planning#1133
…nu dropdown, unified popover positioning

Applies the consolidated review findings for planning#1133 (ui#42):

- SidebarItem badge is now folded into the row's aria-label instead of
  being silently dropped by the unconditional aria-label override; the
  visible pill is aria-hidden once folded in.
- UserMenu's dropdown now portals to <body> with viewport-fixed
  coordinates, like NotificationBell's row popover, so it isn't clipped
  by Sidebar's overflow-y: auto as the variant="full" footer control.
- NotificationBell + UserMenu popover positioning is unified into a
  shared usePopoverPosition hook: one useLayoutEffect pass (not two
  effects racing on a stale closure), both axes clamped to the viewport
  against the panel's real measured size, recomputed on scroll too.
- NotificationBell row variant no longer opens a mobile sheet (and body
  scroll lock) if left open while the viewport crosses below 720px —
  the sidebar is CSS-hidden there, not unmounted.
- NotificationBell row variant always has an accessible name (including
  at 0 unread) and carries the same title tooltip Item() sets.
- Collapsed-rail captions are aria-hidden; a caption-turned-divider no
  longer doubles up with the first secondary section's own border.
- Rail collapse toggle restored to 40x40 (was shrunk to 32x32).
- Dev-only warning when SidebarItem.render is combined with fields it
  ignores.
- Docs: themeToggle adoption hazard (porygon/webui dual-control
  conflict), caption-collapse behavioral note, dead label dropped from
  the render() example.
@ditto-m
ditto-m Bot merged commit 22b1c45 into main Aug 1, 2026
2 checks passed
@ditto-m
ditto-m Bot deleted the sidebar-1133 branch August 1, 2026 06:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants