feat(portal-admin): header brand logo + sidebar background covers full column (#148)
## 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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user