refactor: replace hand-rolled utility CSS with Tailwind classes (host build now scans theme templates)

This commit is contained in:
Alex Dunmow 2026-07-05 17:56:00 +08:00
parent c2dd751f6b
commit 707b1f1ce1
5 changed files with 13 additions and 43 deletions

View File

@ -182,29 +182,13 @@ body.coffee-paper {
} }
/* --- Layout helpers ------------------------------------------------------ /* --- Layout helpers ------------------------------------------------------
* Explicit CSS so these layouts never depend on the host Tailwind JIT * coffee-pour-grid keeps an explicit md 2fr:3fr split a non-standard grid
* compiling arbitrary/responsive utilities out of THEME templates it does * ratio with no plain Tailwind utility. Single-column base collapses on
* not scan them reliably, so `min-h-[50vh]` / `md:grid-cols-[2fr_3fr]` / * mobile. */
* `md:grid-cols-2` in a theme file can silently vanish. Base is always a
* single column, so grids collapse on mobile regardless of the JIT. */
.coffee-minh-50 { min-height: 50vh; }
.coffee-minh-75 { min-height: 75vh; }
.coffee-minh-screen { min-height: 100vh; }
.coffee-minh-400 { min-height: 400px; }
.coffee-minh-320 { min-height: 320px; }
.coffee-split-2 { display: grid; grid-template-columns: 1fr; }
.coffee-pour-grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; } .coffee-pour-grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; }
.coffee-menu-grid { display: grid; grid-template-columns: 1fr; gap: 2.5rem 3rem; }
.coffee-info-grid { display: grid; grid-template-columns: 1fr; gap: 2.5rem; }
@media (min-width: 768px) { @media (min-width: 768px) {
.coffee-pour-grid { grid-template-columns: 2fr 3fr; align-items: center; } .coffee-pour-grid { grid-template-columns: 2fr 3fr; align-items: center; }
.coffee-menu-grid.coffee-menu-grid--2 { grid-template-columns: 1fr 1fr; }
.coffee-info-grid.coffee-info-grid--2 { grid-template-columns: 1fr 1fr; }
}
@media (min-width: 1024px) {
.coffee-split-2 { grid-template-columns: 1fr 1fr; }
} }
/* --- Price + spec chips ------------------------------------------------- */ /* --- Price + spec chips ------------------------------------------------- */

View File

@ -290,29 +290,15 @@ css:
} }
/* --- Layout helpers ------------------------------------------------------ /* --- Layout helpers ------------------------------------------------------
* Explicit CSS so these layouts never depend on the host Tailwind JIT * coffee-pour-grid keeps an explicit md 2fr:3fr split — a non-standard grid
* compiling arbitrary/responsive utilities out of THEME templates — it does * ratio with no plain Tailwind utility. Single-column base collapses on
* not scan them reliably, so `min-h-[50vh]` / `md:grid-cols-[2fr_3fr]` / * mobile. (The min-height + standard-column grid helpers that used to live
* `md:grid-cols-2` in a theme file can silently vanish. Base is always a * here are now plain Tailwind utilities in the templates, since the host
* single column, so grids collapse on mobile regardless of the JIT. */ * build scans theme .ninjatpl files.) */
.coffee-minh-50 { min-height: 50vh; }
.coffee-minh-75 { min-height: 75vh; }
.coffee-minh-screen { min-height: 100vh; }
.coffee-minh-400 { min-height: 400px; }
.coffee-minh-320 { min-height: 320px; }
.coffee-split-2 { display: grid; grid-template-columns: 1fr; }
.coffee-pour-grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; } .coffee-pour-grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; }
.coffee-menu-grid { display: grid; grid-template-columns: 1fr; gap: 2.5rem 3rem; }
.coffee-info-grid { display: grid; grid-template-columns: 1fr; gap: 2.5rem; }
@media (min-width: 768px) { @media (min-width: 768px) {
.coffee-pour-grid { grid-template-columns: 2fr 3fr; align-items: center; } .coffee-pour-grid { grid-template-columns: 2fr 3fr; align-items: center; }
.coffee-menu-grid.coffee-menu-grid--2 { grid-template-columns: 1fr 1fr; }
.coffee-info-grid.coffee-info-grid--2 { grid-template-columns: 1fr 1fr; }
}
@media (min-width: 1024px) {
.coffee-split-2 { grid-template-columns: 1fr 1fr; }
} }
/* --- Price + spec chips ------------------------------------------------- */ /* --- Price + spec chips ------------------------------------------------- */

