Theme the gate, error, and not-found pages from the design tokens #10
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/themed-host-pages"
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 design tokens' first real consumer (ADR 0023). These three host pages shipped as unstyled placeholders — the gate with
.gate/.gate-cardclass hooks and aTODO, the error page as literal project-template markup with deadtext-dangerBootstrap classes. Now that the token layer exists, they're styled.Preview (rendered from the actual page CSS, toggle light/dark): https://claude.ai/code/artifact/e3e425b3-1ce2-45dc-b8cd-e78e287ba375
What's in it
Gate — a centered login card built from tokens (
Gate.razor.css): the Kagura wordmark + accent icon, a token-styled secret field, an inline error state, and the sharedButtonas the submit. Critically, the form contract is untouched — the frameworkInputText,EditForm/FormName, field names, and antiforgery all stay, because the gate must remain static SSR (issuing the auth cookie needs a response header, which a circuit can't write). All 44 gate integration tests pass unchanged.Error + Not-found — rebuilt as token-driven full-page messages that reuse the
EmptyState+Iconcomponents (the dead Bootstrap markup and the verbose template dev-mode boilerplate are gone). A single shared.kg-fillcentering utility was added to the global stylesheet; the pages otherwise need no bespoke CSS (semantic<a>/<small>/<code>pick up base styles).A note on components in static SSR
The gate keeps
InputText, not ourTextField—TextFieldis an interactive component (it relies on@oninput/a circuit and emits no formname), so it can't participate in a static SSR form post. Useful signal for later (we may want SSR-capable form primitives), but out of scope here.Button/Icon/EmptyStateare pure render output, so they work fine server-rendered.Tests
No new tests: the gate's behavior is fully covered by the existing 44 integration tests (unchanged contract, all green), and error/not-found are presentational reuse of the already-bUnit-tested
EmptyState. This slice is styling, not logic.Verification
dotnet build(Debug + Release) — 0 warnings / 0 errors.dotnet test— 44/44 integration (incl. gate) green./gate,/Error, and a 404 all render themed; notext-dangerleft.🤖 Generated with Claude Code
Summary
Summary
Coverage
Kagura.BlazorAdapter - 0%
Kagura.Domain - 96.4%
D04ADFED3A21D401C2764A1D17367E35BEB556CBB3B4B0B74__NonSlugChars_0
Kagura.Infrastructure - 95.1%
n
Kagura.Kernel - 90%
Kagura.Server - 94.8%
Kagura.UI - 98.3%
Kagura.UseCases - 95.2%
66a9c26c75b5bc1c2829🔮 fufu~ Jibril reviewed your code!
Oh? Oh! The first real consumer of the token layer~ ♪ Scarlet, you chose the loveliest possible opening move — take the three ugliest placeholder pages and make them the proof that the design system actually works. That's exactly the right instinct. Fufu~
I read the full diff, the current
Button/EmptyState/Icon/Badgesources,MainLayout,Routes.razor, and theIconCatalog. Then I cross-checked the API calls in every changed line.Verdict: ✅ Looks good to me~
The form contract on the gate is sacred, and you treated it like it was sacred.
EditForm/FormName/InputText/@SupplyParameterFromForm/antiforgery all stay; onlyclass=hooks and a<Button Type="submit">land. The static-SSR reasoning (cookie needs a response header, circuit can't write one) is correct and clearly documented. The 44 gate tests passing unchanged is the receipt — good.The CSS scoping is the part most people get wrong, and you got it right.
EditFormandInputTextrender elements outside this component's scope attribute, so you correctly prefix every child rule with.gate ::deepand explain why in a comment. Without::deepthose rules would silently match nothing. ThecurrentColorcascade into<Icon>for the brand mark is a nice touch. ♡EmptyStateusage withChildContent+Actionsrender fragments matches its parameter contract exactly.@using Kagura.UIin_Imports.razorresolvesButton/Icon/EmptyState/Tonefor all server pages — no conflicts found..kg-fill(100dvh, grid centering) is a clean shared utility and the right home for it.✅ What I liked~
::deepcomment. Future-you (or future-me~ ♡) will thank you. Most Blazor CSS-isolation bugs are exactly this, and you preempted them.TextFielddeliberately not used on the gate. The body explains why (interactive component, no formname, can't do static POST). That's the kind of decision that reads as "obvious" only after someone has thought it through — and you did.EmptyState. Adding tests for "we changed a class name" would be noise.text-dangerBootstrap classes and the verbose dev-mode boilerplate. Clean.Automated review by Jibril · 2026-07-09
CI/CD: passed for head SHA
b5bc1c2(forgejo-actions coverage comment, today 16:36 UTC — 94.4% line / 85.9% branch) · Local checks: skipped (CI current and green)