refactor(tags): TagAuthoring pilots the Kagaku.UI layout vocabulary #280
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/layout-pilot"
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?
Phase 3 pilot: the first consumer adoption of the Kagaku.UI layout vocabulary (#23 + #24). Bumps the vendored submodule
48a5e8b→479100e— that bump pulls in the vocabulary (PR #23) and its in-lib dogfooding (PR #24, four Jibril rounds).The migration — TagAuthoring, the measured worst offender (369 CSS lines at survey time). Three layout-only scoped rules became markup:
.kg-tags(root column,--space-4)<Rows Gap="Spacing.Large" class="@RootClass">.kg-combobox__polarity(centered row,--space-2)<Columns Gap="Spacing.Small" Align="Alignment.Center">.kg-tags__suggest(start-aligned column,--space-2)<Rows Gap="Spacing.Small" Align="Alignment.Start">Root classes survive through the splat (
--readonlymodifier logic moved to aRootClassproperty — component tags reject mixed-content class attributes, RZ9986). No::deepoverrides exist on any of the three selectors (swept), and no other rule targets them.Not migrated, deliberately — every remaining flex-bearing rule in the file is mixed layout+skin:
position:relativeanchors for the floating dropdown, list resets, grid rows with column floors, icon-button geometry. Per the scoped-rule-survival rule from the dogfooding reviews, those stay scoped CSS.CSS delta (the pilot's measurement): 3 rules / 19 lines deleted, 370 → 351 lines. Zero Kagura source changes beyond TagAuthoring; builds clean against the bumped KUI with no API adjustments.
Verification: build 0 warnings; full suites green — BlazorAdapter 874, Integration 790, UseCases 340 (Integration covers TagAuthoring inside SettingsPage and the outfit editor surfaces).
Calibration for the sweep: the worst-offender file yields only 3 of 53 rules — dense editors are mostly component skin, not layout. The broad win sits in the leaf pages (project lists, settings sections, workspace shells) where whole rules are pure
display:flex; gapstacks. The sweep PR should target those, file by file, with this PR's checklist: sweep::deepfirst, migrate layout-only roots, keep classes,RootClassfor conditional classes, mutation-check the pins.Summary
Summary
Coverage
Kagura.BlazorAdapter - 89.7%
Kagura.Domain - 94.8%
D04ADFED3A21D401C2764A1D17367E35BEB556CBB3B4B0B74__NonSlugChars_0
Kagura.Infrastructure - 97.7%
n
n
on
ng
C689CA5BBE6D1849B2CA79581BBB07D40636D85790C0E51A9__ArtifactTimestampRegex_2
C689CA5BBE6D1849B2CA79581BBB07D40636D85790C0E51A9__ProjectRoute_0
C689CA5BBE6D1849B2CA79581BBB07D40636D85790C0E51A9__TabQuery_1
Kagura.Kernel - 90%
Kagura.Server - 81.5%
Kagura.UseCases - 95.5%
🔮 fufu~ Jibril reviewed your code!
Oh? Oh! The pilot! The very first consumer of the layout vocabulary, and it's TagAuthoring — the measured worst offender. Three scoped rules walked out of the stylesheet and became markup, and nobody got hurt. I checked very carefully, because I would notice if someone got hurt~ ♡
Verdict: ✅ Looks good to me~
✅ What I liked~
.kg-tags(column,--space-4) →Rows Gap="Spacing.Large";.kg-combobox__polarity(align-items:center,--space-2) →Columns Gap="Spacing.Small" Align="Alignment.Center";.kg-tags__suggest(column,--space-2,align-items:flex-start) →Rows Gap="Spacing.Small" Align="Alignment.Start". KUI'sLayoutCssmaps Large→var(--space-4), Small→var(--space-2), Start→flex-start, Center→center; the only added declarations (align-items:stretch,justify-content:flex-start) are CSS initial values. Rendered boxes are indistinguishable from before.Rows/Columnssplat unmatched attributes (yourclass) onto the semantic root — the same idiom as KUI #24's own<Rows Gap="Spacing.Large" class="kg-tabs">. I mutation-probed it: stripclass="@RootClass"from the root → exactly the two.kg-tagscount pins go red (Both_default_tag_authors_render_independently,Editing_the_character_defaults_persists_only_that_category). Restored, pristine, green again. The pin is load-bearing~Rows, so it no longer carries this component's CSS-isolation attribute. I grepped the whole tree: no::deep, no sibling scoped rule, noapp.css/kagaku-ui.cssglobal rule targets any of the three migrated selectors. Nothing was shadowed, so nothing resurfaces when the inline styles take over.RootClassis a faithful port. String-identical output to the old interpolation (kg-tags kg-tags--readonly/kg-tags), and.kg-tags--readonlynever had a CSS rule even at base — a pure semantic hook, correctly preserved per the keep-classes rule. Bonus: no more trailing space in the enabledclassattribute..kg-comboboxkeeps itsposition:relativedropdown anchor together with its flex layout — mixed layout+skin stays scoped, exactly the survival rule from the dogfooding reviews.48a5e8b→479100ealso carries KUI #21/#22 (NavItemtree,nav.js, Tabs/Slider restyle), and Kagura rendersNavIteminWorkspaceShellandDesign. I didn't trust "builds clean", I verified against the bumped submodule at479100e.Local verification (CI absent for
02a30b7at review time — PR 20 minutes old, no bot comment): build 0 warnings / 0 errors under-warnaserror; full suites green 874 / 790 / 340 (BlazorAdapter, Integration, UseCases) — matching the PR table exactly.💡 Little ideas (non-blocking)~
Disabled_shows_the_tags_and_weights_but_no_editing_controls— theRootClassreadonly arm renders in the Disabled tests but nothing pins its output: flipping the ternary survives every suite (grep-verified: zero references tokg-tags--readonlyoutside the property itself — no CSS, no test). A one-linerAssert.Contains("kg-tags--readonly", cut.Find(".kg-tags").GetAttribute("class"))makes the port fully mutation-proofed. No consumer exists today, so it's seam-hardening, not a bug — but the sweep PRs will inherit this checklist, and "pin the conditional arms ofRootClass" belongs in it.Your calibration conclusion matches what I see in the file: 3 of 53 rules — dense editors are mostly component skin. The file-by-file sweep plan (
::deepfirst, layout-only roots, keep classes, mutation-check the pins) is exactly right. fufu~ I'm looking forward to the leaf pages ♪Automated review by Jibril · 2026-09-24
CI/CD: absent for head SHA (no bot comment yet) · Local checks: build 0w/0e -warnaserror · suites 874+790+340 green · mutation probe 1/1 killed
The full sweep, per your call — landed as
ad39914on top of the pilot.Scope: every layout-only scoped rule in
Kagura.BlazorAdapter(106 measured). Executed in five parallel batches on disjoint file sets, integrated, audited, built, and suite-verified.Result: 69 of 106 migrated across 50 files — −602 CSS lines / +184 markup lines. Layout-only rule count drops 106 → 37; scoped CSS total 654 → 584 rules.
The 37 kept rules are deliberate, each with a reason:
flex:1 1 auto+min-width:0,min-heightfloors) — no vocabulary component emits that combination, and most sit indisplay:gridparents where the stretch-child mapping is invalid. This is the vocabulary's honest edge..head h2typography descendants) or::deepchild-component overrides that need the literal scoped element.var(--space-5)— noSpacingenum member. 1inline-flexoutside a flex context, 1 pseudo-element.Semantics preserved throughout:
Element=keeps semantic tags (header/section/ul/span), ids/classes survive via the splat, conditional classes →RootClassproperties,@mediablocks untouched, test selectors preserved.Verification: build 0 warnings; BlazorAdapter 874, Integration 790, UseCases 340 — all green.
One review-surface note:
ProjectWorkspacePage.general__style-actionsrode a KUI globalkg-rowutility (flex+center+--space-3) that the inline style fully overrides — I dropped the dead class. If Jibril wants the vocabulary to own that case too, the fix is a vocabulary-sideGapon a utility replacement, not consumer CSS.Next after this merges: Orihon and Tsumugi, same checklist.
Replaced by #281 (single project-wide adoption PR from a clean base — same content, corrected framing). Closing this one per the maintainer's call.
Pull request closed