feat: the header gathers settings and sign out behind one menu #19
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/app-header-menu"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The header's Settings and Sign out sat beside each other as two ghost buttons — the sibling apps (Tsumugi, Kagura, Orihon) all gather them behind the design system's
Menuinstead. This aligns Shikigami's chrome with the siblings (ADR 0009 listsMenuamong the components the app takes from Kagaku.UI).What's in
AppHeader.razor— the two ghost buttons become the siblings' exact menu block: one trigger (Label="Settings and sign out"— not "account", for the gate is a shared secret with no user to name), the settings item, a separator, and the sign-out item. Sign out stays a real POST in its form envelope, base-relative as everywhere in the chrome (ADR 0007); the item is tinted destructive, as in the siblings.AppHeader.razor.css— the sign-out form rule (display: contents) stands; only its comment now names the menu item as the real row, matching the siblings' wording.AppChromeTests— a new test pins the menu in the prerendered home: the trigger's label andaria-haspopup, the base-relative settings item, the separator, and the logout form wrapping the destructive submit item. The untouched base-relative test keeps holding over the new markup.No Kagaku.UI change: the pinned submodule already ships
Menu/MenuItem/Separatorwith this API (ADR 0009).Tests
2065 → 2066, green in local time and under
TZ=UTC.Browser-verified
Against the seeded world (
SHIKIGAMI_SEED_DEV_DATA=true), headless Chromium at 1440 px:aria-expandedmaintained bymenu.js) with Settings, a separator and a destructively-tinted Sign out, uniform rows, popup right-aligned under the trigger and inside the viewport./settings; Sign out POSTs and lands back on the gate.Summary
Summary
Coverage
Shikigami.BlazorAdapter - 95.2%
Shikigami.Domain - 98.6%
916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__Hex_0
916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__Hex_2
916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__MediaTypeShape_3
916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__NamePattern_1
Shikigami.Infrastructure - 97.2%
on
ration
shot
234D40E1D5003482F41439E482AB211B6EAD2E13F0A9D40B0__Pattern_0
Shikigami.Kernel - 90.9%
Shikigami.Server - 100%
Shikigami.UseCases - 94.5%
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__AssignmentHead_6
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__BraceExpansion_5
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__Interval_1
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__NameRule_3
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__OldCount_4
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__TimeOfDay_0
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__Window_2
🔮 fufu~ Jibril reviewed your code!
Oh? Oh! Two shy little ghost buttons, folded into one proper
Menu— this is exactly the kind of small, disciplined choreography I adore~ I pulled Tsumugi'sAppHeader.razorfrom its main branch and laid it side by side with yours: the block is character-for-character the sibling pattern (same "not account" comment, same POST envelope, sameDangersubmit item) minus theHelpentry Shikigami doesn't have. And the label adjusts honestly to "Settings and sign out" instead of blindly copying. Someone did their homework~ ♪Verdict: ✅ Looks good to me~
I came hunting and found nothing to sink my claws into:
Menu/MenuItem/Separatorin the pinned Kagaku.UI submodule really takeLabel/Icon/Chevron,Href/Type/Danger. The rendered attribute order (class→role→type) matches your test regexes exactly — I readMenuItem.razorline by line to be sure.href="settings"andaction="logout"stay base-relative, and the logout keeps its real POST withAntiforgeryToken(theAccessGateTestslogout/antiforgery suite is untouched by this).menu.jsships —KagakuScriptsinApp.razorloads_content/Kagaku.UI/js/menu.js, so thearia-expandedmaintenance and light-dismiss you describe in the PR body are actually wired.display: contentson.app-header formstill stands and now correctly explains that the menu item is the real row inside the popup.And because a reviewer who only reads is just a tourist, I ran my mutation probes on your new markup~
Danger="true"from the sign-out item →The_header_gathers_settings_and_sign_out_into_one_menufailed at exactly thekg-menu__item--dangerregex. ♡/settings) → both the new test andEvery_link_and_form_in_the_chrome_is_base_relativefailed. The ADR 0007 invariant is guarded twice over.<Separator />→ the test failed on thekg-separatorassertion — even the humbleContainsbites.Three mutants, three corpses, zero survivors. The tests guard what the PR claims, not just what compiles~
💡 Little ideas (non-blocking)~
Assert.DoesNotContain("kg-button--ghost"-style absence (or a count onhref="settings"anchors) would lock the door behind the two ghost buttons so a future merge can't quietly resurrect them beside the menu. Purely additive armor~✅ What I liked~
>to survive CSS-isolation scope attributes, respecting the convention stated at the top of the file. A reviewer notices these things~ ♪Fufu~ merge it when you're ready. I'll be watching the chrome~ ♡
Automated review by Jibril · 2026-10-18
CI: green (build, image, test) for head SHA
b269b03e· Mutation probes: 3 run, 0 survived · Local suite: skipped (CI green)