View File

@ -22,14 +22,14 @@
{% if trustLogos %}<div class="mt-10"><p class="coffee-hand mb-3 text-lg text-accent">Regulars love</p><div class="flex flex-wrap items-center gap-6{% if align == "center" %} justify-center{% endif %}">{% for logo in trustLogos %}{% if logo.url %}<a href="{{ logo.url }}" target="_blank" rel="noopener" class="opacity-60 transition-opacity hover:opacity-100">{% img logo.image alt=logo.alt class="h-8 w-auto" %}</a>{% else %}{% img logo.image alt=logo.alt class="h-8 w-auto opacity-60" %}{% endif %}{% endfor %}</div></div>{% endif %} {% if trustLogos %}<div class="mt-10"><p class="coffee-hand mb-3 text-lg text-accent">Regulars love</p><div class="flex flex-wrap items-center gap-6{% if align == "center" %} justify-center{% endif %}">{% for logo in trustLogos %}{% if logo.url %}<a href="{{ logo.url }}" target="_blank" rel="noopener" class="opacity-60 transition-opacity hover:opacity-100">{% img logo.image alt=logo.alt class="h-8 w-auto" %}</a>{% else %}{% img logo.image alt=logo.alt class="h-8 w-auto opacity-60" %}{% endif %}{% endfor %}</div></div>{% endif %}
{% endmacro %} {% endmacro %}
{% if variant == "split" %} {% if variant == "split" %}
<section class="hero coffee-split-2 overflow-hidden bg-background text-foreground{% if class %} {{ class }}{% endif %}"> <section class="hero grid grid-cols-1 lg:grid-cols-2 overflow-hidden bg-background text-foreground{% if class %} {{ class }}{% endif %}">
<div class="coffee-minh-320 relative bg-secondary {% if mediaPosition == "left" %}order-1 lg:order-1{% else %}order-1 lg:order-2{% endif %}">{% if hasImage %}{% img backgroundImage alt=headlineText class="absolute inset-0 h-full w-full object-cover" layout="hero" %}{% endif %}</div> <div class="min-h-[320px] relative bg-secondary {% if mediaPosition == "left" %}order-1 lg:order-1{% else %}order-1 lg:order-2{% endif %}">{% if hasImage %}{% img backgroundImage alt=headlineText class="absolute inset-0 h-full w-full object-cover" layout="hero" %}{% endif %}</div>
<div class="flex flex-col justify-center px-6 py-16 lg:px-12 {% if mediaPosition == "left" %}order-2 lg:order-2{% else %}order-2 lg:order-1{% endif %}"><div class="max-w-lg text-left">{{ herocontent("left") }}</div></div> <div class="flex flex-col justify-center px-6 py-16 lg:px-12 {% if mediaPosition == "left" %}order-2 lg:order-2{% else %}order-2 lg:order-1{% endif %}"><div class="max-w-lg text-left">{{ herocontent("left") }}</div></div>
</section> </section>
{% else %} {% else %}
{% set align = "center" %} {% set align = "center" %}
{% if variant == "left-aligned" %}{% set align = "left" %}{% endif %} {% if variant == "left-aligned" %}{% set align = "left" %}{% endif %}
<section class="hero relative flex flex-col overflow-hidden bg-background text-foreground {% if minHeight == "screen" %}coffee-minh-screen{% elif minHeight == "50vh" %}coffee-minh-50{% elif minHeight == "auto" %}coffee-minh-400{% else %}coffee-minh-75{% endif %} {% if verticalAlign == "top" %}justify-start pt-20{% elif verticalAlign == "bottom" %}justify-end pb-20{% else %}justify-center{% endif %}{% if class %} {{ class }}{% endif %}"> <section class="hero relative flex flex-col overflow-hidden bg-background text-foreground {% if minHeight == "screen" %}min-h-screen{% elif minHeight == "50vh" %}min-h-[50vh]{% elif minHeight == "auto" %}min-h-[400px]{% else %}min-h-[75vh]{% endif %} {% if verticalAlign == "top" %}justify-start pt-20{% elif verticalAlign == "bottom" %}justify-end pb-20{% else %}justify-center{% endif %}{% if class %} {{ class }}{% endif %}">
{% if hasImage %}<div class="absolute inset-0 z-0">{% img backgroundImage alt=headlineText class="h-full w-full object-cover" layout="hero" %}{% if showOverlay %}<div class="absolute inset-0 {% if overlayColor == "light" %}bg-background/60{% elif overlayColor == "primary" %}bg-primary/50{% elif overlayOpacity <= 30 %}bg-black/30{% elif overlayOpacity <= 50 %}bg-black/50{% elif overlayOpacity <= 70 %}bg-black/70{% else %}bg-black/80{% endif %}"></div>{% endif %}</div>{% endif %} {% if hasImage %}<div class="absolute inset-0 z-0">{% img backgroundImage alt=headlineText class="h-full w-full object-cover" layout="hero" %}{% if showOverlay %}<div class="absolute inset-0 {% if overlayColor == "light" %}bg-background/60{% elif overlayColor == "primary" %}bg-primary/50{% elif overlayOpacity <= 30 %}bg-black/30{% elif overlayOpacity <= 50 %}bg-black/50{% elif overlayOpacity <= 70 %}bg-black/70{% else %}bg-black/80{% endif %}"></div>{% endif %}</div>{% endif %}
<div class="relative z-10 mx-auto w-full max-w-4xl px-4 sm:px-6 lg:px-8 {% if variant == "left-aligned" %}text-left{% else %}text-center{% endif %}">{{ herocontent(align) }}</div> <div class="relative z-10 mx-auto w-full max-w-4xl px-4 sm:px-6 lg:px-8 {% if variant == "left-aligned" %}text-left{% else %}text-center{% endif %}">{{ herocontent(align) }}</div>
</section> </section>

