feat(portal-admin): header brand logo + sidebar background covers full column #148

Merged
julien merged 1 commits from feat/portal-admin-header-logo-and-sidebar-envelope into main 2026-05-15 13:59:17 +02:00
Owner

Summary

Two small portal-admin polish items so the admin shell stops looking like a scaffold:

  1. APF mark in the header, before the APF Portal wordmark — same lock-up portal-shell already ships.
  2. Sidebar gray background + right border now cover the entire column, not just the rail of nav links.

What lands

Header — brand logo

apps/portal-admin/src/app/components/header/header.html<img> slipped in before the wordmark inside the .brand flex row:

<img src="logos/apf-logo.svg" alt="" aria-hidden="true" width="28" height="28" class="brand-logo" />

The image is decorative: alt="" + aria-hidden="true". The accessible name of the brand link is already carried by APF Portal + the Admin badge — adding a non-empty alt here would just produce noise for screen-reader users (WCAG 1.1.1 / Decorative images).

Sized at 28×28 (1.75rem) to keep the lock-up proportionate to the admin header's compact 3.5rem height — portal-shell uses 36×36 in a 4rem header. The new .brand-logo SCSS rule pins display: block; flex-shrink: 0; height/width: 1.75rem so the SVG can't be squashed by other header content.

Sidebar — full-column chrome

apps/portal-admin/src/app/components/sidebar/sidebar.scss — the gray background and right border move from the inner <nav class="admin-sidebar"> to :host (i.e. the <app-admin-sidebar> element itself). Result: the chrome covers the whole flex column, not just the area the link list occupies.

Three things had to move together for the visual to land:

  • background-color + border-right — what the user asked for.
  • width: 16rem + flex: 0 0 16rem — the host is the direct flex child of .shell-body; sizing must live on the flex item, not on a grandchild.
  • display: flex; flex-direction: column — Angular custom elements default to display: inline. Without an explicit display, background and border don't render on the host, regardless of the parent's align-items: stretch.

The inner <nav> now keeps just its content concerns: padding for the list breathing room, overflow-y: auto for the scroll, and flex: 1 1 auto so it grows to fill the host envelope.

Dark-mode variants follow the same move — :host-context(.dark) swaps the host's background + border-color directly.

Assets

apps/portal-admin/public/logos/{apf-logo.svg, apf-portal.svg} mirror the portal-shell public/logos/ layout; Angular's build pipeline picks them up at /logos/* per the standard static-asset convention.

Test plan

  • pnpm nx test portal-admin45 specs pass, unchanged. Header spec asserts on .brand-wordmark + .brand-badge (untouched); sidebar spec asserts on the <nav> landmark + RouterLinks (also untouched).
  • pnpm nx lint portal-admin — clean.
  • pnpm nx build portal-admin — clean; lazy chunks unchanged (audit 4.35 KB gzip, users 3.76 KB gzip).
  • Visual smoke in dev — sign in, confirm the APF mark renders to the left of the wordmark, then navigate to /audit and /users and confirm the gray background + right border extend the full height of the sidebar column.
