You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Split out of #52 so Tier 1 could ship independently (acceptance criterion 7). The primitives layer landed in #53 with the five Tier 1 components — button, badge, heading, label, icon — across all five themes and both template sets. These two containers were scoped out of it deliberately.
What
Component
Measured use in the reference repo
What it is
box / surface
59
A plain bordered/elevated container. Distinct from card, which imposes a header/body/footer structure the caller cannot opt out of. Most uses are just "a thing with a border and some padding."
prose / content
61
Typographic reset for server-rendered or user-supplied HTML — the block where <h2>, <p>, <ul> inside a chunk of markup get sane styling without the caller writing a class per element.
Per component: base wrapper + 5 cotton theme partials + 5 jinja templates = 11 files. 22 for both.
Settled, and these should be reused rather than redesigned:
primitives.py is the vocabulary and the class map, and AXIS_KINDS declares whether an axis's value becomes a class, a tag, or an attribute. A container that takes only class-valued axes needs no new machinery.
Classes are spelled longhand in the templates because Tailwind's scanner reads source text. A bidirectional parity test binds primitives.py and the templates.
{% cf_ui_validate %} on the cotton wrapper, validate() in the jinja template.
daisy has no prose without the Tailwind typography plugin.prose is a @tailwindcss/typography class, not a daisyUI one. Either the daisy variant declares that plugin as a requirement (and themes.py / the docs say so), or it emits something else. This is the same shape of asymmetry that made grid questionable in Add a primitives layer: button, icon, badge, heading, label across all five themes #52 — decide it explicitly rather than discovering it in a consumer's build.
Does box take an axis at all? Bulma's box and Bootstrap's border rounded p-3 are not obviously variant-able. An elevation or padding axis may be right, or the component may legitimately have no axes and just be a themed container.
Acceptance criteria
box/surface and prose/content implemented as base + 5 cotton themes + 5 jinja themes each.
Names chosen and justified — one name per component, not the slashes above.
Any new axis added to primitives.py with an AXIS_KINDS entry, a closed vocabulary, and per-theme class maps; the existing parity and drift tests must cover it without modification.
The daisy prose decision documented in docs/primitives.md — whether it requires @tailwindcss/typography, and if so where that is declared.
The escaping contract for prose stated explicitly in docs/escaping.md, including that cf-ui does not sanitize caller-supplied HTML.
Docs page coverage matching the Tier 1 components.
Split out of #52 so Tier 1 could ship independently (acceptance criterion 7). The primitives layer landed in #53 with the five Tier 1 components —
button,badge,heading,label,icon— across all five themes and both template sets. These two containers were scoped out of it deliberately.What
box/surfacecard, which imposes a header/body/footer structure the caller cannot opt out of. Most uses are just "a thing with a border and some padding."prose/content<h2>,<p>,<ul>inside a chunk of markup get sane styling without the caller writing a class per element.Per component: base wrapper + 5 cotton theme partials + 5 jinja templates = 11 files. 22 for both.
What #53 already settled, and what it does not
Settled, and these should be reused rather than redesigned:
primitives.pyis the vocabulary and the class map, andAXIS_KINDSdeclares whether an axis's value becomes a class, a tag, or an attribute. A container that takes only class-valued axes needs no new machinery.primitives.pyand the templates.{% cf_ui_validate %}on the cotton wrapper,validate()in the jinja template.Not settled, and this is the actual design work:
proseis the one primitive whose whole job is to wrap markup the caller supplies. Add a primitives layer: button, icon, badge, heading, label across all five themes #52's open question 4 called this out and feat(primitives): a primitives layer — button, badge, heading, label, icon (#52) #53 sidestepped it — Tier 1 primitives take slot content, sodocs/escaping.mdneeded no new rule.prosedoes not get that luxury: if the content is aSafeString/Markupthe caller built, the escaping contract has to be stated explicitly, and if it is user-supplied HTML the docs need to say plainly that cf-ui does not sanitize it and name what should.prosewithout the Tailwind typography plugin.proseis a@tailwindcss/typographyclass, not a daisyUI one. Either the daisy variant declares that plugin as a requirement (andthemes.py/ the docs say so), or it emits something else. This is the same shape of asymmetry that madegridquestionable in Add a primitives layer: button, icon, badge, heading, label across all five themes #52 — decide it explicitly rather than discovering it in a consumer's build.boxtake an axis at all? Bulma'sboxand Bootstrap'sborder rounded p-3are not obviously variant-able. An elevation or padding axis may be right, or the component may legitimately have no axes and just be a themed container.Acceptance criteria
box/surfaceandprose/contentimplemented as base + 5 cotton themes + 5 jinja themes each.primitives.pywith anAXIS_KINDSentry, a closed vocabulary, and per-theme class maps; the existing parity and drift tests must cover it without modification.prosedecision documented indocs/primitives.md— whether it requires@tailwindcss/typography, and if so where that is declared.prosestated explicitly indocs/escaping.md, including that cf-ui does not sanitize caller-supplied HTML.