feat: add Tailwind CSS via its own CLI

This commit is contained in:
fromme committed 2026-09-13 14:24:01 +02:00
1 parent 67875ccf10
commit da8af9ff08
17 files changed
+1255 -3

No files matched your search

+6
View File
@@ -18,3 +18,9 @@
/public/assets/
/assets/vendor/
###< symfony/asset-mapper ###
###> tailwindcss ###
/node_modules/
# Build artifact of `npm run tailwind:build` -- the source lives in /tailwind/.
/assets/styles/app.css
###< tailwindcss ###
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-3
View File
@@ -1,3 +0,0 @@
body {
background-color: skyblue;
}
+1037
View File
File diff suppressed because it is too large. Load diff
+12
View File
@@ -0,0 +1,12 @@
{
"name": "ephub",
"private": true,
"scripts": {
"tailwind:build": "tailwindcss -i tailwind/app.css -o assets/styles/app.css --minify",
"tailwind:watch": "tailwindcss -i tailwind/app.css -o assets/styles/app.css --watch"
},
"devDependencies": {
"@tailwindcss/forms": "^0.5.9",
"tailwindcss": "^3.4"
}
}
+36
View File
@@ -0,0 +1,36 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./templates/**/*.twig',
// Class strings built in PHP (badge/status helpers) are purged without this.
'./src/**/*.php',
],
theme: {
container: {
center: true,
padding: '2rem',
},
extend: {
fontFamily: {
sans: ['Lato', 'sans-serif'],
},
// EP house palette, ported from myep. Its per-brand palettes (sbw/snz/ser)
// are a multi-brand concern that does not apply to an internal tool.
colors: {
primary: '#3d8ccb',
secondary: '#f9c700',
'primary-bg': '#ebf3fa',
'primary-light': '#0070e0',
'primary-medium': '#165883',
'primary-dark': '#18527b',
pink: '#fa1a8c',
},
backgroundImage: {
'brand-gradient': 'linear-gradient(to top right, #009fff, #165883, #18527b)',
},
},
},
plugins: [
require('@tailwindcss/forms'),
],
}
+49
View File
@@ -0,0 +1,49 @@
/* lato-regular - latin */
@font-face {
font-display: swap;
font-family: 'Lato';
font-style: normal;
font-weight: 400;
src: url('../fonts/lato-v24-latin-regular.woff2') format('woff2');
}
/* lato-italic - latin */
@font-face {
font-display: swap;
font-family: 'Lato';
font-style: italic;
font-weight: 400;
src: url('../fonts/lato-v24-latin-italic.woff2') format('woff2');
}
/* lato-700 - latin */
@font-face {
font-display: swap;
font-family: 'Lato';
font-style: normal;
font-weight: 700;
src: url('../fonts/lato-v24-latin-700.woff2') format('woff2');
}
/* lato-900 - latin */
@font-face {
font-display: swap;
font-family: 'Lato';
font-style: normal;
font-weight: 900;
src: url('../fonts/lato-v24-latin-900.woff2') format('woff2');
}
/* These url()s are NOT relative to this file. postcss-import inlines this partial verbatim
and Tailwind's CLI does not rebase urls, so they are resolved by the browser relative to
the OUTPUT file, assets/styles/app.css -- which is what makes ../fonts/ correct.
AssetMapper then rewrites them to versioned paths when it compiles assets/styles/app.css. */
/* htmx indicator visibility. app.js sets htmx.config.includeIndicatorStyles = false, so htmx
injects no <style> block of its own -- these three rules are what replaces it. */
.htmx-indicator {
@apply invisible;
}
.htmx-request .htmx-indicator {
@apply visible;
}
.htmx-request.htmx-indicator {
@apply visible;
}
+4
View File
@@ -0,0 +1,4 @@
@import "components/typography.css";
@import "components/button.css";
@import "components/forms.css";
@import "components/badge.css";
+7
View File
@@ -0,0 +1,7 @@
@layer utilities {
/* Reserve the scrollbar gutter so content does not shift width when a
scrollbar appears (e.g. when a collapsible section is opened). */
.scroll-stable {
scrollbar-gutter: stable;
}
}
+8
View File
@@ -0,0 +1,8 @@
@import "tailwindcss/base";
@import "_base.css";
@import "tailwindcss/components";
@import "_components.css";
@import "tailwindcss/utilities";
@import "_utilities.css";
+3
View File
@@ -0,0 +1,3 @@
.badge {
@apply inline-flex items-center rounded-md px-1.5 py-0.5 text-xs font-medium whitespace-nowrap;
}
+35
View File
@@ -0,0 +1,35 @@
.button {
@apply inline-flex items-center justify-center space-x-2 h-8 leading-8 md:h-10 md:leading-10 px-4 md:px-8 cursor-pointer;
@apply uppercase leading-none text-center text-sm md:text-base;
@apply transition-colors outline-none focus:outline-2 focus:outline-offset-2 focus:outline-primary-dark;
@apply rounded-md;
}
.button--small {
@apply px-2 py-1 md:px-4 text-xs sm:text-sm;
}
.button--primary {
background: linear-gradient(120deg, #960167 0%, #9e036a 40%, #fa1a8c 100%);
@apply text-white;
@apply hover:bg-none hover:bg-pink/80;
}
.button[disabled] {
@apply cursor-not-allowed;
}
.button--secondary {
@apply bg-none bg-primary-light text-white;
@apply hover:bg-primary-light/50;
}
.button--neutral {
@apply bg-none bg-gray-200;
@apply hover:bg-gray-200/50;
}
.button--warning {
@apply bg-none bg-red-500 text-white;
@apply hover:bg-red-500/50;
}
+30
View File
@@ -0,0 +1,30 @@
label.required:after {
@apply inline-block text-sm;
content: '*';
}
.form-field {
@apply border-zinc-400 ring-0 mt-1 block w-full rounded-md;
@apply focus:outline-primary-light focus:border-zinc-800 focus:outline-2 focus:outline-offset-2;
}
.form-field--has-error {
@apply border-red-700;
}
.form-checkbox,
.form-radio {
@apply border-zinc-400 focus:border-zinc-800 ring-0 focus:outline-2 focus:outline-offset-2 focus:outline-primary-light text-primary h-4 w-4;
}
.form-checkbox--has-error,
.form-radio--has-error {
@apply border-red-700;
}
select[readonly] {
@apply pointer-events-none cursor-not-allowed;
}
input[readonly] {
@apply cursor-not-allowed;
}
+28
View File
@@ -0,0 +1,28 @@
h1,
.headline--primary {
@apply block text-3xl md:text-4xl font-bold mb-2;
}
h2,
.headline--secondary {
@apply block text-2xl md:text-3xl font-bold mb-2;
}
h3,
.headline--3 {
@apply block text-xl md:text-2xl font-bold leading-6 mb-2;
}
h4,
.headline--4 {
@apply block font-semibold;
}
.headline--underlined:after {
@apply block border-b-4 border-primary-light pb-4 mb-4 -mt-2 w-20;
content: '';
}
.subline {
@apply block text-xs md:text-sm font-normal leading-6 opacity-60;
}