## Summary Two small portal-admin polish items so the admin shell stops looking like a scaffold: 1. **APF mark in the header**, before the `APF Portal` wordmark — same lock-up portal-shell already ships. 2. **Sidebar gray background + right border now cover the entire column**, not just the rail of nav links. ## What lands ### Header — brand logo [`apps/portal-admin/src/app/components/header/header.html`](apps/portal-admin/src/app/components/header/header.html) — `<img>` slipped in before the wordmark inside the `.brand` flex row: ```html <img src="logos/apf-logo.svg" alt="" aria-hidden="true" width="28" height="28" class="brand-logo" /> ``` The image is **decorative**: `alt=""` + `aria-hidden="true"`. The accessible name of the brand link is already carried by `APF Portal` + the `Admin` badge — adding a non-empty `alt` here would just produce noise for screen-reader users (WCAG 1.1.1 / Decorative images). Sized at 28×28 (1.75rem) to keep the lock-up proportionate to the admin header's compact 3.5rem height — portal-shell uses 36×36 in a 4rem header. The new `.brand-logo` SCSS rule pins `display: block; flex-shrink: 0; height/width: 1.75rem` so the SVG can't be squashed by other header content. ### Sidebar — full-column chrome [`apps/portal-admin/src/app/components/sidebar/sidebar.scss`](apps/portal-admin/src/app/components/sidebar/sidebar.scss) — the gray background and right border move from the inner `<nav class="admin-sidebar">` to `:host` (i.e. the `<app-admin-sidebar>` element itself). Result: the chrome covers the whole flex column, not just the area the link list occupies. Three things had to move together for the visual to land: - **`background-color` + `border-right`** — what the user asked for. - **`width: 16rem` + `flex: 0 0 16rem`** — the host is the direct flex child of `.shell-body`; sizing must live on the flex item, not on a grandchild. - **`display: flex; flex-direction: column`** — Angular custom elements default to `display: inline`. Without an explicit display, background and border don't render on the host, regardless of the parent's `align-items: stretch`. The inner `<nav>` now keeps just its content concerns: `padding` for the list breathing room, `overflow-y: auto` for the scroll, and `flex: 1 1 auto` so it grows to fill the host envelope. Dark-mode variants follow the same move — `:host-context(.dark)` swaps the host's background + border-color directly. ### Assets `apps/portal-admin/public/logos/{apf-logo.svg, apf-portal.svg}` mirror the portal-shell `public/logos/` layout; Angular's build pipeline picks them up at `/logos/*` per the standard static-asset convention. ## Test plan - [x] `pnpm nx test portal-admin` — **45 specs pass**, unchanged. Header spec asserts on `.brand-wordmark` + `.brand-badge` (untouched); sidebar spec asserts on the `<nav>` landmark + RouterLinks (also untouched). - [x] `pnpm nx lint portal-admin` — clean. - [x] `pnpm nx build portal-admin` — clean; lazy chunks unchanged (`audit` 4.35 KB gzip, `users` 3.76 KB gzip). - [x] Visual smoke in dev — sign in, confirm the APF mark renders to the left of the wordmark, then navigate to `/audit` and `/users` and confirm the gray background + right border extend the full height of the sidebar column.
julien added 1 commit 2026-05-15 13:58:48 +02:00
feat(portal-admin): header brand logo + sidebar background covers full column
CI / scan (pull_request) Successful in 2m40s
CI / commits (pull_request) Successful in 2m40s
CI / check (pull_request) Successful in 3m58s
CI / a11y (pull_request) Successful in 1m34s
CI / perf (pull_request) Successful in 5m9s
7a62ac69b0
* Drop the APF mark before the wordmark in the admin header, mirroring
  the portal-shell brand zone shape. 28px square keeps the lock-up
  proportionate to the admin header's compact 3.5rem height (vs
  portal-shell's 4rem). The image is decorative (`alt=""` +
  `aria-hidden="true"`) — the wordmark + Admin badge already carry
  the accessible name.

* Move the gray background + right border from the inner `<nav>` to
  the `:host` of `app-admin-sidebar` so the chrome covers the whole
  flex column, not just the link rail. Width/flex sizing and a
  `display: flex` go with it (custom elements default to `display:
  inline` so `:host` needs an explicit display for the background to
  render). The inner `<nav>` keeps padding + scroll and now grows with
  `flex: 1 1 auto`.

* Add the shared APF logo assets under apps/portal-admin/public/logos/
  so the build pipeline picks them up at `/logos/*` per the Angular
  static-asset convention.
julien merged commit e3e7800ecb into main 2026-05-15 13:59:17 +02:00
julien deleted branch feat/portal-admin-header-logo-and-sidebar-envelope 2026-05-15 13:59:19 +02:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: julien/apf_portal#148