Skip to content

docs(primitives): close Tier 3 — layout is out of scope, no grid (#55) - #60

Merged
fsecada01 merged 3 commits into
masterfrom
docs/component-framework-ui-55-grid-decision
Aug 1, 2026
Merged

docs(primitives): close Tier 3 — layout is out of scope, no grid (#55)#60
fsecada01 merged 3 commits into
masterfrom
docs/component-framework-ui-55-grid-decision

Conversation

@fsecada01

Copy link
Copy Markdown
Owner

Closes #55.

#55 was a decide-then-maybe-build, and the decision is won't-do. cf-ui does not ship a grid; docs/primitives.md now says so, with the reasoning, so the question does not come back as a bug report.

Base: this targets #54's branch, not master, because its only deliverable is a rewrite of the ## Not yet implemented section that #54 owns. GitHub will retarget it to master when #59 merges. Merge #59 first.

The ticket's premise did not survive checking

#55's own body says "Bootstrap, Bulma, Foundation and Fomantic each ship a 12-column grid" and treats daisyUI's absence of one as the whole difficulty. Checked against upstream documentation, that is wrong, and the two things it gets wrong are each fatal on their own.

Theme Columns Breakpoint model Tiers
Bootstrap 5.3 12 min-width (none) · sm 576 · md 768 · lg 992 · xl 1200 · xxl 1400
Bulma 1.0 12 mobile is max-width, the rest min-width mobile <768 · tablet 769 · desktop 1024 · widescreen 1216 · fullhd 1408
Foundation 6.7 12 min-width small 0 · medium 640 · large 1024 · xlarge 1200 · xxlarge 1440
Fomantic 2.9 16 min-width mobile 320 · tablet 768 · computer 992 · large monitor 1200 · widescreen 1920
Tailwind 3 (daisy) 12 utilities min-width sm 640 · md 768 · lg 1024 · xl 1280 · 2xl 1536

Fomantic's grid is 16 columns. A span of 6 would mean half the row on four themes and three-eighths of it on Fomantic. That is not a different spelling of one concept — it is a different concept, which is the first time an axis in this package has had no single idea underneath it. Every other axis cf-ui absorbs maps n framework names onto n spellings of one thing. And the failure is silent: the page still renders, just at the wrong width.

Bulma's mobile tier is a max-width cap while every other ladder is min-width. So a canonical breakpoint set is not a numbers problem where cf-ui picks the least-wrong value — it is a shape problem. at="mobile" would have to mean "from here up" on four themes and "below here" on the fifth, and a mapping that inverts a condition is not a mapping.

I also want to flag where I overstated the case, because it went into the doc corrected rather than quietly dropped: "no two frameworks agree on breakpoints" is not true. Bootstrap's md and Tailwind's md are both 768px, and Bulma's tablet is one pixel away. That incidental overlap was the strongest thing the build case had, and it still is not enough — agreement at one tier out of five, between two themes out of five, does not make the ladders interchangeable.

daisyUI's asymmetry, which the ticket led with, is real but turns out to be the least of it.

Why not the reduced version either (acceptance criterion 2)

The obvious retreat is a fixed set of column counts with no responsive axis. It covers most measured uses and sidesteps the breakpoint disagreement entirely.

It is still wrong to ship, for two reasons pointing the same way. A three-column layout that stays three columns on a phone is not a simpler grid, it is a broken one — so nobody would use the reduced version as-is; they would reach for the responsive escape hatch immediately, which is the part that does not work. And Fomantic's 16 columns break the reduced version just as thoroughly, because the column count is not the responsive axis. Cutting responsiveness removes the smaller problem and leaves the larger one intact.

The Tailwind literal-class cost — 60 spelled-out branches per template, duplicated in primitives.py for the parity test — is the third strike here, not the first. It would be worth paying for something that was semantically correct.

The cost, stated rather than hidden (acceptance criterion 5)

cf-ui's design principle is that switching CSS frameworks means changing CF_UI_THEME in one place. Layout is now a named exception. A consumer who writes <div class="columns"><div class="column is-6"> has written Bulma into their templates, and flipping the theme leaves every component correct and every page's layout broken.

That is a real limit, and the docs would rather name it than paper over it with a component that is silently wrong on one theme in five. The section ends with what to do instead — the framework's own vocabulary, plain CSS Grid / flexbox for theme-independent layout, Tailwind utilities if you are migrating there — and says plainly that this is a decision, not a gap, so please don't file it as a bug.

Also in this PR: a djLint drift that the gate could not see

prek run --all-files restyles all 12 of #54's new box/prose templates. That means every contributor's hook run would dirty files they did not touch, so djlint's own output is now committed and the reformat is a no-op.

Worth stating why it got through: this is not a lint failure. just lint-templates reports 0 errors on both trees before and after — djlint's check mode does not enforce single_attribute_per_line, only --reformat applies it. The gate was green on a file the formatter wanted to change. The change is layout inside the opening tag only and no class="…" value moved, which is the line that matters: whitespace inside a class value changes the rendered bytes and breaks the substring assertions the parity tests rely on.

It is committed on #54's branch (so #59 carries it) and merged forward into this one.

Acceptance criteria

  • A written decision with the reasoning — close as won't-do, in docs/primitives.md under ## Layout is out of scope.
  • Reduced version considered explicitly and rejected, with what was cut and why it does not help.
  • Canonical breakpoint set and per-theme mapping — not applicable, nothing was built.
  • daisy asymmetry stated — not applicable; it is described in the reasoning as the least of the three problems rather than as a shipped caveat.
  • docs/primitives.md says layout is out of scope and what to do instead.

Gate

2273 passed, 13 skipped · ruff check src tests clean · ruff format --check src tests clean · just lint-templates 0 errors on both trees · mkdocs build --strict clean · prek run --all-files all hooks pass and now leave the tree clean.

One note on the gate: ruff format --check . (repo-wide) flags 9 markdown files over Python fences inside code blocks. None are touched by this PR and it is not what the project or CI runs — justfile scopes it to src tests. Mentioning it because it is a real latent inconsistency someone will trip over, not because it blocks anything.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NhqNRBg83czKfr8L6FF5xf

fsecada01 and others added 2 commits July 31, 2026 21:17
The ticket's premise did not survive checking. It assumed four of five
themes ship a 12-column grid and only daisyUI was the odd one out.
Upstream says otherwise on two counts, each fatal on its own:

Fomantic's grid is 16 columns. A span of 6 would mean half the row on
four themes and three-eighths of it on Fomantic — a different idea, not
a different spelling — and the page would still render, just at the
wrong width. Every other axis cf-ui absorbs maps n names onto one
concept. This one has no single concept underneath it.

Bulma's mobile tier is a max-width cap while every other framework's
ladder is min-width, so a canonical breakpoint set is not a numbers
problem where cf-ui picks the least-wrong value. at="mobile" would have
to mean "from here up" on four themes and "below here" on the fifth,
and a mapping that inverts a condition is not a mapping.

The reduced non-responsive version is not a fallback either. A layout
that stays three columns on a phone is broken rather than simpler, so
consumers would reach immediately for the axis that does not work — and
Fomantic's column count breaks the reduced version just as thoroughly,
because it is not the responsive axis. Cutting responsiveness removes
the smaller problem and leaves the larger one. The Tailwind
literal-class cost is the third strike, not the first.

The cost is named rather than hidden: layout is now a stated exception
to "changing frameworks means changing CF_UI_THEME in one place", with
the alternatives that do work.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NhqNRBg83czKfr8L6FF5xf
…docs/component-framework-ui-55-grid-decision
@fsecada01

Copy link
Copy Markdown
Owner Author

Review — PR #60

Docs-only decision record plus a formatter-drift fix carried in from the base branch. 128 additions, 11 deletions, 2 files. Reviewed the factual claims (which is where a decision doc can actually be wrong) rather than the prose.

Verification of the load-bearing claims

Both of the two facts the decision rests on hold up:

  • Fomantic 2.9's grid is 16 columns by default — confirmed. .ui.grid divides into 16, and the width classes are worded (eight wide column), which is why the count is easy to miss when skimming: nothing in the class name says 16. This is the strongest argument in the PR and it is correct.
  • Bulma 1.0's mobile is max-width: 768px — confirmed; it compiles from until($tablet) while tablet/desktop/widescreen/fullhd are all from(). So it genuinely is a different shape, not a different number.

The self-correction in the PR body is also right and worth keeping: Bootstrap md and Tailwind md are both 768px, so "no two frameworks agree" would have been false. Stating the strongest counter-evidence against your own conclusion is the correct move here.

Findings

1. The Foundation row overstates its usable tiers — and understates your own argument. (low)

The table lists five Foundation breakpoints (small/medium/large/xlarge/xxlarge). Accurate as defined breakpoints, but Foundation 6.7 only generates grid classes for small, medium and large out of the box — $breakpoint-classes excludes xlarge and xxlarge by default. A reader comparing rows would conclude Foundation has a 5-rung ladder like the others; it has 3 unless you edit the settings file.

This cuts in your favour, so it is worth a parenthetical rather than a rewrite: it means a canonical 5-tier set would have two tiers that silently do nothing on Foundation, on top of the Bulma inversion.

2. "and will not" is a stronger claim than the evidence supports. (low, judgement)

The reasoning is contingent on facts about five specific framework versions. If cf-ui later dropped Fomantic, or Fomantic moved to 12 columns, the argument would not survive its own premises — and the doc would still say "will not."

Not asking for a hedge, since a decision doc that reads as tentative gets re-litigated, which is exactly what this is trying to prevent. But "will not while these five themes are what they are" costs three words and keeps the door honest.

3. The djLint drift is the real defect in this PR, and it is worth more than the one paragraph it gets. (medium — process, not code)

just lint-templates reports 0 errors on templates that djlint --reformat immediately rewrites. That is a gate that cannot see the thing it exists to enforce: single_attribute_per_line is a reformat-only rule, so check mode is structurally blind to it, and the 12 files shipped in #54 having passed the gate is not evidence they were formatted.

The fix here (commit the formatter's output) resolves this instance and does nothing about the next one. The durable version is a check-mode equivalent — run --reformat against a scratch copy and fail on any diff, or drop single_attribute_per_line if it is not worth enforcing. Per the repo's own "replace the mechanism, don't patch it," this is a patch.

Out of scope for #55 and correctly not folded into it. Flagging it as a follow-up worth filing rather than something to fix in this PR.

4. Missing: nothing in the code refuses a grid. (informational)

The decision lives only in prose. If someone adds "grid" to PRIMITIVES later without reading docs/primitives.md, no test objects — IMPLEMENTED is derived, so it would simply demand templates and start checking parity on them.

That is probably fine; a test asserting a component's absence is unusual and has its own smell. Noting it because the repo's pattern elsewhere is to put invariants where the owned artifact lives, and this one deliberately does not.

Non-findings I checked

  • No remaining references to the removed ## Not yet implemented anchor anywhere in the docs, README, or mkdocs nav — the two inbound links to primitives.md target #cfprose-c-cfprose, which still exists. mkdocs build --strict passing confirms it.
  • No stale grid/Tier 3 references left in primitives.py, the README, or any other doc.
  • The djlint change touches layout inside the opening tag only; no class="…" value moved, which is the constraint that would have broken the parity tests' substring assertions. Full suite green at 2273/13 before and after.
  • The <div class="columns"> example is inline code, not a component tag, so it is invisible to the test_docs_samples.py guard by design. The one hypothetical cotton tag written during drafting was caught by that guard and rewritten as prose — the guard is doing its job.

Verdict

The conclusion is well-supported and the reasoning is durable enough to stop the question coming back, which is the actual deliverable. Findings 1 and 2 are optional polish. Finding 3 is a genuine gap in the repo's tooling that this PR surfaces without closing, and deserves its own issue.

…docs/component-framework-ui-55-grid-decision
Base automatically changed from feat/component-framework-ui-54-tier-2-primitives to master August 1, 2026 01:37
@fsecada01 fsecada01 self-assigned this Aug 1, 2026
@fsecada01 fsecada01 closed this Aug 1, 2026
@fsecada01 fsecada01 reopened this Aug 1, 2026
@fsecada01
fsecada01 merged commit 88c5bd9 into master Aug 1, 2026
9 checks passed
@fsecada01
fsecada01 deleted the docs/component-framework-ui-55-grid-decision branch August 1, 2026 01:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation wontfix This will not be worked on

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Primitives Tier 3: decide whether grid is in scope, then build or close

1 participant