View File

@ -1,7 +1,7 @@
<section class="py-16 md:py-24 bg-background text-foreground{% if class %} {{ class }}{% endif %}"> <section class="py-16 md:py-24 bg-background text-foreground{% if class %} {{ class }}{% endif %}">
<div class="mx-auto max-w-5xl px-4"> <div class="mx-auto max-w-5xl px-4">
{% if heading %}<h2 class="coffee-display text-3xl text-primary md:text-4xl"><span class="coffee-doodle-underline">{{ heading }}</span></h2>{% endif %} {% if heading %}<h2 class="coffee-display text-3xl text-primary md:text-4xl"><span class="coffee-doodle-underline">{{ heading }}</span></h2>{% endif %}
<div class="coffee-info-grid{% if mapEmbedUrl %} coffee-info-grid--2{% endif %} mt-10"> <div class="grid grid-cols-1 gap-10{% if mapEmbedUrl %} md:grid-cols-2{% endif %} mt-10">
<div> <div>
{% if hours %} {% if hours %}
<table class="coffee-body w-full text-sm" data-coffee-hours> <table class="coffee-body w-full text-sm" data-coffee-hours>

View File

@ -3,7 +3,7 @@
{% if heading %}<h2 class="coffee-display text-3xl text-primary md:text-4xl"><span class="coffee-doodle-underline">{{ heading }}</span></h2>{% endif %} {% if heading %}<h2 class="coffee-display text-3xl text-primary md:text-4xl"><span class="coffee-doodle-underline">{{ heading }}</span></h2>{% endif %}
{% if intro %}<p class="coffee-body mt-3 max-w-2xl text-lg text-muted-foreground">{{ intro }}</p>{% endif %} {% if intro %}<p class="coffee-body mt-3 max-w-2xl text-lg text-muted-foreground">{{ intro }}</p>{% endif %}
<div class="coffee-chalkboard mt-10 p-6 md:p-10"> <div class="coffee-chalkboard mt-10 p-6 md:p-10">
<div class="coffee-menu-grid{% if columns == 2 %} coffee-menu-grid--2{% endif %}"> <div class="grid grid-cols-1 gap-x-12 gap-y-10{% if columns == 2 %} md:grid-cols-2{% endif %}">
{% for section in sections %} {% for section in sections %}
<div class="menu-section"> <div class="menu-section">
{% if section.title %}<h3 class="coffee-hand border-b coffee-chalk-rule pb-2 text-3xl">{{ section.title }}</h3>{% endif %} {% if section.title %}<h3 class="coffee-hand border-b coffee-chalk-rule pb-2 text-3xl">{{ section.title }}</h3>{% endif %}