feat(portal-admin): header brand logo + sidebar background covers full column (#148)
CI / scan (push) Successful in 2m0s
CI / commits (push) Has been skipped
CI / check (push) Successful in 2m35s
CI / a11y (push) Successful in 2m4s
CI / perf (push) Successful in 3m44s

## 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).
- [ ] 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.

---------

Co-authored-by: Julien Gautier <julien.gautier@apf.asso.fr>
Reviewed-on: #148
This commit was merged in pull request #148.
This commit is contained in:
2026-05-15 13:59:16 +02:00
parent 6120471b66
commit e3e7800ecb
5 changed files with 42 additions and 4 deletions
@@ -1,5 +1,13 @@
<header class="admin-header">
<a class="brand" routerLink="/">
<img
src="logos/apf-logo.svg"
alt=""
aria-hidden="true"
width="28"
height="28"
class="brand-logo"
/>
<span class="brand-wordmark">APF Portal</span>
<span class="brand-badge">Admin</span>
</a>
@@ -30,6 +30,13 @@
}
}
.brand-logo {
display: block;
flex-shrink: 0;
height: 1.75rem;
width: 1.75rem;
}
// "Admin" pill — distinct color from the wordmark so it reads as a
// status badge even in dense headers. Keeps the surface
// immediately recognisable per ADR-0020 §"Discoverability for
@@ -1,18 +1,28 @@
.admin-sidebar {
// The host element owns the sidebar envelope (width + chrome) so
// the gray background + right border cover the full column, not
// just the rail of links. The inner <nav> handles the scrolling
// list inside that envelope.
:host {
display: flex;
flex-direction: column;
width: 16rem;
flex: 0 0 16rem;
background-color: #f3f4f6;
border-right: 1px solid #e5e7eb;
padding: 0.75rem 0;
overflow-y: auto;
}
:host-context(.dark) .admin-sidebar {
:host-context(.dark) {
background-color: #0f172a;
border-right-color: #1f2937;
color: #e5e7eb;
}
.admin-sidebar {
flex: 1 1 auto;
padding: 0.75rem 0;
overflow-y: auto;
}
.nav-list {
list-style: none;
margin: 0;