Why the merchant sidebar footer rose up (#988) โ
- Status: cause confirmed against computed styles, fixed, and verified live on 2026-08-28.
- Issue: bug(merchant): the sidebar profile footer is not pinned to the bottom of the rail, it rises up under the nav (#988).
- Test plan:
merchant-portal-defects-2026-08-28.
What was the actual cause? โ
Yesterday's M5 fix set flex: 0 1 auto on the merchant nav, which is the property that pins the footer. โ
.sidebarisdisplay: flex; flex-direction: column; height: 100vh..sidebar-footeris an ordinary flex item after the nav, with noposition, nomargin-top: auto, and noflex-grow.- So the ONLY thing holding the footer at the bottom is
.sidebar-nav { flex: 1 1 0% }in the shared sheet: the nav eats every spare pixel and the footer gets pushed down against it. apps/admin/src/merchant/MerchantShell.cssoverrode that with.sidebar--merchant .sidebar-nav { flex: 0 1 auto }, to close survey item M5 ("the merchant sidebar carries roughly 420px of empty nav"). With the nav sized to its content, nothing pushed the footer, so it followed the last nav item up the rail.
The issue's hypothesis was right about the mechanism, and the cause was our own change from the day before. โ
- The issue guessed "the nav does not grow to fill the rail". That is exactly it. What it could not know is that the nav had been deliberately told not to.
What proved it? โ
The computed styles, measured on the operator's own running portal. โ
| Measured at 1440x950 | Before (her stack, http://localhost:3001) | After (this branch, http://localhost:3013) |
|---|---|---|
.sidebar--merchant .sidebar-nav computed flex | 0 / 1 / auto | 1 / 1 / 0% |
| nav height | 324.7px | 692.6px |
| footer bottom edge | 582.1px | 950px |
| rail bottom edge | 950px | 950px |
| footer to rail bottom | 367.9px | 0px |
One rule deleted from the live CSSOM moved the footer 367.9px, with nothing else changed. โ
- The harness walked
document.styleSheets, found.sidebar--merchant .sidebar-nav, and calleddeleteRuleon that single rule. That is byte-for-byte what removing it from the file does. - The footer went from 582.1px to 950px on the same page, in the same session, in the same paint.
- Only two rules in the whole document set
flexon.sidebar-nav: the sharedflex: 1 1 0%and that merchant override. Nothing else was in the chain.
Does the ADMIN rail share the defect? โ
No, and it never did. It reads flex-grow: 1 and a zero gap at every height tested. โ
- The admin rail reports
merchantScoped: false, so.sidebar--merchant .sidebar-navnever matched it. The override was correctly scoped when it was written; the scoping is not what went wrong. - Measured on
/admin/usersat both 1440x950 and 1440x500:footerToRailBottom: 0in every case,flexGrow: 1, nav scrolling internally. - Those numbers are IDENTICAL before and after this change, which is the other half of the control: a merchant-only fix did not leak onto the admin portal.
What changed? โ
The whole MerchantShell.css file went, and its import with it. โ
- Both of its rules existed to serve M5, and both are wrong now. The second one,
.sidebar--merchant .sidebar-footer { margin-top: var(--space-4) }, existed only because the un-pinned footer's border sat flush against "Settings". With the nav filling the rail again there is nothing to separate, and the 24px made the merchant footer differ from the admin one for no reason. - The
sidebar--merchantclass stays on the<aside>: it is the rail's variant marker and it is what let this diagnosis tell the two portals apart in the DOM. - A comment above
<nav className="sidebar-nav">inMerchantShell.jsxnow records that the merchant rail inherits the sharedflex: 1on purpose, so the next reader of M5 does not close it the same way twice.
What does this cost, and what is her call? โ
M5 comes back. Seven nav items do not fill a 950px rail, so there is now 407.9px between "Settings" and the footer. โ
- The survey offered three options for M5 and yesterday's session took the first. Her words this morning pick the second: "the sidebar nav profile which is supposed to be sticky at the bottom". Pinned wins, and the empty space is the consequence.
- The admin rail has the same shape and does not read as broken there, because eleven items plus sub-navs fill the height.
She ruled on 2026-08-28: leave it. โ
- The space stays empty, the same way the admin rail's does. The survey's third option (put the merchant's own context there) is declined for now, so nothing is being built against it.
- The two are one knob and cannot both be had: pinned to the bottom means a gap, and no gap means not pinned, for as long as the merchant nav has seven items. It stops being noticeable the moment that nav grows.
What is related? โ
design-survey.md, item M5, whose first option this reverses.merchant-defect-fixes.md, yesterday's M1 to M5 record. M1 to M4 were re-measured on the fixed build and all four still hold.