From 7722abcd668725f5e9688d6089edba6cb71db0b7 Mon Sep 17 00:00:00 2001 From: George Cushen Date: Sun, 17 Aug 2025 20:58:14 +0100 Subject: [PATCH] feat: upgrade from Tailwind v3 to v4 See Tailwind v4 breaking changes: https://tailwindcss.com/docs/upgrade-guide See Hugo's new integration with Tailwind v4: https://gohugo.io/functions/css/tailwindcss/ Close #3211 --- .github/workflows/build-test-site.yaml | 7 +- .../_partials/page_metadata_authors.html | 2 +- modules/blox-tailwind/.npmrc | 4 + modules/blox-tailwind/README.md | 66 +- .../blox-tailwind/assets/css/blox/navbar.css | 22 +- modules/blox-tailwind/assets/css/chroma.css | 9 +- .../assets/css/color-utilities.css | 285 +++ .../assets/css/components/cards.css | 32 +- .../assets/css/components/copy.css | 9 +- .../assets/css/components/page.css | 7 +- .../assets/css/components/sidebar-left.css | 26 +- .../assets/css/components/steps.css | 14 +- .../assets/css/config/safelist.css | 5 + .../assets/css/config/tailwind.css | 25 + .../blox-tailwind/assets/css/config/theme.css | 61 + .../assets/css/framework/base.css | 54 + .../assets/css/framework/components.css | 110 + modules/blox-tailwind/assets/css/main.css | 111 +- modules/blox-tailwind/assets/css/styles.css | 9 - modules/blox-tailwind/assets/css/tailwind.css | 3 - .../assets/css/views/attachments.css | 22 +- modules/blox-tailwind/hugo.yaml | 12 + .../headers/floating-theme-toggler.html | 4 +- .../components/headers/navbar-simple.html | 16 +- .../_partials/components/headers/navbar.html | 10 +- .../blox-tailwind/layouts/_partials/css.html | 13 + .../layouts/_partials/page_links.html | 28 +- .../_partials/page_metadata_authors.html | 2 +- .../layouts/_partials/site_head.html | 16 +- modules/blox-tailwind/layouts/taxonomy.html | 32 + modules/blox-tailwind/layouts/terms.html | 2 +- modules/blox-tailwind/package.json | 31 +- modules/blox-tailwind/pnpm-lock.yaml | 1923 +++++++++-------- modules/blox-tailwind/pnpm-workspace.yaml | 2 + modules/blox-tailwind/postcss.config.js | 10 - modules/blox-tailwind/tailwind.config.js | 183 -- package.json | 5 +- pnpm-lock.yaml | 561 +++-- scripts/view-starter-dev.sh | 30 + .../academic-cv/content/authors/_index.md | 6 +- .../portfolio/content/authors/_index.md | 6 +- starters/academic-cv/netlify.toml | 7 +- starters/academic-cv/package.json | 16 + starters/academic-cv/pnpm-lock.yaml | 707 ++++++ starters/blog/content/authors/_index.md | 6 +- starters/blog/netlify.toml | 8 +- starters/blog/package.json | 16 + starters/blog/pnpm-lock.yaml | 707 ++++++ .../documentation/content/authors/_index.md | 6 +- starters/documentation/netlify.toml | 7 +- starters/documentation/package.json | 16 + starters/documentation/pnpm-lock.yaml | 707 ++++++ .../landing-page/content/authors/_index.md | 6 +- starters/landing-page/netlify.toml | 7 +- starters/landing-page/package.json | 16 + .../link-in-bio/content/authors/_index.md | 6 +- starters/link-in-bio/netlify.toml | 7 +- starters/link-in-bio/package.json | 16 + starters/resume/content/authors/_index.md | 6 +- starters/resume/netlify.toml | 7 +- starters/resume/package.json | 16 + 61 files changed, 4607 insertions(+), 1458 deletions(-) create mode 100644 modules/blox-tailwind/.npmrc create mode 100644 modules/blox-tailwind/assets/css/color-utilities.css create mode 100644 modules/blox-tailwind/assets/css/config/safelist.css create mode 100644 modules/blox-tailwind/assets/css/config/tailwind.css create mode 100644 modules/blox-tailwind/assets/css/config/theme.css create mode 100644 modules/blox-tailwind/assets/css/framework/base.css create mode 100644 modules/blox-tailwind/assets/css/framework/components.css delete mode 100644 modules/blox-tailwind/assets/css/styles.css delete mode 100644 modules/blox-tailwind/assets/css/tailwind.css create mode 100644 modules/blox-tailwind/layouts/_partials/css.html create mode 100644 modules/blox-tailwind/layouts/taxonomy.html create mode 100644 modules/blox-tailwind/pnpm-workspace.yaml delete mode 100644 modules/blox-tailwind/postcss.config.js delete mode 100644 modules/blox-tailwind/tailwind.config.js create mode 100644 starters/academic-cv/package.json create mode 100644 starters/academic-cv/pnpm-lock.yaml create mode 100644 starters/blog/package.json create mode 100644 starters/blog/pnpm-lock.yaml create mode 100644 starters/documentation/package.json create mode 100644 starters/documentation/pnpm-lock.yaml create mode 100644 starters/landing-page/package.json create mode 100644 starters/link-in-bio/package.json create mode 100644 starters/resume/package.json diff --git a/.github/workflows/build-test-site.yaml b/.github/workflows/build-test-site.yaml index 1d6fbdc4..1779101b 100644 --- a/.github/workflows/build-test-site.yaml +++ b/.github/workflows/build-test-site.yaml @@ -34,8 +34,11 @@ jobs: - recursive: false args: [--frozen-lockfile] -# - name: Install JS dependencies -# run: rm -rf node_modules && pnpm install --frozen-lockfile + - name: Install Tailwind v4 dependencies + run: | + cd modules/blox-tailwind + pnpm install --frozen-lockfile + cd ../.. - name: Check for linting errors run: pnpm run lint:js # TODO: also lint styles again once new rule errors resolved diff --git a/modules/blox-bootstrap/layouts/_partials/page_metadata_authors.html b/modules/blox-bootstrap/layouts/_partials/page_metadata_authors.html index 5eec60aa..5024f7f8 100644 --- a/modules/blox-bootstrap/layouts/_partials/page_metadata_authors.html +++ b/modules/blox-bootstrap/layouts/_partials/page_metadata_authors.html @@ -7,7 +7,7 @@ {{- if gt $index 0 }}, {{ end -}} - {{/* Effectively check the page's `_build` option as `_build` is not exposed in Hugo's Page object. */}} + {{/* Effectively check the page's `build` option as `build` is not exposed in Hugo's Page object. */}} {{- if .RelPermalink -}} {{.LinkTitle}} {{- else -}} diff --git a/modules/blox-tailwind/.npmrc b/modules/blox-tailwind/.npmrc new file mode 100644 index 00000000..5b7b8fb3 --- /dev/null +++ b/modules/blox-tailwind/.npmrc @@ -0,0 +1,4 @@ +# pnpm compatibility settings +auto-install-peers=true +strict-peer-dependencies=false +public-hoist-pattern[]=* diff --git a/modules/blox-tailwind/README.md b/modules/blox-tailwind/README.md index 5997f093..217ca59c 100644 --- a/modules/blox-tailwind/README.md +++ b/modules/blox-tailwind/README.md @@ -1,19 +1,67 @@ # Hugo Blox Tailwind UI -The Hugo Blox web framework utilising [TailwindCSS](https://tailwindcss.com/) and its [typography plugin](https://tailwindcss.com/docs/typography-plugin) for styling components. +The Hugo Blox web framework utilizing [Tailwind CSS v4](https://tailwindcss.com/) with Hugo's native integration for styling components with Tailwind v4. -See the Blog Starter Template for an example using this module. +## Requirements + +- Hugo v0.148.2+ (Extended Edition) +- Node.js v20+ +- pnpm (see `packageManager` field in package.json) + +## Quick Start + +### 1. Install Dependencies + +```bash +pnpm install +``` + +### 2. Run Development Server + +```bash +hugo server +``` + +Tailwind CSS is processed automatically by Hugo using the `css.TailwindCSS` function. + +## Features + +- **Tailwind CSS v4**: Latest version with improved performance over Tailwind v3 +- **Hugo Native Integration**: Uses Hugo's built-in `css.TailwindCSS` function +- **Dynamic CSS Generation**: Only includes utilities actually used in your content for ultra-fast page loads +- **No Pre-compilation**: CSS is generated on-demand (previously Tailwind v3 was pre-compiled in Hugo Blox as `wc.min.css`) +- **Community Components**: Community components work seamlessly without manual compilation + +## Configuration + +The Tailwind configuration is now in CSS format at `assets/css/main.css` using the `@theme` directive. The configuration includes: + +- Hugo Blox color schemes (primary, secondary, neutral) +- Typography settings +- Safelist patterns for dynamic classes +- Dark mode support + +## Migration from Tailwind v3 + +If you're upgrading from Tailwind v3: + +1. Install the new dependencies: `pnpm install` +2. Remove any `assets/dist/wc.min.css` files +3. Add the `package.json` file from the latest starter templates +4. Update your deployment scripts to install it with `pnpm install` (refer to the latest `.github` folder in the starters) +5. The old `tailwind.config.js` and `postcss.config.js` files are no longer needed ## Development +For module development: + ```bash -hugo mod npm pack -npm install -``` +# Install dependencies +pnpm install -You need to add this to your `config.yaml` to enable Hugo's Tailwind integration: +# Run development server +hugo server --disableFastRender -```yaml -build: - writeStats: true +# Build for production +hugo --minify ``` diff --git a/modules/blox-tailwind/assets/css/blox/navbar.css b/modules/blox-tailwind/assets/css/blox/navbar.css index 585a26cf..326968a6 100644 --- a/modules/blox-tailwind/assets/css/blox/navbar.css +++ b/modules/blox-tailwind/assets/css/blox/navbar.css @@ -41,7 +41,15 @@ input#nav-toggle:checked ~ #nav-menu { } .nav-link { - @apply hover:text-primary-700 dark:hover:text-primary-300 dark:text-white block p-3 font-semibold transition lg:px-2 lg:py-3; + @apply dark:text-white block p-3 font-semibold transition lg:px-2 lg:py-3; +} + +.nav-link:hover { + color: rgb(var(--color-primary-700)); +} + +.dark .nav-link:hover { + color: rgb(var(--color-primary-300)); } .nav-dropdown { @@ -63,9 +71,17 @@ input#nav-toggle:checked ~ #nav-menu { } .nav-dropdown-item { - @apply px-4 [&:not(:last-child)]:mb-2 dark:hover:bg-primary-500; + @apply px-4 [&:not(:last-child)]:mb-2; +} + +.dark .nav-dropdown-item:hover { + background-color: rgb(var(--color-primary-500)); } .nav-dropdown-link { - @apply hover:text-primary-700 dark:text-white dark:hover:text-white block py-1 font-semibold transition; + @apply dark:text-white dark:hover:text-white block py-1 font-semibold transition; +} + +.nav-dropdown-link:hover { + color: rgb(var(--color-primary-700)); } diff --git a/modules/blox-tailwind/assets/css/chroma.css b/modules/blox-tailwind/assets/css/chroma.css index 0ff91eda..babb1e9f 100644 --- a/modules/blox-tailwind/assets/css/chroma.css +++ b/modules/blox-tailwind/assets/css/chroma.css @@ -5,5 +5,12 @@ /* Requires relative position for Code Copy button */ .prose .chroma, .prose pre { - @apply relative rounded-md text-neutral-700 bg-neutral-50 dark:bg-slate-700 dark:text-white; + @apply relative rounded-md dark:bg-slate-700 dark:text-white; + color: rgb(var(--color-neutral-700)); + background-color: rgb(var(--color-neutral-50)); +} + +.dark .prose .chroma, +.dark .prose pre { + color: white; } diff --git a/modules/blox-tailwind/assets/css/color-utilities.css b/modules/blox-tailwind/assets/css/color-utilities.css new file mode 100644 index 00000000..2a9f3c81 --- /dev/null +++ b/modules/blox-tailwind/assets/css/color-utilities.css @@ -0,0 +1,285 @@ +/* Comprehensive Color Utilities for Hugo Blox with Tailwind v4 */ +/* This file defines all color utilities using CSS variables from theme files */ + +@layer utilities { + /* Primary Colors - Full Range (50-950) */ + .bg-primary-50 { background-color: rgb(var(--color-primary-50)); } + .bg-primary-100 { background-color: rgb(var(--color-primary-100)); } + .bg-primary-200 { background-color: rgb(var(--color-primary-200)); } + .bg-primary-300 { background-color: rgb(var(--color-primary-300)); } + .bg-primary-400 { background-color: rgb(var(--color-primary-400)); } + .bg-primary-500 { background-color: rgb(var(--color-primary-500)); } + .bg-primary-600 { background-color: rgb(var(--color-primary-600)); } + .bg-primary-700 { background-color: rgb(var(--color-primary-700)); } + .bg-primary-800 { background-color: rgb(var(--color-primary-800)); } + .bg-primary-900 { background-color: rgb(var(--color-primary-900)); } + .bg-primary-950 { background-color: rgb(var(--color-primary-950)); } + + .text-primary-50 { color: rgb(var(--color-primary-50)); } + .text-primary-100 { color: rgb(var(--color-primary-100)); } + .text-primary-200 { color: rgb(var(--color-primary-200)); } + .text-primary-300 { color: rgb(var(--color-primary-300)); } + .text-primary-400 { color: rgb(var(--color-primary-400)); } + .text-primary-500 { color: rgb(var(--color-primary-500)); } + .text-primary-600 { color: rgb(var(--color-primary-600)); } + .text-primary-700 { color: rgb(var(--color-primary-700)); } + .text-primary-800 { color: rgb(var(--color-primary-800)); } + .text-primary-900 { color: rgb(var(--color-primary-900)); } + .text-primary-950 { color: rgb(var(--color-primary-950)); } + + .border-primary-50 { border-color: rgb(var(--color-primary-50)); } + .border-primary-100 { border-color: rgb(var(--color-primary-100)); } + .border-primary-200 { border-color: rgb(var(--color-primary-200)); } + .border-primary-300 { border-color: rgb(var(--color-primary-300)); } + .border-primary-400 { border-color: rgb(var(--color-primary-400)); } + .border-primary-500 { border-color: rgb(var(--color-primary-500)); } + .border-primary-600 { border-color: rgb(var(--color-primary-600)); } + .border-primary-700 { border-color: rgb(var(--color-primary-700)); } + .border-primary-800 { border-color: rgb(var(--color-primary-800)); } + .border-primary-900 { border-color: rgb(var(--color-primary-900)); } + .border-primary-950 { border-color: rgb(var(--color-primary-950)); } + + /* Secondary Colors - Full Range */ + .bg-secondary-50 { background-color: rgb(var(--color-secondary-50)); } + .bg-secondary-100 { background-color: rgb(var(--color-secondary-100)); } + .bg-secondary-200 { background-color: rgb(var(--color-secondary-200)); } + .bg-secondary-300 { background-color: rgb(var(--color-secondary-300)); } + .bg-secondary-400 { background-color: rgb(var(--color-secondary-400)); } + .bg-secondary-500 { background-color: rgb(var(--color-secondary-500)); } + .bg-secondary-600 { background-color: rgb(var(--color-secondary-600)); } + .bg-secondary-700 { background-color: rgb(var(--color-secondary-700)); } + .bg-secondary-800 { background-color: rgb(var(--color-secondary-800)); } + .bg-secondary-900 { background-color: rgb(var(--color-secondary-900)); } + .bg-secondary-950 { background-color: rgb(var(--color-secondary-950)); } + + .text-secondary-50 { color: rgb(var(--color-secondary-50)); } + .text-secondary-100 { color: rgb(var(--color-secondary-100)); } + .text-secondary-200 { color: rgb(var(--color-secondary-200)); } + .text-secondary-300 { color: rgb(var(--color-secondary-300)); } + .text-secondary-400 { color: rgb(var(--color-secondary-400)); } + .text-secondary-500 { color: rgb(var(--color-secondary-500)); } + .text-secondary-600 { color: rgb(var(--color-secondary-600)); } + .text-secondary-700 { color: rgb(var(--color-secondary-700)); } + .text-secondary-800 { color: rgb(var(--color-secondary-800)); } + .text-secondary-900 { color: rgb(var(--color-secondary-900)); } + .text-secondary-950 { color: rgb(var(--color-secondary-950)); } + + .border-secondary-50 { border-color: rgb(var(--color-secondary-50)); } + .border-secondary-100 { border-color: rgb(var(--color-secondary-100)); } + .border-secondary-200 { border-color: rgb(var(--color-secondary-200)); } + .border-secondary-300 { border-color: rgb(var(--color-secondary-300)); } + .border-secondary-400 { border-color: rgb(var(--color-secondary-400)); } + .border-secondary-500 { border-color: rgb(var(--color-secondary-500)); } + .border-secondary-600 { border-color: rgb(var(--color-secondary-600)); } + .border-secondary-700 { border-color: rgb(var(--color-secondary-700)); } + .border-secondary-800 { border-color: rgb(var(--color-secondary-800)); } + .border-secondary-900 { border-color: rgb(var(--color-secondary-900)); } + .border-secondary-950 { border-color: rgb(var(--color-secondary-950)); } + + /* Neutral Colors - Full Range with defaults */ + .bg-neutral-50 { background-color: rgb(var(--color-neutral-50, 250 250 250)); } + .bg-neutral-100 { background-color: rgb(var(--color-neutral-100, 245 245 245)); } + .bg-neutral-200 { background-color: rgb(var(--color-neutral-200, 229 229 229)); } + .bg-neutral-300 { background-color: rgb(var(--color-neutral-300, 212 212 212)); } + .bg-neutral-400 { background-color: rgb(var(--color-neutral-400, 163 163 163)); } + .bg-neutral-500 { background-color: rgb(var(--color-neutral-500, 115 115 115)); } + .bg-neutral-600 { background-color: rgb(var(--color-neutral-600, 82 82 82)); } + .bg-neutral-700 { background-color: rgb(var(--color-neutral-700, 64 64 64)); } + .bg-neutral-800 { background-color: rgb(var(--color-neutral-800, 38 38 38)); } + .bg-neutral-900 { background-color: rgb(var(--color-neutral-900, 23 23 23)); } + .bg-neutral-950 { background-color: rgb(var(--color-neutral-950, 10 10 10)); } + + .text-neutral-50 { color: rgb(var(--color-neutral-50, 250 250 250)); } + .text-neutral-100 { color: rgb(var(--color-neutral-100, 245 245 245)); } + .text-neutral-200 { color: rgb(var(--color-neutral-200, 229 229 229)); } + .text-neutral-300 { color: rgb(var(--color-neutral-300, 212 212 212)); } + .text-neutral-400 { color: rgb(var(--color-neutral-400, 163 163 163)); } + .text-neutral-500 { color: rgb(var(--color-neutral-500, 115 115 115)); } + .text-neutral-600 { color: rgb(var(--color-neutral-600, 82 82 82)); } + .text-neutral-700 { color: rgb(var(--color-neutral-700, 64 64 64)); } + .text-neutral-800 { color: rgb(var(--color-neutral-800, 38 38 38)); } + .text-neutral-900 { color: rgb(var(--color-neutral-900, 23 23 23)); } + .text-neutral-950 { color: rgb(var(--color-neutral-950, 10 10 10)); } + + .border-neutral-50 { border-color: rgb(var(--color-neutral-50, 250 250 250)); } + .border-neutral-100 { border-color: rgb(var(--color-neutral-100, 245 245 245)); } + .border-neutral-200 { border-color: rgb(var(--color-neutral-200, 229 229 229)); } + .border-neutral-300 { border-color: rgb(var(--color-neutral-300, 212 212 212)); } + .border-neutral-400 { border-color: rgb(var(--color-neutral-400, 163 163 163)); } + .border-neutral-500 { border-color: rgb(var(--color-neutral-500, 115 115 115)); } + .border-neutral-600 { border-color: rgb(var(--color-neutral-600, 82 82 82)); } + .border-neutral-700 { border-color: rgb(var(--color-neutral-700, 64 64 64)); } + .border-neutral-800 { border-color: rgb(var(--color-neutral-800, 38 38 38)); } + .border-neutral-900 { border-color: rgb(var(--color-neutral-900, 23 23 23)); } + .border-neutral-950 { border-color: rgb(var(--color-neutral-950, 10 10 10)); } + + /* Hover Variants - Primary */ + .hover\:bg-primary-50:hover { background-color: rgb(var(--color-primary-50)); } + .hover\:bg-primary-100:hover { background-color: rgb(var(--color-primary-100)); } + .hover\:bg-primary-200:hover { background-color: rgb(var(--color-primary-200)); } + .hover\:bg-primary-300:hover { background-color: rgb(var(--color-primary-300)); } + .hover\:bg-primary-400:hover { background-color: rgb(var(--color-primary-400)); } + .hover\:bg-primary-500:hover { background-color: rgb(var(--color-primary-500)); } + .hover\:bg-primary-600:hover { background-color: rgb(var(--color-primary-600)); } + .hover\:bg-primary-700:hover { background-color: rgb(var(--color-primary-700)); } + .hover\:bg-primary-800:hover { background-color: rgb(var(--color-primary-800)); } + .hover\:bg-primary-900:hover { background-color: rgb(var(--color-primary-900)); } + .hover\:bg-primary-950:hover { background-color: rgb(var(--color-primary-950)); } + + .hover\:text-primary-50:hover { color: rgb(var(--color-primary-50)); } + .hover\:text-primary-100:hover { color: rgb(var(--color-primary-100)); } + .hover\:text-primary-200:hover { color: rgb(var(--color-primary-200)); } + .hover\:text-primary-300:hover { color: rgb(var(--color-primary-300)); } + .hover\:text-primary-400:hover { color: rgb(var(--color-primary-400)); } + .hover\:text-primary-500:hover { color: rgb(var(--color-primary-500)); } + .hover\:text-primary-600:hover { color: rgb(var(--color-primary-600)); } + .hover\:text-primary-700:hover { color: rgb(var(--color-primary-700)); } + .hover\:text-primary-800:hover { color: rgb(var(--color-primary-800)); } + .hover\:text-primary-900:hover { color: rgb(var(--color-primary-900)); } + .hover\:text-primary-950:hover { color: rgb(var(--color-primary-950)); } + + /* Hover Variants - Neutral */ + .hover\:bg-neutral-50:hover { background-color: rgb(var(--color-neutral-50)); } + .hover\:bg-neutral-100:hover { background-color: rgb(var(--color-neutral-100)); } + .hover\:bg-neutral-200:hover { background-color: rgb(var(--color-neutral-200)); } + .hover\:bg-neutral-300:hover { background-color: rgb(var(--color-neutral-300)); } + .hover\:bg-neutral-400:hover { background-color: rgb(var(--color-neutral-400)); } + .hover\:bg-neutral-500:hover { background-color: rgb(var(--color-neutral-500)); } + .hover\:bg-neutral-600:hover { background-color: rgb(var(--color-neutral-600)); } + .hover\:bg-neutral-700:hover { background-color: rgb(var(--color-neutral-700)); } + .hover\:bg-neutral-800:hover { background-color: rgb(var(--color-neutral-800)); } + .hover\:bg-neutral-900:hover { background-color: rgb(var(--color-neutral-900)); } + + .hover\:text-neutral-50:hover { color: rgb(var(--color-neutral-50)); } + .hover\:text-neutral-100:hover { color: rgb(var(--color-neutral-100)); } + .hover\:text-neutral-200:hover { color: rgb(var(--color-neutral-200)); } + .hover\:text-neutral-300:hover { color: rgb(var(--color-neutral-300)); } + .hover\:text-neutral-400:hover { color: rgb(var(--color-neutral-400)); } + .hover\:text-neutral-500:hover { color: rgb(var(--color-neutral-500)); } + .hover\:text-neutral-600:hover { color: rgb(var(--color-neutral-600)); } + .hover\:text-neutral-700:hover { color: rgb(var(--color-neutral-700)); } + .hover\:text-neutral-800:hover { color: rgb(var(--color-neutral-800)); } + .hover\:text-neutral-900:hover { color: rgb(var(--color-neutral-900)); } + + /* Dark Mode Variants - Primary */ + .dark\:bg-primary-50:where(.dark, .dark *) { background-color: rgb(var(--color-primary-50)); } + .dark\:bg-primary-100:where(.dark, .dark *) { background-color: rgb(var(--color-primary-100)); } + .dark\:bg-primary-200:where(.dark, .dark *) { background-color: rgb(var(--color-primary-200)); } + .dark\:bg-primary-300:where(.dark, .dark *) { background-color: rgb(var(--color-primary-300)); } + .dark\:bg-primary-400:where(.dark, .dark *) { background-color: rgb(var(--color-primary-400)); } + .dark\:bg-primary-500:where(.dark, .dark *) { background-color: rgb(var(--color-primary-500)); } + .dark\:bg-primary-600:where(.dark, .dark *) { background-color: rgb(var(--color-primary-600)); } + .dark\:bg-primary-700:where(.dark, .dark *) { background-color: rgb(var(--color-primary-700)); } + .dark\:bg-primary-800:where(.dark, .dark *) { background-color: rgb(var(--color-primary-800)); } + .dark\:bg-primary-900:where(.dark, .dark *) { background-color: rgb(var(--color-primary-900)); } + .dark\:bg-primary-950:where(.dark, .dark *) { background-color: rgb(var(--color-primary-950)); } + + .dark\:text-primary-50:where(.dark, .dark *) { color: rgb(var(--color-primary-50)); } + .dark\:text-primary-100:where(.dark, .dark *) { color: rgb(var(--color-primary-100)); } + .dark\:text-primary-200:where(.dark, .dark *) { color: rgb(var(--color-primary-200)); } + .dark\:text-primary-300:where(.dark, .dark *) { color: rgb(var(--color-primary-300)); } + .dark\:text-primary-400:where(.dark, .dark *) { color: rgb(var(--color-primary-400)); } + .dark\:text-primary-500:where(.dark, .dark *) { color: rgb(var(--color-primary-500)); } + .dark\:text-primary-600:where(.dark, .dark *) { color: rgb(var(--color-primary-600)); } + .dark\:text-primary-700:where(.dark, .dark *) { color: rgb(var(--color-primary-700)); } + .dark\:text-primary-800:where(.dark, .dark *) { color: rgb(var(--color-primary-800)); } + .dark\:text-primary-900:where(.dark, .dark *) { color: rgb(var(--color-primary-900)); } + + /* Dark Mode Variants - Neutral */ + .dark\:bg-neutral-50:where(.dark, .dark *) { background-color: rgb(var(--color-neutral-50)); } + .dark\:bg-neutral-100:where(.dark, .dark *) { background-color: rgb(var(--color-neutral-100)); } + .dark\:bg-neutral-200:where(.dark, .dark *) { background-color: rgb(var(--color-neutral-200)); } + .dark\:bg-neutral-300:where(.dark, .dark *) { background-color: rgb(var(--color-neutral-300)); } + .dark\:bg-neutral-400:where(.dark, .dark *) { background-color: rgb(var(--color-neutral-400)); } + .dark\:bg-neutral-500:where(.dark, .dark *) { background-color: rgb(var(--color-neutral-500)); } + .dark\:bg-neutral-600:where(.dark, .dark *) { background-color: rgb(var(--color-neutral-600)); } + .dark\:bg-neutral-700:where(.dark, .dark *) { background-color: rgb(var(--color-neutral-700)); } + .dark\:bg-neutral-800:where(.dark, .dark *) { background-color: rgb(var(--color-neutral-800)); } + .dark\:bg-neutral-900:where(.dark, .dark *) { background-color: rgb(var(--color-neutral-900)); } + .dark\:bg-neutral-950:where(.dark, .dark *) { background-color: rgb(var(--color-neutral-950)); } + + .dark\:text-neutral-50:where(.dark, .dark *) { color: rgb(var(--color-neutral-50)); } + .dark\:text-neutral-100:where(.dark, .dark *) { color: rgb(var(--color-neutral-100)); } + .dark\:text-neutral-200:where(.dark, .dark *) { color: rgb(var(--color-neutral-200)); } + .dark\:text-neutral-300:where(.dark, .dark *) { color: rgb(var(--color-neutral-300)); } + .dark\:text-neutral-400:where(.dark, .dark *) { color: rgb(var(--color-neutral-400)); } + .dark\:text-neutral-500:where(.dark, .dark *) { color: rgb(var(--color-neutral-500)); } + .dark\:text-neutral-600:where(.dark, .dark *) { color: rgb(var(--color-neutral-600)); } + .dark\:text-neutral-700:where(.dark, .dark *) { color: rgb(var(--color-neutral-700)); } + .dark\:text-neutral-800:where(.dark, .dark *) { color: rgb(var(--color-neutral-800)); } + .dark\:text-neutral-900:where(.dark, .dark *) { color: rgb(var(--color-neutral-900)); } + + /* Dark Hover Variants - Primary */ + .dark\:hover\:bg-primary-50:where(.dark, .dark *):hover { background-color: rgb(var(--color-primary-50)); } + .dark\:hover\:bg-primary-100:where(.dark, .dark *):hover { background-color: rgb(var(--color-primary-100)); } + .dark\:hover\:bg-primary-200:where(.dark, .dark *):hover { background-color: rgb(var(--color-primary-200)); } + .dark\:hover\:bg-primary-300:where(.dark, .dark *):hover { background-color: rgb(var(--color-primary-300)); } + .dark\:hover\:bg-primary-400:where(.dark, .dark *):hover { background-color: rgb(var(--color-primary-400)); } + .dark\:hover\:bg-primary-500:where(.dark, .dark *):hover { background-color: rgb(var(--color-primary-500)); } + .dark\:hover\:bg-primary-600:where(.dark, .dark *):hover { background-color: rgb(var(--color-primary-600)); } + .dark\:hover\:bg-primary-700:where(.dark, .dark *):hover { background-color: rgb(var(--color-primary-700)); } + .dark\:hover\:bg-primary-800:where(.dark, .dark *):hover { background-color: rgb(var(--color-primary-800)); } + .dark\:hover\:bg-primary-900:where(.dark, .dark *):hover { background-color: rgb(var(--color-primary-900)); } + + .dark\:hover\:text-primary-100:where(.dark, .dark *):hover { color: rgb(var(--color-primary-100)); } + .dark\:hover\:text-primary-200:where(.dark, .dark *):hover { color: rgb(var(--color-primary-200)); } + .dark\:hover\:text-primary-300:where(.dark, .dark *):hover { color: rgb(var(--color-primary-300)); } + .dark\:hover\:text-primary-400:where(.dark, .dark *):hover { color: rgb(var(--color-primary-400)); } + .dark\:hover\:text-primary-500:where(.dark, .dark *):hover { color: rgb(var(--color-primary-500)); } + + /* Dark Hover Variants - Neutral */ + .dark\:hover\:text-neutral-100:where(.dark, .dark *):hover { color: rgb(var(--color-neutral-100)); } + .dark\:hover\:text-neutral-200:where(.dark, .dark *):hover { color: rgb(var(--color-neutral-200)); } + .dark\:hover\:text-neutral-300:where(.dark, .dark *):hover { color: rgb(var(--color-neutral-300)); } + .dark\:hover\:text-neutral-400:where(.dark, .dark *):hover { color: rgb(var(--color-neutral-400)); } + .dark\:hover\:text-neutral-500:where(.dark, .dark *):hover { color: rgb(var(--color-neutral-500)); } + .dark\:hover\:text-neutral-600:where(.dark, .dark *):hover { color: rgb(var(--color-neutral-600)); } + .dark\:hover\:text-neutral-700:where(.dark, .dark *):hover { color: rgb(var(--color-neutral-700)); } + .dark\:hover\:text-neutral-800:where(.dark, .dark *):hover { color: rgb(var(--color-neutral-800)); } + + /* Focus Ring Colors */ + .focus\:ring-primary-50:focus { --tw-ring-color: rgb(var(--color-primary-50)); } + .focus\:ring-primary-100:focus { --tw-ring-color: rgb(var(--color-primary-100)); } + .focus\:ring-primary-200:focus { --tw-ring-color: rgb(var(--color-primary-200)); } + .focus\:ring-primary-300:focus { --tw-ring-color: rgb(var(--color-primary-300)); } + .focus\:ring-primary-400:focus { --tw-ring-color: rgb(var(--color-primary-400)); } + .focus\:ring-primary-500:focus { --tw-ring-color: rgb(var(--color-primary-500)); } + .focus\:ring-primary-600:focus { --tw-ring-color: rgb(var(--color-primary-600)); } + .focus\:ring-primary-700:focus { --tw-ring-color: rgb(var(--color-primary-700)); } + .focus\:ring-primary-800:focus { --tw-ring-color: rgb(var(--color-primary-800)); } + .focus\:ring-primary-900:focus { --tw-ring-color: rgb(var(--color-primary-900)); } + + .dark\:focus\:ring-primary-300:where(.dark, .dark *):focus { --tw-ring-color: rgb(var(--color-primary-300)); } + .dark\:focus\:ring-primary-400:where(.dark, .dark *):focus { --tw-ring-color: rgb(var(--color-primary-400)); } + .dark\:focus\:ring-primary-500:where(.dark, .dark *):focus { --tw-ring-color: rgb(var(--color-primary-500)); } + .dark\:focus\:ring-primary-600:where(.dark, .dark *):focus { --tw-ring-color: rgb(var(--color-primary-600)); } + .dark\:focus\:ring-primary-700:where(.dark, .dark *):focus { --tw-ring-color: rgb(var(--color-primary-700)); } + .dark\:focus\:ring-primary-800:where(.dark, .dark *):focus { --tw-ring-color: rgb(var(--color-primary-800)); } + + /* Gradient utilities */ + .from-primary-50 { --tw-gradient-from: rgb(var(--color-primary-50)) var(--tw-gradient-from-position); } + .from-primary-100 { --tw-gradient-from: rgb(var(--color-primary-100)) var(--tw-gradient-from-position); } + .from-primary-200 { --tw-gradient-from: rgb(var(--color-primary-200)) var(--tw-gradient-from-position); } + .from-primary-300 { --tw-gradient-from: rgb(var(--color-primary-300)) var(--tw-gradient-from-position); } + .from-primary-400 { --tw-gradient-from: rgb(var(--color-primary-400)) var(--tw-gradient-from-position); } + .from-primary-500 { --tw-gradient-from: rgb(var(--color-primary-500)) var(--tw-gradient-from-position); } + .from-primary-600 { --tw-gradient-from: rgb(var(--color-primary-600)) var(--tw-gradient-from-position); } + .from-primary-700 { --tw-gradient-from: rgb(var(--color-primary-700)) var(--tw-gradient-from-position); } + .from-primary-800 { --tw-gradient-from: rgb(var(--color-primary-800)) var(--tw-gradient-from-position); } + .from-primary-900 { --tw-gradient-from: rgb(var(--color-primary-900)) var(--tw-gradient-from-position); } + + .to-primary-50 { --tw-gradient-to: rgb(var(--color-primary-50)) var(--tw-gradient-to-position); } + .to-primary-100 { --tw-gradient-to: rgb(var(--color-primary-100)) var(--tw-gradient-to-position); } + .to-primary-200 { --tw-gradient-to: rgb(var(--color-primary-200)) var(--tw-gradient-to-position); } + .to-primary-300 { --tw-gradient-to: rgb(var(--color-primary-300)) var(--tw-gradient-to-position); } + .to-primary-400 { --tw-gradient-to: rgb(var(--color-primary-400)) var(--tw-gradient-to-position); } + .to-primary-500 { --tw-gradient-to: rgb(var(--color-primary-500)) var(--tw-gradient-to-position); } + .to-primary-600 { --tw-gradient-to: rgb(var(--color-primary-600)) var(--tw-gradient-to-position); } + .to-primary-700 { --tw-gradient-to: rgb(var(--color-primary-700)) var(--tw-gradient-to-position); } + .to-primary-800 { --tw-gradient-to: rgb(var(--color-primary-800)) var(--tw-gradient-to-position); } + .to-primary-900 { --tw-gradient-to: rgb(var(--color-primary-900)) var(--tw-gradient-to-position); } + + /* Special HB dark color */ + .bg-hb-dark { background-color: rgb(var(--color-hb-dark, 23 24 28)); } + .text-hb-dark { color: rgb(var(--color-hb-dark, 23 24 28)); } +} diff --git a/modules/blox-tailwind/assets/css/components/cards.css b/modules/blox-tailwind/assets/css/components/cards.css index 30cde72a..794e600f 100644 --- a/modules/blox-tailwind/assets/css/components/cards.css +++ b/modules/blox-tailwind/assets/css/components/cards.css @@ -9,11 +9,34 @@ .hb-card { @apply flex flex-col justify-start overflow-hidden rounded-lg border border-gray-200 text-current no-underline dark:shadow-none hover:shadow-gray-100 dark:hover:shadow-none shadow-gray-100 active:shadow-sm active:shadow-gray-200 transition-all duration-200; - @apply hover:border-gray-300 bg-transparent shadow-sm dark:border-neutral-700 hover:bg-slate-50 hover:shadow-md dark:hover:border-neutral-600 dark:hover:bg-neutral-800; + @apply hover:border-gray-300 bg-transparent shadow-sm hover:bg-slate-50 hover:shadow-md; + border-color: rgb(var(--color-neutral-700)); +} + +.dark .hb-card { + border-color: rgb(var(--color-neutral-700)); +} + +.dark .hb-card:hover { + border-color: rgb(var(--color-neutral-600)); + background-color: rgb(var(--color-neutral-800)); } .hb-card-title { - @apply flex font-semibold items-start gap-2 text-gray-700 hover:text-gray-900 dark:text-neutral-200 dark:hover:text-neutral-50 items-center; + @apply flex font-semibold items-start gap-2 text-gray-700 hover:text-gray-900 items-center; + color: rgb(var(--color-neutral-700)); +} + +.hb-card-title:hover { + color: rgb(var(--color-neutral-900)); +} + +.dark .hb-card-title { + color: rgb(var(--color-neutral-200)); +} + +.dark .hb-card-title:hover { + color: rgb(var(--color-neutral-50)); } .hb-card-subtitle { @@ -25,8 +48,7 @@ } .hb-card svg { - @apply text-neutral-700; - + color: rgb(var(--color-neutral-700)); width: 1.5rem; transition: color 0.3s ease; } @@ -36,7 +58,7 @@ } .dark .hb-card svg { - @apply text-neutral-300; + color: rgb(var(--color-neutral-300)); } .dark .hb-card:hover svg { diff --git a/modules/blox-tailwind/assets/css/components/copy.css b/modules/blox-tailwind/assets/css/components/copy.css index f115c368..c6e92bfa 100644 --- a/modules/blox-tailwind/assets/css/components/copy.css +++ b/modules/blox-tailwind/assets/css/components/copy.css @@ -24,5 +24,12 @@ .copy-button:focus, .copy-button:active, .copy-button:active:hover { - @apply bg-primary-100 dark:bg-primary-600; + background-color: rgb(var(--color-primary-100)); +} + +.dark .copy-button:hover, +.dark .copy-button:focus, +.dark .copy-button:active, +.dark .copy-button:active:hover { + background-color: rgb(var(--color-primary-600)); } diff --git a/modules/blox-tailwind/assets/css/components/page.css b/modules/blox-tailwind/assets/css/components/page.css index 290695d5..76f464f4 100644 --- a/modules/blox-tailwind/assets/css/components/page.css +++ b/modules/blox-tailwind/assets/css/components/page.css @@ -87,5 +87,10 @@ /* For ToC shortcode, Spoiler shortcode, and direct HTML Details snippets. */ details > summary { - @apply cursor-pointer font-semibold text-primary-700 dark:text-primary-300; + @apply cursor-pointer font-semibold; + color: rgb(var(--color-primary-700)); +} + +.dark details > summary { + color: rgb(var(--color-primary-300)); } diff --git a/modules/blox-tailwind/assets/css/components/sidebar-left.css b/modules/blox-tailwind/assets/css/components/sidebar-left.css index 085788f2..d48a4183 100644 --- a/modules/blox-tailwind/assets/css/components/sidebar-left.css +++ b/modules/blox-tailwind/assets/css/components/sidebar-left.css @@ -27,7 +27,15 @@ } .hb-sidebar-list { - @apply relative flex flex-col gap-1 before:absolute before:inset-y-1 before:w-px before:bg-gray-200 before:content-[""] ltr:ml-3 ltr:pl-3 ltr:before:left-0 rtl:mr-3 rtl:pr-3 rtl:before:right-0 dark:before:bg-neutral-700; + @apply relative flex flex-col gap-1 before:absolute before:inset-y-1 before:w-px before:bg-gray-200 before:content-[""] ltr:ml-3 ltr:pl-3 ltr:before:left-0 rtl:mr-3 rtl:pr-3 rtl:before:right-0; +} + +.hb-sidebar-list::before { + background-color: rgb(var(--color-neutral-200)); +} + +.dark .hb-sidebar-list::before { + background-color: rgb(var(--color-neutral-700)); } .hb-scrollbar { @@ -58,7 +66,11 @@ } .hb-docs-link { - @apply flex rounded px-2 py-1.5 text-sm transition-colors [word-break:break-word] cursor-pointer [-webkit-tap-highlight-color:transparent] [-webkit-touch-callout:none] gap-2 before:opacity-25 before:content-['#'] text-gray-500 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-300 dark:hover:bg-primary-100/5 dark:hover:text-gray-50; + @apply flex rounded px-2 py-1.5 text-sm transition-colors [word-break:break-word] cursor-pointer [-webkit-tap-highlight-color:transparent] [-webkit-touch-callout:none] gap-2 before:opacity-25 before:content-['#'] text-gray-500 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-300 dark:hover:text-gray-50; +} + +.dark .hb-docs-link:hover { + background-color: rgb(var(--color-primary-100) / 0.05); } .hb-sidebar-mobile-menu { @@ -66,7 +78,15 @@ } .hb-sidebar-mobile-toc { - @apply flex flex-col gap-1 relative before:absolute before:inset-y-1 before:w-px before:bg-gray-200 before:content-[""] dark:before:bg-neutral-800 ltr:pl-3 ltr:before:left-0 rtl:pr-3 rtl:before:right-0 ltr:ml-3 rtl:mr-3; + @apply flex flex-col gap-1 relative before:absolute before:inset-y-1 before:w-px before:bg-gray-200 before:content-[""] ltr:pl-3 ltr:before:left-0 rtl:pr-3 rtl:before:right-0 ltr:ml-3 rtl:mr-3; +} + +.hb-sidebar-mobile-toc::before { + background-color: rgb(var(--color-neutral-200)); +} + +.dark .hb-sidebar-mobile-toc::before { + background-color: rgb(var(--color-neutral-800)); } .hb-sidebar-custom-link { diff --git a/modules/blox-tailwind/assets/css/components/steps.css b/modules/blox-tailwind/assets/css/components/steps.css index b643633b..4e41a065 100644 --- a/modules/blox-tailwind/assets/css/components/steps.css +++ b/modules/blox-tailwind/assets/css/components/steps.css @@ -1,5 +1,10 @@ .hb-steps { - @apply ml-4 mb-12 pl-6 border-l border-gray-200 dark:border-neutral-600 [counter-reset:hb_step]; + @apply ml-4 mb-12 pl-6 border-l border-gray-200 [counter-reset:hb_step]; + border-left-color: rgb(var(--color-neutral-200)); +} + +.dark .hb-steps { + border-left-color: rgb(var(--color-neutral-600)); } .hb-steps h3 { @@ -9,9 +14,14 @@ @apply absolute w-[33px] h-[33px]; @apply rounded-full border-4 border-white dark:border-slate-300; @apply bg-gray-100 dark:bg-hb-dark; - @apply text-neutral-700 dark:text-neutral-200 text-base font-normal text-center -indent-px; + @apply text-base font-normal text-center -indent-px; @apply mt-[3px] ml-[-41px]; + color: rgb(var(--color-neutral-700)); content: counter(hb-step); } } + +.dark .hb-steps h3::before { + color: rgb(var(--color-neutral-200)); +} diff --git a/modules/blox-tailwind/assets/css/config/safelist.css b/modules/blox-tailwind/assets/css/config/safelist.css new file mode 100644 index 00000000..ae2bde33 --- /dev/null +++ b/modules/blox-tailwind/assets/css/config/safelist.css @@ -0,0 +1,5 @@ +/* Safelist patterns for dynamic classes */ +/* Note: In v4, we use @source inline to ensure these are included */ +/* This ensures Tailwind generates these classes even if not found in templates */ + +@source inline("
"); diff --git a/modules/blox-tailwind/assets/css/config/tailwind.css b/modules/blox-tailwind/assets/css/config/tailwind.css new file mode 100644 index 00000000..8ab76d59 --- /dev/null +++ b/modules/blox-tailwind/assets/css/config/tailwind.css @@ -0,0 +1,25 @@ +/* Tailwind CSS v4 Configuration */ +/* Content detection and plugin configuration */ + +/* Typography plugin for prose styles */ +@plugin "@tailwindcss/typography"; + +/* Content detection sources */ +/* Note: @source is a Tailwind v4 directive - linters may show warnings that can be ignored */ +@source "hugo_stats.json"; +@source "../../layouts/**/*.html"; +@source "../../assets/**/*.{js,css}"; + +/* Custom Variants Configuration */ +/* Configure dark mode to use class strategy */ +@custom-variant dark (&:where(.dark, .dark *)); + +/* Configure hover to work on all devices (like v3 behavior) */ +@custom-variant hover (&:hover); + +/* Dark mode configuration */ +@media (prefers-color-scheme: dark) { + :root { + color-scheme: dark; + } +} diff --git a/modules/blox-tailwind/assets/css/config/theme.css b/modules/blox-tailwind/assets/css/config/theme.css new file mode 100644 index 00000000..a005f585 --- /dev/null +++ b/modules/blox-tailwind/assets/css/config/theme.css @@ -0,0 +1,61 @@ +/* Tailwind CSS v4 Hugo BloxTheme Configuration */ + +/* Theme Configuration */ +@theme { + /* Custom Colors */ + --color-hb-dark: 23 24 28; + + /* Neutral Colors - Space-separated RGB values (for use with rgb() function) */ + --color-neutral-50: 250 250 250; + --color-neutral-100: 245 245 245; + --color-neutral-200: 229 229 229; + --color-neutral-300: 212 212 212; + --color-neutral-400: 163 163 163; + --color-neutral-500: 115 115 115; + --color-neutral-600: 82 82 82; + --color-neutral-700: 64 64 64; + --color-neutral-800: 38 38 38; + --color-neutral-900: 23 23 23; + --color-neutral-950: 10 10 10; + + /* Primary Colors - Space-separated RGB values (Blue defaults) */ + --color-primary-50: 239 246 255; + --color-primary-100: 219 234 254; + --color-primary-200: 191 219 254; + --color-primary-300: 147 197 253; + --color-primary-400: 96 165 250; + --color-primary-500: 59 130 246; + --color-primary-600: 37 99 235; + --color-primary-700: 29 78 216; + --color-primary-800: 30 64 175; + --color-primary-900: 30 58 138; + --color-primary-950: 23 37 84; + + /* Secondary Colors - Space-separated RGB values (Cyan defaults) */ + --color-secondary-50: 236 254 255; + --color-secondary-100: 207 250 254; + --color-secondary-200: 165 243 252; + --color-secondary-300: 103 232 249; + --color-secondary-400: 34 211 238; + --color-secondary-500: 6 182 212; + --color-secondary-600: 8 145 178; + --color-secondary-700: 14 116 144; + --color-secondary-800: 21 94 117; + --color-secondary-900: 22 78 99; + --color-secondary-950: 8 51 68; + + /* Font family */ + --font-family-sans: Inter var, ui-sans-serif, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji; + + /* Font sizes */ + --font-size-xs: 0.75rem; + --font-size-sm: 0.875rem; + --font-size-base: 1rem; + --font-size-lg: 1.125rem; + --font-size-xl: 1.25rem; + --font-size-2xl: 1.5rem; + --font-size-3xl: 1.875rem; + --font-size-4xl: 2.25rem; + --font-size-5xl: 3rem; + --font-size-6xl: 4rem; +} diff --git a/modules/blox-tailwind/assets/css/framework/base.css b/modules/blox-tailwind/assets/css/framework/base.css new file mode 100644 index 00000000..77446233 --- /dev/null +++ b/modules/blox-tailwind/assets/css/framework/base.css @@ -0,0 +1,54 @@ +/* Base styles for better text rendering */ +@layer base { + html { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-rendering: optimizeLegibility; + } + + body { + line-height: 1.5; + } +} + +/* Custom utilities and components */ +@utility task-list { + list-style: none; + padding-left: 1.5rem; +} + +/* Custom typography styles - the plugin handles the base styles */ +/* Additional customization for prose elements */ +@layer components { + .prose a { + text-decoration: underline; + text-decoration-color: rgb(var(--color-primary-300)); + font-weight: 500; + } + + .prose a:hover { + color: rgb(var(--color-primary-600)); + text-decoration: none; + border-radius: 0.09rem; + } + + .prose mark { + color: rgb(var(--color-neutral-900)); + background-color: rgb(var(--color-primary-200)); + padding: 0.1rem 0.2rem; + border-radius: 0.25rem; + } + + .dark .prose-invert a { + text-decoration-color: rgb(var(--color-neutral-500)); + } + + .dark .prose-invert a:hover { + color: rgb(var(--color-primary-300)); + } + + .dark .prose-invert mark { + background-color: rgb(var(--color-primary-400)); + color: black; + } +} diff --git a/modules/blox-tailwind/assets/css/framework/components.css b/modules/blox-tailwind/assets/css/framework/components.css new file mode 100644 index 00000000..0fe375dd --- /dev/null +++ b/modules/blox-tailwind/assets/css/framework/components.css @@ -0,0 +1,110 @@ +/* Hugo Blox Framework Custom Classes */ +@layer components { + /* Section styles for Hugo Blox blocks */ + .hbb-section { + padding-top: 6rem; + padding-bottom: 6rem; + } + + .section-subheading { + font-size: 1.25rem; + font-weight: 700; + } + + /* Home section background styles */ + .home-section-bg { + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + z-index: -1; + } + + .home-section-bg.bg-image { + background-position: center; + background-repeat: no-repeat; + background-size: cover; + } + + /* Video background */ + .bg-video { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + object-fit: cover; + object-position: center center; + opacity: 1; + } + + /* Flip video horizontally */ + .bg-video.flip { + transform: scaleX(-1); + } + + /* Container styles */ + .universal-wrapper { + margin: 0 auto; + padding-right: 1rem; + padding-left: 1rem; + width: 100%; + } + + @media (min-width: 1200px) { + .universal-wrapper { + max-width: 1200px; + } + } + + .article-container { + max-width: 760px; + margin: 0 auto; + } + + /* Button toolbar */ + .btn-toolbar { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 0.5rem; + } + + /* Documentation specific */ + .docs-article-container { + max-width: 760px; + } + + /* Powered-by footer styles */ + .powered-by { + font-size: 0.75rem; + } + + .powered-by a { + color: inherit; + text-decoration: none; + } + + .powered-by a:hover { + text-decoration: underline; + } + + /* Parallax effect */ + .parallax { + background-attachment: fixed; + background-position: center; + background-repeat: no-repeat; + background-size: cover; + position: relative; + } + + /* Section color schemes - for backward compatibility */ + section.light { + background-color: transparent; + } + + section.dark { + background-color: transparent; + } +} diff --git a/modules/blox-tailwind/assets/css/main.css b/modules/blox-tailwind/assets/css/main.css index a61460cc..a02cf06e 100644 --- a/modules/blox-tailwind/assets/css/main.css +++ b/modules/blox-tailwind/assets/css/main.css @@ -1,79 +1,36 @@ -:root { - /* TW Neutral */ - --color-neutral-50: 250 250 250; - --color-neutral-100: 245 245 245; - --color-neutral-200: 229 229 229; - --color-neutral-300: 212 212 212; - --color-neutral-400: 163 163 163; - --color-neutral-500: 115 115 115; - --color-neutral-600: 82 82 82; - --color-neutral-700: 64 64 64; - --color-neutral-800: 38 38 38; - --color-neutral-900: 23 23 23; - --color-neutral-950: 10 10 10; - - /* TW Zinc */ - --color-secondary-50: 250 250 250; - --color-secondary-100: 244 244 245; - --color-secondary-200: 228 228 231; - --color-secondary-300: 212 212 216; - --color-secondary-400: 161 161 170; - --color-secondary-500: 113 113 122; - --color-secondary-600: 82 82 91; - --color-secondary-700: 63 63 70; - --color-secondary-800: 39 39 42; - --color-secondary-900: 24 24 27; - --color-secondary-950: 9 9 11; -} - -.hbb-section { - @apply py-24; /* last:mb-0 */ -} - -.section-subheading { - @apply font-bold text-xl; -} - -/* Fill padding of `.home-section` parent */ - .home-section-bg { - position: absolute; - top: 0; - left: 0; - height: 100%; /* Or fill-available when supported. */ - width: 100%; /* Or fill-available when supported. */ - z-index: -1; /* Place bg div behind content. */ - } - -/* Default background image properties for home sections. */ -.home-section-bg.bg-image { - background-position: center; - background-repeat: no-repeat; - background-size: cover; -} - -.bg-video { - position: absolute; - top: 0; - max-height: initial; /* Override general `video` selector's max-height. */ -} - -.bg-video.flip { - transform: rotateY(180deg); -} - -/* Create a parallax-like scrolling effect on desktop browsers. */ -.parallax { - background-attachment: fixed; -} - -/* Workaround issue with mobile browser support for fixed parallax background. -@include media-breakpoint-down(md) { - .parallax { - background-attachment: scroll; - } -} +/* + Hugo Blox Tailwind CSS v4 - Main Entry Point + + This file orchestrates all CSS imports in the correct order: + 1. Tailwind base with configuration + 2. Theme and color definitions + 3. Base styles and utilities + 4. Hugo Blox framework components + 5. Hugo Blox module components + 6. Safelist for dynamic classes */ -.powered-by a { - @apply underline text-blue-600 hover:text-blue-800 dark:text-blue-300 dark:hover:text-blue-200; -} +/* Tailwind CSS v4 Base */ +@import "tailwindcss"; + +/* Configuration */ +@import "./config/tailwind.css"; +@import "./config/theme.css"; + +/* Base styles and utilities */ +@import "./framework/base.css"; + +/* Hugo Blox theme system (color utilities) */ +@import "./color-utilities.css"; + +/* Hugo Blox framework components */ +@import "./framework/components.css"; + +/* Hugo Blox module components */ +@import "./components/all.css"; +@import "./blox/all.css"; +@import "./views/attachments.css"; +@import "chroma.css"; + +/* Safelist for dynamic classes */ +@import "./config/safelist.css"; \ No newline at end of file diff --git a/modules/blox-tailwind/assets/css/styles.css b/modules/blox-tailwind/assets/css/styles.css deleted file mode 100644 index 22997225..00000000 --- a/modules/blox-tailwind/assets/css/styles.css +++ /dev/null @@ -1,9 +0,0 @@ -/* Import Tailwind */ -@import "./tailwind.css"; - -/*! Hugo Blox Components | https://hugoblox.com */ -@import "main.css"; -@import "./components/all.css"; -@import "./blox/all.css"; -@import "./views/attachments.css"; -@import "chroma.css"; diff --git a/modules/blox-tailwind/assets/css/tailwind.css b/modules/blox-tailwind/assets/css/tailwind.css deleted file mode 100644 index b5c61c95..00000000 --- a/modules/blox-tailwind/assets/css/tailwind.css +++ /dev/null @@ -1,3 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; diff --git a/modules/blox-tailwind/assets/css/views/attachments.css b/modules/blox-tailwind/assets/css/views/attachments.css index cbb3a608..60dcfdf9 100644 --- a/modules/blox-tailwind/assets/css/views/attachments.css +++ b/modules/blox-tailwind/assets/css/views/attachments.css @@ -1,11 +1,27 @@ .hb-attachment-link { - @apply inline-block text-primary-600 dark:text-primary-400 font-bold uppercase outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150; + @apply inline-block font-semibold uppercase outline-none mr-4 mb-1.5 transition-all text-sm tracking-wide focus:outline-none; + color: rgb(var(--color-primary-600)); } +.hb-attachment-link:hover { + color: rgb(var(--color-primary-700)); + text-decoration: underline; +} + +.dark .hb-attachment-link { + color: rgb(var(--color-primary-400)); +} + +.dark .hb-attachment-link:hover { + color: rgb(var(--color-primary-300)); +} + +/* Small links - used in list views */ .hb-attachment-link-small { - @apply px-3 py-1 text-xs; + @apply p-0 text-xs; } +/* Large links - used on single pages */ .hb-attachment-link-large { - @apply px-8 py-3; + @apply p-0 text-sm; } diff --git a/modules/blox-tailwind/hugo.yaml b/modules/blox-tailwind/hugo.yaml index fbb27354..a87d7463 100644 --- a/modules/blox-tailwind/hugo.yaml +++ b/modules/blox-tailwind/hugo.yaml @@ -1,3 +1,12 @@ +build: + buildStats: + enable: true + cachebusters: + - source: assets/notwatching/hugo_stats\.json + target: css + - source: (postcss|tailwind)\.config\.js + target: css + markup: defaultMarkdownHandler: goldmark goldmark: @@ -77,6 +86,9 @@ module: target: i18n - source: archetypes target: archetypes + - disableWatch: true + source: hugo_stats.json + target: assets/notwatching/hugo_stats.json security: funcs: getenv: diff --git a/modules/blox-tailwind/layouts/_partials/components/headers/floating-theme-toggler.html b/modules/blox-tailwind/layouts/_partials/components/headers/floating-theme-toggler.html index 967a6936..fcd8d524 100644 --- a/modules/blox-tailwind/layouts/_partials/components/headers/floating-theme-toggler.html +++ b/modules/blox-tailwind/layouts/_partials/components/headers/floating-theme-toggler.html @@ -3,12 +3,12 @@