diff --git a/CHANGELOG.md b/CHANGELOG.md index 06cfedf3..95fd82af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,47 +1,89 @@ -## next / unreleased +# `tailwindcss-rails` Changelog -## v4.0.0.rc2 / 2025-01-26 +## v4.3.0.rc2 -Everything in v4.0.0.rc1, plus ... +### Improved -General changes: +* Experimental support for Rails engines. Feedback is welcome at #355. #554, #556 @bopm -- The location of `application.tailwind.css` has moved from `app/assets/stylesheets` to `app/assets/tailwind`. If Propshaft is being used, `app/assets/tailwind` will be excluded from its asset handling. -Changes to the `tailwindcss:install` task: +## v4.2.3 / 2025-05-02 -- The "tailwind" stylesheet link tag will only be added to the application layout if Propshaft isn't in use and already handling `app/assets/build/tailwind.css`. Previously it was always injected, resulting in the tag being rendered twice if Propshaft was in use. +### Improved -Changes to the `tailwindcss:upgrade` task: +* The "tailwindcss:upgrade" task now pins to v4.1.4 of the `@tailwindcss/upgrade` tool. #544 @flavorjones + + +## v4.2.2 / 2025-04-05 + +### Improved + +* The "tailwindcss:upgrade" task now uses the latest version of the `@tailwindcss/upgrade` tool. #529 @flavorjones +* The "verbose" flag on Rails tasks now emits additional tailwind CLI debugging info (e.g., `bin/rails tailwindcss:build[verbose]`). #530 @flavorjones +* Simplified the scaffold templates, removing unnecessary `div` tags. @523 @patriciomacadden + + +## v4.2.1 / 2025-03-19 + +### Fixed + +* Fix styles for form errors in some scaffold fields. #513 @patriciomacadden +* Update scaffold system tests to handle the "Destroy" confirmation prompt when Turbo is enabled. Fixes #519. #520 @patriciomacadden @flavorjones -- The "tailwind" stylesheet link tag will be removed if Propshaft is in use and already handling `app/assets/build/tailwind.css`. -- The file `application.tailwind.css` will be moved from `app/assets/stylesheets` to `app/assets/tailwind`. +## v4.2.0 / 2025-03-02 -## v4.0.0.rc1 / 2025-01-23 +### Features + +* Improve the view templates to display better on mobile devices. #503 @patriciomacadden +* Support for environment variable `TAILWINDCSS_DEBUG` to turn off CSS minification. #504 @r-sierra + + +## v4.1.0 / 2025-02-19 + +### View template improvements + +* Field outlines are no longer hidden, and the focus border is brighter. #489 @rubys +* Boolean fields are improved (checkbox labels aligned, "Yes"/"No" instead of "true"/"false"). #454 @patriciomacadden +* Attachment links are consistently spaced and styled. #460 @patriciomacadden +* Index page links to Show, Edit, and Destroy for each resource. #460 @patriciomacadden @flavorjones +* Turbo confirm prompt added to Destroy links. #498 @patriciomacadden + + +## v4.0.0 / 2025-02-01 ### Upgrade to Tailwind CSS v4 General changes: -- Dependency on `tailwindcss-ruby` set to `~> 4.0`. +- The dependency on `tailwindcss-ruby` is set to `~> 4.0`. - The location of (optional) `postcss.config.js` has moved from the `config/` directory to the app root. +- The input file `app/assets/tailwind/application.tailwind.css` has been renamed to `app/assets/tailwind/application.css`. +- If Propshaft is being used, `app/assets/tailwind` will be excluded from its asset handling. +- The Inter font is no longer packaged with the gem. +- Some Tailwind class names in the generated ERB templates are updated for v4. +- The README is updated to contain verbose instructions on upgrading. Changes to the `tailwindcss:install` task: -- The `tailwindcss:install` task no longer installs `config/tailwind.config.js`. -- The Inter font is no longer packaged with the gem. -- Some Tailwind class names are updated for v4. +- The `tailwindcss:install` task no longer installs `config/tailwind.config.js`, as v4 recommends placing Tailwind configuration in the CSS file. +- The Inter font is no longer configured in the application layout. +- The "tailwind" stylesheet link tag will only be added to the application layout if Propshaft isn't in use and therefore already handling `app/assets/build/tailwind.css`. Previously it was always injected, resulting in the tag being rendered twice if Propshaft was in use. New task `tailwindcss:upgrade` upgrades many apps cleanly: -- Cleans up some things in the generated `config/tailwind.config.js`. +- Cleans up `config/tailwind.config.js` and references it from the CSS file as recommended for v4 upgrades. - Runs the upstream upgrader (note: requires `npx` to run the one-time upgrade, but highly recommended). -- Removes references to the Inter font from the application layout. +- Removes configuration for the Inter font from the application layout. - If present, moves `config/postcss.config.js` to the root directory. +- The "tailwind" stylesheet link tag will be removed if Propshaft is in use and already handling `app/assets/build/tailwind.css`. +- The input file `app/assets/tailwind/application.tailwind.css` will be moved to `app/assets/tailwind/application.css`. + +Thanks to @EricGusmao, @patriciomacadden, @excid3, and @brunoprietog for their feedback, contributions, and advice on v4 support. -Thanks to @EricGusmao and @excid3 for their help and advice on this work. +### Other changes +- The gem's Rails generators are now hidden in the `rails g --help` output. #483 @patriciomacadden ## v3.3.1 / 2025-01-23 diff --git a/Gemfile.lock b/Gemfile.lock index 91f050ca..dc9444f1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,23 +1,23 @@ PATH remote: . specs: - tailwindcss-rails (4.0.0.rc2) + tailwindcss-rails (4.3.0.rc1) railties (>= 7.0.0) tailwindcss-ruby (~> 4.0) GEM remote: https://rubygems.org/ specs: - actionmailer (8.0.1) - actionpack (= 8.0.1) - actionview (= 8.0.1) - activejob (= 8.0.1) - activesupport (= 8.0.1) + actionmailer (8.0.2) + actionpack (= 8.0.2) + actionview (= 8.0.2) + activejob (= 8.0.2) + activesupport (= 8.0.2) mail (>= 2.8.0) rails-dom-testing (~> 2.2) - actionpack (8.0.1) - actionview (= 8.0.1) - activesupport (= 8.0.1) + actionpack (8.0.2) + actionview (= 8.0.2) + activesupport (= 8.0.2) nokogiri (>= 1.8.5) rack (>= 2.2.4) rack-session (>= 1.0.1) @@ -25,16 +25,16 @@ GEM rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) useragent (~> 0.16) - actionview (8.0.1) - activesupport (= 8.0.1) + actionview (8.0.2) + activesupport (= 8.0.2) builder (~> 3.1) erubi (~> 1.11) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - activejob (8.0.1) - activesupport (= 8.0.1) + activejob (8.0.2) + activesupport (= 8.0.2) globalid (>= 0.3.6) - activesupport (8.0.1) + activesupport (8.0.2) base64 benchmark (>= 0.3) bigdecimal @@ -65,11 +65,11 @@ GEM i18n (1.14.7) concurrent-ruby (~> 1.0) io-console (0.8.0) - irb (1.15.0) + irb (1.15.1) pp (>= 0.6.0) rdoc (>= 4.0.0) reline (>= 0.4.2) - logger (1.6.5) + logger (1.6.6) loofah (2.24.0) crass (~> 1.0.2) nokogiri (>= 1.12.0) @@ -80,28 +80,28 @@ GEM net-smtp mini_mime (1.1.5) mini_portile2 (2.8.8) - minitest (5.25.4) - net-imap (0.5.5) + minitest (5.25.5) + net-imap (0.5.6) date net-protocol net-pop (0.1.2) net-protocol net-protocol (0.2.2) timeout - net-smtp (0.5.0) + net-smtp (0.5.1) net-protocol - nokogiri (1.18.2) + nokogiri (1.18.4) mini_portile2 (~> 2.8.2) racc (~> 1.4) - nokogiri (1.18.2-aarch64-linux-gnu) + nokogiri (1.18.4-aarch64-linux-gnu) racc (~> 1.4) - nokogiri (1.18.2-arm-linux-gnu) + nokogiri (1.18.4-arm-linux-gnu) racc (~> 1.4) - nokogiri (1.18.2-arm64-darwin) + nokogiri (1.18.4-arm64-darwin) racc (~> 1.4) - nokogiri (1.18.2-x86_64-darwin) + nokogiri (1.18.4-x86_64-darwin) racc (~> 1.4) - nokogiri (1.18.2-x86_64-linux-gnu) + nokogiri (1.18.4-x86_64-linux-gnu) racc (~> 1.4) pp (0.6.2) prettyprint @@ -110,7 +110,7 @@ GEM date stringio racc (1.8.1) - rack (3.1.8) + rack (3.1.12) rack-session (2.1.0) base64 (>= 0.1.0) rack (>= 3.0.0) @@ -125,33 +125,33 @@ GEM rails-html-sanitizer (1.6.2) loofah (~> 2.21) nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) - railties (8.0.1) - actionpack (= 8.0.1) - activesupport (= 8.0.1) + railties (8.0.2) + actionpack (= 8.0.2) + activesupport (= 8.0.2) irb (~> 1.13) rackup (>= 1.0.0) rake (>= 12.2) thor (~> 1.0, >= 1.2.2) zeitwerk (~> 2.6) rake (13.2.1) - rdoc (6.11.0) + rdoc (6.12.0) psych (>= 4.0.0) reline (0.6.0) io-console (~> 0.5) securerandom (0.4.1) - stringio (3.1.2) - tailwindcss-ruby (4.0.0) - tailwindcss-ruby (4.0.0-aarch64-linux-gnu) - tailwindcss-ruby (4.0.0-arm64-darwin) - tailwindcss-ruby (4.0.0-x86_64-darwin) - tailwindcss-ruby (4.0.0-x86_64-linux-gnu) + stringio (3.1.5) + tailwindcss-ruby (4.1.10) + tailwindcss-ruby (4.1.10-aarch64-linux-gnu) + tailwindcss-ruby (4.1.10-arm64-darwin) + tailwindcss-ruby (4.1.10-x86_64-darwin) + tailwindcss-ruby (4.1.10-x86_64-linux-gnu) thor (1.3.2) timeout (0.4.3) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - uri (1.0.2) + uri (1.0.3) useragent (0.16.11) - zeitwerk (2.7.1) + zeitwerk (2.7.2) PLATFORMS aarch64-linux diff --git a/README.md b/README.md index 623f3f30..450a177d 100644 --- a/README.md +++ b/README.md @@ -12,16 +12,20 @@ - [Upgrading your application from Tailwind v3 to v4](#upgrading-your-application-from-tailwind-v3-to-v4) * [You don't _have_ to upgrade](#you-dont-_have_-to-upgrade) * [Upgrade steps](#upgrade-steps) - * [Troubleshooting](#troubleshooting) + * [Troubleshooting a v4 upgrade](#troubleshooting-a-v4-upgrade) + * [Updating CSS class names for v4](#updating-css-class-names-for-v4) - [Developing with Tailwindcss](#developing-with-tailwindcss) * [Configuration and commands](#configuration-and-commands) * [Building for production](#building-for-production) * [Building for testing](#building-for-testing) * [Building unminified assets](#building-unminified-assets) * [Live rebuild](#live-rebuild) + * [Using Tailwind plugins](#using-tailwind-plugins) * [Using with PostCSS](#using-with-postcss) * [Custom inputs or outputs](#custom-inputs-or-outputs) -- [Troubleshooting](#troubleshooting-1) + * [Rails Engines support (Experimental)](#rails-engines-support-experimental) +- [Troubleshooting](#troubleshooting) + * [The `watch` command is hanging](#the-watch-command-is-hanging) * [Lost keystrokes or hanging when using terminal-based debugging tools (e.g. IRB, Pry, `ruby/debug`...etc.) with the Puma plugin](#lost-keystrokes-or-hanging-when-using-terminal-based-debugging-tools-eg-irb-pry-rubydebugetc-with-the-puma-plugin) * [Running in a docker container exits prematurely](#running-in-a-docker-container-exits-prematurely) * [Conflict with sassc-rails](#conflict-with-sassc-rails) @@ -34,19 +38,18 @@ ## Installation -With Rails 7 you can generate a new application preconfigured with Tailwind by using `--css tailwind`. If you're adding Tailwind later, you need to: +With Rails 7 you can generate a new application preconfigured with Tailwind CSS by using `--css tailwind`. If you're adding Tailwind later, you need to: 1. Run `./bin/bundle add tailwindcss-rails` 2. Run `./bin/rails tailwindcss:install` -This gem depends on the `tailwindcss-ruby` gem to install a working tailwind executable. - +This gem depends on the `tailwindcss-ruby` gem to install a working Tailwind CLI executable. ### Choosing a specific version of `tailwindcss` -The `tailwindcss-ruby` gem is declared as a floating dependency of this gem, so by default you will get the most recent stable version. However, you can select a specific version of tailwind by pinning that gem to the analogous version in your application's `Gemfile`. For example, +The `tailwindcss-ruby` gem is declared as a floating dependency of this gem, so by default you will get the most recent stable version. However, you can select a specific version of Tailwind CSS by pinning that gem to the analogous version in your application's `Gemfile`. For example, -``` ruby +```ruby gem "tailwindcss-rails" # pin to tailwindcss version 3.4.13 @@ -57,60 +60,76 @@ gem "tailwindcss-ruby", "3.4.13" You can also use a local (npm-based) installation if you prefer, please go to https://github.com/flavorjones/tailwindcss-ruby for more information. - ## Upgrading your application from Tailwind v3 to v4 v4.x of this gem has been updated to work with Tailwind v4, including providing some help with upgrading your application. -A full explanation of a Tailwind v4 upgrade is out of scope for this README, so we strongly urge you to read the [official Tailwind v4 upgrade guide](https://tailwindcss.com/docs/upgrade-guide) before embarking on an upgrade to an existing large app. +A full explanation of a Tailwind CSS v4 upgrade is out of scope for this README, so we **strongly urge** you to read the [official Tailwind CSS v4 upgrade guide](https://tailwindcss.com/docs/upgrade-guide) before embarking on an upgrade to an existing large app. -This gem will help with some of the mechanics of the upgrade, however. +This gem will help with some of the mechanics of the upgrade: +- update some generated files to handle breaking changes in v4 of this gem, +- update some local project files to meet some Tailwind CSS v4 conventions, +- attempt to run the [upstream v4 upgrade tool](https://tailwindcss.com/docs/upgrade-guide#using-the-upgrade-tool). ### You don't _have_ to upgrade -Keep in mind that you don't _need_ to upgrade. You can stay on Tailwind v3 for the foreseeable future if you prefer not to migrate now, or if your migration runs into problems. +Keep in mind that you don't _need_ to upgrade. You can stay on Tailwind CSS v3 for the foreseeable future if you prefer not to migrate now, or if your migration runs into problems. -Just make sure you're either pinned to v3.3.1 of this gem: +If you don't want to upgrade, then pin your application to v3.3.1 of this gem: -``` ruby +```ruby # Gemfile -gem "tailwindcss-rails", "3.3.1" # which transitively pins tailwindcss-ruby to v3 +gem "tailwindcss-rails", "~> 3.3.1" # which transitively pins tailwindcss-ruby to v3 ``` -or if you're on an earlier version of this gem, make sure you're pinning the version of **both** `tailwindcss-rails` and `tailwindcss-ruby`: +If you're on an earlier version of this gem, `<= 3.3.0`, then make sure you're pinning the version of **both** `tailwindcss-rails` and `tailwindcss-ruby`: -``` ruby +```ruby # Gemfile gem "tailwindcss-rails", "~> 3.3" -gem "tailwindcss-ruby", "~> 3.4" +gem "tailwindcss-ruby", "~> 3.4" # only necessary with tailwindcss-rails <= 3.3.0 ``` - ### Upgrade steps +> [!WARNING] +> In applications using Tailwind plugins without JavaScript tooling, these upgrade steps may fail to fully migrate `tailwind.config.js` because the upstream upgrade tool needs the Tailwind plugins to be installed and available through a JavaScript package manager. If you see errors from the upstream upgrade tool, you should try following the additional steps in [Updating CSS class names for v4](#updating-css-class-names-for-v4) which will help you install (temporarily!) the necessary packages and clean up afterwards. + First, update to `tailwindcss-rails` v4.0.0 or higher. This will also ensure you're transitively depending on `tailwindcss-ruby` v4. -``` html -# Gemfile +```ruby +# Gemfile gem "tailwindcss-rails", "~> 4.0" # which transitively pins tailwindcss-ruby to v4 ``` -Then, run the `tailwindcss:upgrade` task. Among other things, this will try to run the official Tailwind upgrade utility. It requires `npx` in order to run, but it's a one-time operation and is *highly recommended* for a successful upgrade. +**Update** path references to any existing css files imported in `app/assets/stylesheets/application.tailwind.css` so that they will resolve when the file is moved to `app/assets/tailwind/application.css`. -Here's what the upgrade task does: +```diff +-@import "pagy.css"; ++@import "../stylesheets/pagy.css"; +``` + +If you want to migrate CSS class names for v4 (this is an optional step!), jump to [Updating CSS class names for v4](#updating-css-class-names-for-v4) before continuing. + +Then, run `bin/rails tailwindcss:upgrade`. Among other things, this will try to run the official Tailwind upgrade utility. It requires `npx` in order to run, but it's a one-time operation and is _highly recommended_ for a successful upgrade. + +
+Here's a detailed list of what the upgrade task does. - Cleans up some things in the generated `config/tailwind.config.js`. - If present, moves `config/postcss.config.js` to the root directory. -- If present, moves `app/assets/stylesheets/application.tailwind.css` to `app/assets/tailwind`. +- If present, moves `app/assets/stylesheets/application.tailwind.css` to `app/assets/tailwind/application.css`. - Removes unnecessary `stylesheet_link_tag "tailwindcss"` tags from the application layout. - Removes references to the Inter font from the application layout. -- Runs the upstream upgrader (note: requires `npx` to run the one-time upgrade, but highly recommended). +- Runs v4.1.4 of the upstream upgrader (note: requires `npx` to run the one-time upgrade, but highly recommended). + +
Here's what that upgrade looks like on a vanilla Rails app. -``` sh +```sh $ bin/rails tailwindcss:upgrade apply /path/to/tailwindcss-rails/lib/install/upgrade_tailwindcss.rb Removing references to 'defaultTheme' from /home/user/myapp/config/tailwind.config.js @@ -119,22 +138,22 @@ $ bin/rails tailwindcss:upgrade gsub app/views/layouts/application.html.erb Remove unnecessary stylesheet_link_tag from application layout gsub app/views/layouts/application.html.erb - Moving application.tailwind.css to /home/user/myapp/app/assets/tailwind - create app/assets/tailwind/application.tailwind.css + Moving /home/user/myapp/app/assets/stylesheets/application.tailwind.css to /home/user/myapp/app/assets/tailwind/application.css + create app/assets/tailwind/application.css remove app/assets/stylesheets/application.tailwind.css 10.9.0 Running the upstream Tailwind CSS upgrader - run npx @tailwindcss/upgrade@next --force --config /home/user/myapp/config/tailwind.config.js from "." + run npx @tailwindcss/upgrade@4.1.4 --force --config /home/user/myapp/config/tailwind.config.js from "." ≈ tailwindcss v4.0.0 │ Searching for CSS files in the current directory and its subdirectories… -│ ↳ Linked `./config/tailwind.config.js` to `./app/assets/tailwind/application.tailwind.css` +│ ↳ Linked `./config/tailwind.config.js` to `./app/assets/tailwind/application.css` │ Migrating JavaScript configuration files… │ ↳ The configuration file at `./config/tailwind.config.js` could not be automatically migrated to the new CSS │ configuration format, so your CSS has been updated to load your existing configuration file. │ Migrating templates… │ ↳ Migrated templates for configuration file: `./config/tailwind.config.js` │ Migrating stylesheets… -│ ↳ Migrated stylesheet: `./app/assets/tailwind/application.tailwind.css` +│ ↳ Migrated stylesheet: `./app/assets/tailwind/application.css` │ ↳ No PostCSS config found, skipping migration. │ Updating dependencies… │ Could not detect a package manager. Please manually update `tailwindcss` to v4. @@ -148,30 +167,86 @@ Done in 56ms
-If this doesn't succeed, it's likely that you've customized your Tailwind configuration and you'll need to do some work to make sure your application upgrades. Please read the [official upgrade guide](https://tailwindcss.com/docs/upgrade-guide)! +If this doesn't succeed, it's likely that you've customized your Tailwind configuration and you'll need to do some work to make sure your application upgrades. Please read the [official upgrade guide](https://tailwindcss.com/docs/upgrade-guide) and try following the additional steps in [Updating CSS class names for v4](#updating-css-class-names-for-v4). - -### Troubleshooting +### Troubleshooting a v4 upgrade You may want to check out [TailwindCSS v4 - upgrade experience report · rails/tailwindcss-rails · Discussion #450](https://github.com/rails/tailwindcss-rails/discussions/450) if you're having trouble upgrading. We know there are some cases we haven't addressed with the upgrade task: -- If the user isn’t using PostCSS, some migrations (e.g., updating class names in the view files) may fail -- In setups without JavaScript tooling, the update process may fail to fully migrate `tailwind.config.js` because the tool assumes that the imported packages (e.g., tailwind plugins) are installed via a package manager, allowing them to be called. +- In applications using Tailwind plugins without JavaScript tooling, these upgrade steps may fail to fully migrate `tailwind.config.js` because the upstream upgrade tool needs the Tailwind plugins to be installed and available through a JavaScript package manager. If you see errors from the upstream upgrade tool, you should try following the additional steps in [Updating CSS class names for v4](#updating-css-class-names-for-v4) which will help you install (temporarily!) the necessary packages and clean up afterwards. We'll try to improve the upgrade process over time, but for now you may need to do some manual work to upgrade. +### Updating CSS class names for v4 + +> [!NOTE] +> If you'd like to help automate these steps, please drop a note to the maintainers in [this discussion thread](https://github.com/rails/tailwindcss-rails/discussions/450). + +With some additional manual work the upstream upgrade tool will update your application's CSS class names to v4 conventions. **This is an optional step that requires a JavaScript toolchain.** + +**Add** the following line to the `.gitignore` file, to prevent the upstream upgrade tool from accessing node_modules files. + +```gitignore +/node_modules +``` + +**Create** or **update** a `package.json` in the root of the project: + +```jsonc +{ + "name": "app_name", + "version": "1.0.0", + "dependencies": { + "tailwindcss": "^3.4.17", // Mandatory!! + // Install all plugins and modules that are referenced in tailwind.config.js + "@tailwindcss/aspect-ratio": "^0.4.2", + "@tailwindcss/container-queries": "^0.1.1", + "@tailwindcss/forms": "^0.5.10", + "@tailwindcss/typography": "^0.5.16", + // And so on... + }, +} +``` + +**Run** `npm install` (or `yarn install` if using `yarn`) + +**Update** `config/tailwind.config.js` and temporarily change the `content` part to have an additional `.` on all paths so they are relative to the config file: + +```js + content: [ + '../public/*.html', + '../app/helpers/**/*.rb', + '../app/javascript/**/*.js', + '../app/views/**/*.{erb,haml,html,slim}' + ], +``` + +(Just add an additional `.` to all the paths referenced) + +**Run** the upstream upgrader as instructed above. + +Then, once you've run that successfully, clean up: + +- **Review** `package.json` to remove unnecessary modules. + - This includes modules added for the period of upgrade. + - If you don't need any modules besides `tailwindcss` itself, **delete** `package.json`, `node_modules/` and `package-lock.json` (or `yarn.lock`), plus remove `/node_modules` from `.gitignore`. +- **Go** to your CSS file and remove the following line (if present): + ```css + @plugin '@tailwindcss/container-queries'; + ``` +- **Revert** the changes to `config/tailwind.config.js` so that paths are once again relative to the application root. ## Developing with Tailwindcss ### Configuration and commands -#### Input file: `app/assets/tailwind/application.tailwind.css` +#### Input file: `app/assets/tailwind/application.css` -The `tailwindcss:install` task will generate a Tailwind input file in `app/assets/tailwind/application.tailwind.css`. This is where you import the plugins you want to use and where you can setup your custom `@apply` rules. +The `tailwindcss:install` task will generate a Tailwind input file in `app/assets/tailwind/application.css`. This is where you import the plugins you want to use and where you can setup your custom `@apply` rules. -⚠ The location of this file changed in v4, from `app/assets/stylesheets` to `app/assets/tailwind`. The `tailwindcss:upgrade` task will move it for you. +⚠ The location of this file changed in v4, from `app/assets/stylesheets/application.tailwind.css` to `app/assets/tailwind/application.css`. The `tailwindcss:upgrade` task will move it for you. #### Output file: `app/assets/builds/tailwind.css` @@ -197,21 +272,22 @@ This gem also makes available a Puma plugin to manage a live rebuild process whe This gem also generates a `Procfile.dev` file which will run both the rails server and a live rebuild process (see "Live Rebuild" section below). - ### Building for production The `tailwindcss:build` is automatically attached to `assets:precompile`, so before the asset pipeline digests the files, the Tailwind output will be generated. - ### Building for testing The `tailwindcss:build` task is automatically attached to the `test:prepare` Rake task. This task runs before test commands. If you run `bin/rails test` in your CI environment, your Tailwind output will be generated before tests run. - ### Building unminified assets -If you want unminified assets, you can pass a `debug` argument to the rake task, i.e. `rails tailwindcss:build[debug]` or `rails tailwindcss:watch[debug]`. +If you want unminified assets, you can: + +- pass a `debug` argument to the rake task, i.e. `rails tailwindcss:build[debug]` or `rails tailwindcss:watch[debug]`. +- set an environment variable named `TAILWINDCSS_DEBUG` with a non-blank value +If both values are set, the environment variable will take precedence over the rake task argument. ### Live rebuild @@ -221,7 +297,6 @@ While you're developing your application, you want to run Tailwind in "watch" mo - or run `rails tailwindcss:watch` as a separate process, - or run `bin/dev` which uses [Foreman](https://github.com/ddollar/foreman) - #### Puma plugin This gem ships with a Puma plugin. To use it, add this line to your `puma.rb` configuration: @@ -232,7 +307,6 @@ plugin :tailwindcss if ENV.fetch("RAILS_ENV", "development") == "development" and then running `rails server` (or just `puma`) will run the Tailwind watch process in the background. - #### Run `rails tailwindcss:watch` This is a flexible command, which can be run with a few different options. @@ -249,15 +323,38 @@ If you are running `rails tailwindcss:watch` as a process in a Docker container, If you are running `rails tailwindcss:watch` in a docker container without a tty, pass the `always` argument to the task to instruct tailwindcss to keep the watcher alive even when `stdin` is closed: `rails tailwindcss:watch[always]`. If you use `bin/dev` then you should modify your `Procfile.dev`. - #### Foreman Running `bin/dev` invokes Foreman to start both the Tailwind watch process and the rails server in development mode based on your `Procfile.dev` file. +### Using Tailwind plugins + +If you want to use Tailwind plugins, they can be installed using `package.json`. + +Using Yarn: + +```sh +[ ! -f package.json ] && yarn init +yarn add daisyui # example +``` + +Using npm: + +```sh +npm init +npm add daisyui # example +``` + +Than use `@plugin` annotation in `app/assets/tailwind/application.css`: + +```css +@import "tailwindcss"; +@plugin "daisyui"; +``` ### Using with PostCSS -If you want to use PostCSS as a preprocessor, create a custom `postcss.config.js` in your project root directory, and that file will be loaded by tailwind automatically. +If you want to use PostCSS as a preprocessor, create a custom `postcss.config.js` in your project root directory, and that file will be loaded by Tailwind automatically. For example, to enable nesting: @@ -266,11 +363,11 @@ For example, to enable nesting: export default { plugins: { "@tailwindcss/postcss": {}, - } -} + }, +}; ``` -⚠ Note that PostCSS is a javascript tool with its own prerequisites! By default `tailwindcss-rails` does not require any javascript tooling, so in order to use PostCSS, a `package.json` with dependencies for your plugins and a package manager like `yarn` or `npm` is required, for example: +⚠ Note that PostCSS is a JavaScript tool with its own prerequisites! By default `tailwindcss-rails` does not require any JavaScript tooling, so in order to use PostCSS, a `package.json` with dependencies for your plugins and a package manager like `yarn` or `npm` is required, for example: ```json // package.json @@ -287,15 +384,49 @@ export default { Then you can use yarn or npm to install the dependencies. - ### Custom inputs or outputs If you need to use a custom input or output file, you can run `bundle exec tailwindcss` to access the platform-specific executable, and give it your own build options. +### Rails Engines support (Experimental) + +_This feature is experimental and may change in the future. If you have feedback, please join the [discussion](https://github.com/rails/tailwindcss-rails/discussions/355)._ + +If you have Rails Engines in your application that use Tailwind CSS and provide an `app/assets/tailwind//engine.css` file, entry point files will be created for each of them in `app/assets/builds/tailwind/.css` on the first build/watch invocation or manual call for `rails tailwindcss:engines` so they can be included in your host application's Tailwind CSS by adding `@import "../builds/tailwind/"` to your `app/assets/tailwind/application.css` file. + +> [!IMPORTANT] +> You must `@import` the engine CSS files in your `app/assets/tailwind/application.css` for the engine to be included in the build. By default, no engine CSS files are imported, and you must opt-in to using the file in your build. ## Troubleshooting -Some common problems experienced by users ... +When having trouble with `tailwindcss:build` or `tailwindcss:watch`, the first thing you should do is collect some diagnostic information by setting the "verbose" flag, which will emit: + +1. the command being run (so you can try running `tailwindcss` yourself without the gem's help) +2. additional debugging output from `tailwindcss` by setting the env var `DEBUG=1` + +Here's what that looks like: + +```sh +$ bin/rails tailwindcss:build[verbose] + +Running: /path/to/tailwindcss-ruby-4.0.17-x86_64-linux-gnu/exe/x86_64-linux-gnu/tailwindcss -i /home/flavorjones/code/oss/tailwindcss-rails/My Workspace/test-install/app/assets/tailwind/application.css -o /home/flavorjones/code/oss/tailwindcss-rails/My Workspace/test-install/app/assets/builds/tailwind.css --minify +≈ tailwindcss v4.0.17 + +Done in 37ms + +[38.22ms] [@tailwindcss/cli] (initial build) +[11.90ms] ↳ Setup compiler +[ 6.52ms] ↳ Scan for candidates +[10.39ms] ↳ Build CSS +[ 1.69ms] ↳ Optimize CSS +[ 5.80ms] ↳ Write output +``` + +### The `watch` command is hanging + +There is a [known issue](https://github.com/tailwindlabs/tailwindcss/issues/17246#issuecomment-2753067488) running `tailwindcss -w` (that's the CLI in watch mode) when the utility `watchman` is also installed. + +Please try uninstalling `watchman` and try running the watch task again. ### Lost keystrokes or hanging when using terminal-based debugging tools (e.g. IRB, Pry, `ruby/debug`...etc.) with the Puma plugin @@ -321,29 +452,30 @@ See https://github.com/flavorjones/tailwindcss-ruby for help. ### Using asset-pipeline assets -In Rails, you want to use [assets from the asset pipeline to get fingerprinting](https://guides.rubyonrails.org/asset_pipeline.html#what-is-fingerprinting-and-why-should-i-care-questionmark). However, Tailwind isn't aware of those assets. +In Rails, you want to use [assets from the asset pipeline to get fingerprinting](https://guides.rubyonrails.org/asset_pipeline.html#fingerprinting-versioning-with-digest-based-urls). However, Tailwind isn't aware of those assets. To use assets from the pipeline, use `url(image.svg)`. [Since Sprockets v3.3.0](https://github.com/rails/sprockets-rails/pull/476) `url(image.svg)` is rewritten to `/path/to/assets/image-7801e7538c6f1cc57aa75a5876ab0cac.svg` so output CSS will have the correct path to those assets. ```js module.exports = { - theme: { - extend: { - backgroundImage: { - 'image': "url('image.svg')" - } - } - } -} + theme: { + extend: { + backgroundImage: { + image: "url('image.svg')", + }, + }, + }, +}; ``` The inline version also works: ```html -
Has the image as it's background
+
+ Has the image as it's background +
``` ## License Tailwind for Rails is released under the [MIT License](https://opensource.org/licenses/MIT). -The Inter font is released under the [SIL Open Font License, Version 1.1](https://github.com/rsms/inter/blob/master/LICENSE.txt). diff --git a/app/assets/fonts/Inter-italic.alternates.var.woff2 b/app/assets/fonts/Inter-italic.alternates.var.woff2 deleted file mode 100644 index cbeb7846..00000000 Binary files a/app/assets/fonts/Inter-italic.alternates.var.woff2 and /dev/null differ diff --git a/app/assets/fonts/Inter-italic.cyrillic.var.woff2 b/app/assets/fonts/Inter-italic.cyrillic.var.woff2 deleted file mode 100644 index 90930a09..00000000 Binary files a/app/assets/fonts/Inter-italic.cyrillic.var.woff2 and /dev/null differ diff --git a/app/assets/fonts/Inter-italic.extra.var.woff2 b/app/assets/fonts/Inter-italic.extra.var.woff2 deleted file mode 100644 index cbeb7846..00000000 Binary files a/app/assets/fonts/Inter-italic.extra.var.woff2 and /dev/null differ diff --git a/app/assets/fonts/Inter-italic.greek.var.woff2 b/app/assets/fonts/Inter-italic.greek.var.woff2 deleted file mode 100644 index c0684d11..00000000 Binary files a/app/assets/fonts/Inter-italic.greek.var.woff2 and /dev/null differ diff --git a/app/assets/fonts/Inter-italic.latin-ext.var.woff2 b/app/assets/fonts/Inter-italic.latin-ext.var.woff2 deleted file mode 100644 index be543c42..00000000 Binary files a/app/assets/fonts/Inter-italic.latin-ext.var.woff2 and /dev/null differ diff --git a/app/assets/fonts/Inter-italic.latin.var.woff2 b/app/assets/fonts/Inter-italic.latin.var.woff2 deleted file mode 100644 index 5066cfdf..00000000 Binary files a/app/assets/fonts/Inter-italic.latin.var.woff2 and /dev/null differ diff --git a/app/assets/fonts/Inter-italic.symbols.var.woff2 b/app/assets/fonts/Inter-italic.symbols.var.woff2 deleted file mode 100644 index 1542bc95..00000000 Binary files a/app/assets/fonts/Inter-italic.symbols.var.woff2 and /dev/null differ diff --git a/app/assets/fonts/Inter-italic.vietnamese.var.woff2 b/app/assets/fonts/Inter-italic.vietnamese.var.woff2 deleted file mode 100644 index badcf325..00000000 Binary files a/app/assets/fonts/Inter-italic.vietnamese.var.woff2 and /dev/null differ diff --git a/app/assets/fonts/Inter-roman.alternates.var.woff2 b/app/assets/fonts/Inter-roman.alternates.var.woff2 deleted file mode 100644 index f2ee9eeb..00000000 Binary files a/app/assets/fonts/Inter-roman.alternates.var.woff2 and /dev/null differ diff --git a/app/assets/fonts/Inter-roman.cyrillic.var.woff2 b/app/assets/fonts/Inter-roman.cyrillic.var.woff2 deleted file mode 100644 index a9378e78..00000000 Binary files a/app/assets/fonts/Inter-roman.cyrillic.var.woff2 and /dev/null differ diff --git a/app/assets/fonts/Inter-roman.extra.var.woff2 b/app/assets/fonts/Inter-roman.extra.var.woff2 deleted file mode 100644 index f2ee9eeb..00000000 Binary files a/app/assets/fonts/Inter-roman.extra.var.woff2 and /dev/null differ diff --git a/app/assets/fonts/Inter-roman.greek.var.woff2 b/app/assets/fonts/Inter-roman.greek.var.woff2 deleted file mode 100644 index 8604c8a0..00000000 Binary files a/app/assets/fonts/Inter-roman.greek.var.woff2 and /dev/null differ diff --git a/app/assets/fonts/Inter-roman.latin-ext.var.woff2 b/app/assets/fonts/Inter-roman.latin-ext.var.woff2 deleted file mode 100644 index ac92ffba..00000000 Binary files a/app/assets/fonts/Inter-roman.latin-ext.var.woff2 and /dev/null differ diff --git a/app/assets/fonts/Inter-roman.latin.var.woff2 b/app/assets/fonts/Inter-roman.latin.var.woff2 deleted file mode 100644 index 9503ba17..00000000 Binary files a/app/assets/fonts/Inter-roman.latin.var.woff2 and /dev/null differ diff --git a/app/assets/fonts/Inter-roman.symbols.var.woff2 b/app/assets/fonts/Inter-roman.symbols.var.woff2 deleted file mode 100644 index c8da0889..00000000 Binary files a/app/assets/fonts/Inter-roman.symbols.var.woff2 and /dev/null differ diff --git a/app/assets/fonts/Inter-roman.vietnamese.var.woff2 b/app/assets/fonts/Inter-roman.vietnamese.var.woff2 deleted file mode 100644 index b65ab546..00000000 Binary files a/app/assets/fonts/Inter-roman.vietnamese.var.woff2 and /dev/null differ diff --git a/lib/generators/tailwindcss/authentication/authentication_generator.rb b/lib/generators/tailwindcss/authentication/authentication_generator.rb index aa6fc23b..756f1d7b 100644 --- a/lib/generators/tailwindcss/authentication/authentication_generator.rb +++ b/lib/generators/tailwindcss/authentication/authentication_generator.rb @@ -3,6 +3,8 @@ module Tailwindcss module Generators class AuthenticationGenerator < Erb::Generators::AuthenticationGenerator + hide! + source_root File.expand_path("templates", __dir__) end end diff --git a/lib/generators/tailwindcss/authentication/templates/app/views/passwords/edit.html.erb b/lib/generators/tailwindcss/authentication/templates/app/views/passwords/edit.html.erb index 5c989810..7096a5bc 100644 --- a/lib/generators/tailwindcss/authentication/templates/app/views/passwords/edit.html.erb +++ b/lib/generators/tailwindcss/authentication/templates/app/views/passwords/edit.html.erb @@ -7,15 +7,15 @@ <%%= form_with url: password_path(params[:token]), method: :put, class: "contents" do |form| %>
- <%%= form.password_field :password, required: true, autocomplete: "new-password", placeholder: "Enter new password", maxlength: 72, class: "block shadow-sm rounded-md border border-gray-400 outline-hidden focus:outline-blue-600 px-3 py-2 mt-2 w-full" %> + <%%= form.password_field :password, required: true, autocomplete: "new-password", placeholder: "Enter new password", maxlength: 72, class: "block shadow-sm rounded-md border border-gray-400 focus:outline-solid focus:outline-blue-600 px-3 py-2 mt-2 w-full" %>
- <%%= form.password_field :password_confirmation, required: true, autocomplete: "new-password", placeholder: "Repeat new password", maxlength: 72, class: "block shadow-sm rounded-md border border-gray-400 outline-hidden focus:outline-blue-600 px-3 py-2 mt-2 w-full" %> + <%%= form.password_field :password_confirmation, required: true, autocomplete: "new-password", placeholder: "Repeat new password", maxlength: 72, class: "block shadow-sm rounded-md border border-gray-400 focus:outline-solid focus:outline-blue-600 px-3 py-2 mt-2 w-full" %>
- <%%= form.submit "Save", class: "rounded-md px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white inline-block font-medium cursor-pointer" %> + <%%= form.submit "Save", class: "w-full sm:w-auto text-center rounded-md px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white inline-block font-medium cursor-pointer" %>
<%% end %> diff --git a/lib/generators/tailwindcss/authentication/templates/app/views/passwords/new.html.erb b/lib/generators/tailwindcss/authentication/templates/app/views/passwords/new.html.erb index e5862200..36dff837 100644 --- a/lib/generators/tailwindcss/authentication/templates/app/views/passwords/new.html.erb +++ b/lib/generators/tailwindcss/authentication/templates/app/views/passwords/new.html.erb @@ -7,11 +7,11 @@ <%%= form_with url: passwords_path, class: "contents" do |form| %>
- <%%= form.email_field :email_address, required: true, autofocus: true, autocomplete: "username", placeholder: "Enter your email address", value: params[:email_address], class: "block shadow-sm rounded-md border border-gray-400 outline-hidden focus:outline-blue-600 px-3 py-2 mt-2 w-full" %> + <%%= form.email_field :email_address, required: true, autofocus: true, autocomplete: "username", placeholder: "Enter your email address", value: params[:email_address], class: "block shadow-sm rounded-md border border-gray-400 focus:outline-solid focus:outline-blue-600 px-3 py-2 mt-2 w-full" %>
- <%%= form.submit "Email reset instructions", class: "rounded-lg px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white inline-block font-medium cursor-pointer" %> + <%%= form.submit "Email reset instructions", class: "w-full sm:w-auto text-center rounded-lg px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white inline-block font-medium cursor-pointer" %>
<%% end %> diff --git a/lib/generators/tailwindcss/authentication/templates/app/views/sessions/new.html.erb b/lib/generators/tailwindcss/authentication/templates/app/views/sessions/new.html.erb index 64c145c0..30fb0d91 100644 --- a/lib/generators/tailwindcss/authentication/templates/app/views/sessions/new.html.erb +++ b/lib/generators/tailwindcss/authentication/templates/app/views/sessions/new.html.erb @@ -20,7 +20,7 @@
- <%%= form.submit "Sign in", class: "rounded-md px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white inline-block font-medium cursor-pointer" %> + <%%= form.submit "Sign in", class: "w-full sm:w-auto text-center rounded-md px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white inline-block font-medium cursor-pointer" %>
diff --git a/lib/generators/tailwindcss/scaffold/scaffold_generator.rb b/lib/generators/tailwindcss/scaffold/scaffold_generator.rb index 39c2da1f..8748210d 100644 --- a/lib/generators/tailwindcss/scaffold/scaffold_generator.rb +++ b/lib/generators/tailwindcss/scaffold/scaffold_generator.rb @@ -1,5 +1,6 @@ require "rails/generators/erb/scaffold/scaffold_generator" require "rails/generators/resource_helpers" +require File.expand_path("../../test_unit/scaffold/scaffold_generator.rb", __dir__) module Tailwindcss module Generators diff --git a/lib/generators/tailwindcss/scaffold/templates/_form.html.erb.tt b/lib/generators/tailwindcss/scaffold/templates/_form.html.erb.tt index 9e392609..1821201c 100644 --- a/lib/generators/tailwindcss/scaffold/templates/_form.html.erb.tt +++ b/lib/generators/tailwindcss/scaffold/templates/_form.html.erb.tt @@ -12,32 +12,32 @@ <%% end %> <% attributes.each do |attribute| -%> -
+
"> <% if attribute.password_digest? -%> <%%= form.label :password %> - <%%= form.password_field :password, class: ["block shadow-sm rounded-md border outline-hidden px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:password].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:password].any?}] %> + <%%= form.password_field :password, class: ["block shadow-sm rounded-md border px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:password].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:password].any?}] %>
<%%= form.label :password_confirmation %> - <%%= form.password_field :password_confirmation, class: ["block shadow-sm rounded-md border outline-hidden px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:password_confirmation].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:password_confirmation].any?}] %> + <%%= form.password_field :password_confirmation, class: ["block shadow-sm rounded-md border px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:password_confirmation].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:password_confirmation].any?}] %> <% elsif attribute.attachments? -%> <%%= form.label :<%= attribute.column_name %> %> - <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, multiple: true, class: ["block shadow-sm rounded-md border outline-hidden px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:password].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:password].any?}] %> + <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, multiple: true, class: ["block shadow-sm rounded-md border px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].any?}] %> <% else -%> <%%= form.label :<%= attribute.column_name %> %> <% if attribute.field_type == :textarea || attribute.field_type == :text_area -%> - <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, rows: 4, class: ["block shadow-sm rounded-md border outline-hidden px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].any?}] %> + <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, rows: 4, class: ["block shadow-sm rounded-md border px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].any?}] %> <% elsif attribute.field_type == :checkbox || attribute.field_type == :check_box -%> - <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, class: ["block shadow-sm rounded-md border outline-hidden mt-2 h-5 w-5", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].any?}] %> + <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, class: ["block shadow-sm rounded-md border order-first h-5 w-5", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].any?}] %> <% else -%> - <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, class: ["block shadow-sm rounded-md border outline-hidden px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].any?}] %> + <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, class: ["block shadow-sm rounded-md border px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].none?, "border-red-400 focus:outline-red-600": <%= model_resource_name %>.errors[:<%= attribute.column_name %>].any?}] %> <% end -%> <% end -%>
<% end -%>
- <%%= form.submit class: "rounded-md px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white inline-block font-medium cursor-pointer" %> + <%%= form.submit class: "w-full sm:w-auto rounded-md px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white inline-block font-medium cursor-pointer" %>
<%% end %> diff --git a/lib/generators/tailwindcss/scaffold/templates/edit.html.erb.tt b/lib/generators/tailwindcss/scaffold/templates/edit.html.erb.tt index 74edd3de..08d92d3a 100644 --- a/lib/generators/tailwindcss/scaffold/templates/edit.html.erb.tt +++ b/lib/generators/tailwindcss/scaffold/templates/edit.html.erb.tt @@ -5,6 +5,6 @@ <%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %> - <%%= link_to "Show this <%= human_name.downcase %>", <%= model_resource_name(prefix: "@") %>, class: "ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %> - <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %>, class: "ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %> + <%%= link_to "Show this <%= human_name.downcase %>", <%= model_resource_name(prefix: "@") %>, class: "w-full sm:w-auto text-center mt-2 sm:mt-0 sm:ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %> + <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %>, class: "w-full sm:w-auto text-center mt-2 sm:mt-0 sm:ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %>
diff --git a/lib/generators/tailwindcss/scaffold/templates/index.html.erb.tt b/lib/generators/tailwindcss/scaffold/templates/index.html.erb.tt index 3d337f95..12a0db16 100644 --- a/lib/generators/tailwindcss/scaffold/templates/index.html.erb.tt +++ b/lib/generators/tailwindcss/scaffold/templates/index.html.erb.tt @@ -10,13 +10,17 @@ <%%= link_to "New <%= human_name.downcase %>", new_<%= singular_route_name %>_path, class: "rounded-md px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white block font-medium" %>
-
+
<%% if @<%= plural_table_name %>.any? %> <%% @<%= plural_table_name %>.each do |<%= singular_table_name %>| %> - <%%= render <%= singular_table_name %> %> -

- <%%= link_to "Show this <%= human_name.downcase %>", <%= model_resource_name(singular_table_name) %>, class: "ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %> -

+
+ <%%= render <%= singular_table_name %> %> +
+ <%%= link_to "Show", <%= model_resource_name(singular_table_name) %>, class: "w-full sm:w-auto text-center rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %> + <%%= link_to "Edit", <%= edit_helper(singular_table_name, type: :path) %>, class: "w-full sm:w-auto text-center rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %> + <%%= button_to "Destroy", <%= model_resource_name %>, method: :delete, class: "w-full sm:w-auto rounded-md px-3.5 py-2.5 text-white bg-red-600 hover:bg-red-500 font-medium cursor-pointer", data: { turbo_confirm: "Are you sure?" } %> +
+
<%% end %> <%% else %>

No <%= human_name.downcase.pluralize %> found.

diff --git a/lib/generators/tailwindcss/scaffold/templates/new.html.erb.tt b/lib/generators/tailwindcss/scaffold/templates/new.html.erb.tt index 0a10d967..32ad9b83 100644 --- a/lib/generators/tailwindcss/scaffold/templates/new.html.erb.tt +++ b/lib/generators/tailwindcss/scaffold/templates/new.html.erb.tt @@ -5,5 +5,5 @@ <%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %> - <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %>, class: "ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %> + <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %>, class: "w-full sm:w-auto text-center mt-2 sm:mt-0 sm:ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %>
diff --git a/lib/generators/tailwindcss/scaffold/templates/partial.html.erb.tt b/lib/generators/tailwindcss/scaffold/templates/partial.html.erb.tt index 88dc3eda..433b7a33 100644 --- a/lib/generators/tailwindcss/scaffold/templates/partial.html.erb.tt +++ b/lib/generators/tailwindcss/scaffold/templates/partial.html.erb.tt @@ -1,16 +1,18 @@ -
+
<% attributes.reject(&:password_digest?).each do |attribute| -%> -

+

<%= attribute.human_name %>: <% if attribute.attachment? -%> - <%%= link_to <%= singular_name %>.<%= attribute.column_name %>.filename, <%= singular_name %>.<%= attribute.column_name %> if <%= singular_name %>.<%= attribute.column_name %>.attached? %> + <%%= link_to <%= singular_name %>.<%= attribute.column_name %>.filename, <%= singular_name %>.<%= attribute.column_name %>, class: "text-gray-700 underline hover:no-underline" if <%= singular_name %>.<%= attribute.column_name %>.attached? %> <% elsif attribute.attachments? -%> <%% <%= singular_name %>.<%= attribute.column_name %>.each do |<%= attribute.singular_name %>| %> -
<%%= link_to <%= attribute.singular_name %>.filename, <%= attribute.singular_name %> %>
+
<%%= link_to <%= attribute.singular_name %>.filename, <%= attribute.singular_name %>, class: "text-gray-700 underline hover:no-underline" %>
<%% end %> +<% elsif attribute.type == :boolean -%> + <%%= <%= singular_name %>.<%= attribute.column_name %>? ? "Yes" : "No" %> <% else -%> <%%= <%= singular_name %>.<%= attribute.column_name %> %> <% end -%> -

+
<% end -%>
diff --git a/lib/generators/tailwindcss/scaffold/templates/show.html.erb.tt b/lib/generators/tailwindcss/scaffold/templates/show.html.erb.tt index 3a49e9a0..2b6687d2 100644 --- a/lib/generators/tailwindcss/scaffold/templates/show.html.erb.tt +++ b/lib/generators/tailwindcss/scaffold/templates/show.html.erb.tt @@ -9,9 +9,7 @@ <%%= render @<%= singular_table_name %> %> - <%%= link_to "Edit this <%= human_name.downcase %>", <%= edit_helper(type: :path) %>, class: "mt-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %> - <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper %>_path, class: "ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %> -
- <%%= button_to "Destroy this <%= human_name.downcase %>", <%= model_resource_name(prefix: "@") %>, method: :delete, class: "mt-2 rounded-md px-3.5 py-2.5 text-white bg-red-600 hover:bg-red-500 font-medium" %> -
+ <%%= link_to "Edit this <%= human_name.downcase %>", <%= edit_helper(type: :path) %>, class: "w-full sm:w-auto text-center rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %> + <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper %>_path, class: "w-full sm:w-auto text-center mt-2 sm:mt-0 sm:ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %> + <%%= button_to "Destroy this <%= human_name.downcase %>", <%= model_resource_name(prefix: "@") %>, method: :delete, form_class: "sm:inline-block mt-2 sm:mt-0 sm:ml-2", class: "w-full rounded-md px-3.5 py-2.5 text-white bg-red-600 hover:bg-red-500 font-medium cursor-pointer", data: { turbo_confirm: "Are you sure?" } %>
diff --git a/lib/generators/test_unit/scaffold/scaffold_generator.rb b/lib/generators/test_unit/scaffold/scaffold_generator.rb new file mode 100644 index 00000000..ff809b32 --- /dev/null +++ b/lib/generators/test_unit/scaffold/scaffold_generator.rb @@ -0,0 +1,21 @@ +require "rails/generators/test_unit/scaffold/scaffold_generator" + +module TestUnit # :nodoc: + module Generators # :nodoc: + class ScaffoldGenerator < Base # :nodoc: + def fix_system_test + if turbo_defined? + gsub_file File.join("test/system", class_path, "#{file_name.pluralize}_test.rb"), + /(click_on.*Destroy this.*)$/, + "accept_confirm { \\1 }" + end + end + + private + + def turbo_defined? + defined?(Turbo) + end + end + end +end diff --git a/lib/install/application.tailwind.css b/lib/install/application.css similarity index 100% rename from lib/install/application.tailwind.css rename to lib/install/application.css diff --git a/lib/install/install_tailwindcss.rb b/lib/install/install_tailwindcss.rb index e210d60b..3d471d07 100644 --- a/lib/install/install_tailwindcss.rb +++ b/lib/install/install_tailwindcss.rb @@ -1,6 +1,6 @@ APPLICATION_LAYOUT_PATH = Rails.root.join("app/views/layouts/application.html.erb") CENTERING_CONTAINER_INSERTION_POINT = /^\s*<%= yield %>/.freeze -TAILWIND_ASSET_PATH = Rails.root.join("app/assets/tailwind") +TAILWIND_ASSET_PATH = Rails.root.join("app/assets/tailwind/application.css") if APPLICATION_LAYOUT_PATH.exist? unless File.read(APPLICATION_LAYOUT_PATH).match?(/stylesheet_link_tag :app/) @@ -32,9 +32,9 @@ append_to_file(".gitignore", %(\n/app/assets/builds/*\n!/app/assets/builds/.keep\n)) end -unless TAILWIND_ASSET_PATH.join("application.tailwind.css").exist? - say "Add default #{TAILWIND_ASSET_PATH}/application.tailwind.css" - copy_file "#{__dir__}/application.tailwind.css", TAILWIND_ASSET_PATH.join("application.tailwind.css") +unless TAILWIND_ASSET_PATH.exist? + say "Add default #{TAILWIND_ASSET_PATH}" + copy_file "#{__dir__}/application.css", TAILWIND_ASSET_PATH end if Rails.root.join("Procfile.dev").exist? diff --git a/lib/install/upgrade_tailwindcss.rb b/lib/install/upgrade_tailwindcss.rb index 84a1aa8c..d6ecadab 100644 --- a/lib/install/upgrade_tailwindcss.rb +++ b/lib/install/upgrade_tailwindcss.rb @@ -1,8 +1,8 @@ TAILWIND_CONFIG_PATH = Rails.root.join("config/tailwind.config.js") APPLICATION_LAYOUT_PATH = Rails.root.join("app/views/layouts/application.html.erb") POSTCSS_CONFIG_PATH = Rails.root.join("config/postcss.config.js") -OLD_TAILWIND_ASSET_PATH = Rails.root.join("app/assets/stylesheets") -TAILWIND_ASSET_PATH = Rails.root.join("app/assets/tailwind") +OLD_TAILWIND_ASSET_PATH = Rails.root.join("app/assets/stylesheets/application.tailwind.css") +TAILWIND_ASSET_PATH = Rails.root.join("app/assets/tailwind/application.css") unless TAILWIND_CONFIG_PATH.exist? say "Default tailwind.config.js is missing!", :red @@ -38,15 +38,21 @@ say %( Please check your layouts and remove any "inter-font" stylesheet links.) end -if OLD_TAILWIND_ASSET_PATH.join("application.tailwind.css").exist? - say "Moving application.tailwind.css to #{TAILWIND_ASSET_PATH}" - copy_file OLD_TAILWIND_ASSET_PATH.join("application.tailwind.css"), TAILWIND_ASSET_PATH.join("application.tailwind.css") - remove_file OLD_TAILWIND_ASSET_PATH.join("application.tailwind.css") +if OLD_TAILWIND_ASSET_PATH.exist? + say "Moving #{OLD_TAILWIND_ASSET_PATH} to #{TAILWIND_ASSET_PATH}" + copy_file OLD_TAILWIND_ASSET_PATH, TAILWIND_ASSET_PATH + remove_file OLD_TAILWIND_ASSET_PATH end if system("npx --version") + # We're pinning to v4.1.4 because v4.1.5 of the upgrade tool introduces a dependency version check + # on tailwind and I haven't been able to figure out how to get that to work reliably and I am + # extremely frustrated with the whole thing. See #544 + # + # At some point we will probably need to unpin this at which point I am sincerely hoping that + # someone else will do it. say "Running the upstream Tailwind CSS upgrader" - command = Shellwords.join(["npx", "@tailwindcss/upgrade@next", "--force", "--config", TAILWIND_CONFIG_PATH.to_s]) + command = Shellwords.join(["npx", "@tailwindcss/upgrade@4.1.4", "--force", "--config", TAILWIND_CONFIG_PATH.to_s]) success = run(command, abort_on_failure: false) unless success say "The upgrade tool failed!", :red diff --git a/lib/tailwindcss-rails.rb b/lib/tailwindcss-rails.rb index 2b86ff1c..bdfb592d 100644 --- a/lib/tailwindcss-rails.rb +++ b/lib/tailwindcss-rails.rb @@ -2,5 +2,6 @@ module Tailwindcss end require_relative "tailwindcss/version" +require_relative "tailwindcss/engines" require_relative "tailwindcss/engine" require_relative "tailwindcss/commands" diff --git a/lib/tailwindcss/commands.rb b/lib/tailwindcss/commands.rb index 11105dbc..99ad30e0 100644 --- a/lib/tailwindcss/commands.rb +++ b/lib/tailwindcss/commands.rb @@ -4,17 +4,18 @@ module Tailwindcss module Commands class << self def compile_command(debug: false, **kwargs) + debug = ENV["TAILWINDCSS_DEBUG"].present? if ENV.key?("TAILWINDCSS_DEBUG") rails_root = defined?(Rails) ? Rails.root : Pathname.new(Dir.pwd) command = [ Tailwindcss::Ruby.executable(**kwargs), - "-i", rails_root.join("app/assets/tailwind/application.tailwind.css").to_s, + "-i", rails_root.join("app/assets/tailwind/application.css").to_s, "-o", rails_root.join("app/assets/builds/tailwind.css").to_s, ] command << "--minify" unless (debug || rails_css_compressor?) - postcss_path = rails_root.join("config/postcss.config.js") + postcss_path = rails_root.join("postcss.config.js") command += ["--postcss", postcss_path.to_s] if File.exist?(postcss_path) command @@ -28,6 +29,12 @@ def watch_command(always: false, poll: false, **kwargs) end end + def command_env(verbose:) + {}.tap do |env| + env["DEBUG"] = "1" if verbose + end + end + def rails_css_compressor? defined?(Rails) && Rails&.application&.config&.assets&.css_compressor.present? end diff --git a/lib/tailwindcss/engine.rb b/lib/tailwindcss/engine.rb index 0c020bbc..7b88c5f1 100644 --- a/lib/tailwindcss/engine.rb +++ b/lib/tailwindcss/engine.rb @@ -6,7 +6,7 @@ class Engine < ::Rails::Engine Rails.application.config.generators.stylesheets = false end - initializer "tailwindcss.exclude_asset_path", after: "propshaft.append_assets_path" do + initializer "tailwindcss.exclude_asset_path", before: "propshaft.append_assets_path" do if Rails.application.config.assets.excluded_paths # the app may not be using Propshaft Rails.application.config.assets.excluded_paths << Rails.root.join("app/assets/tailwind") end diff --git a/lib/tailwindcss/engines.rb b/lib/tailwindcss/engines.rb new file mode 100644 index 00000000..d1d6bf63 --- /dev/null +++ b/lib/tailwindcss/engines.rb @@ -0,0 +1,23 @@ +module Tailwindcss + module Engines + class << self + def bundle + FileUtils.mkdir_p(Rails.root.join("app/assets/builds/tailwind")) + Rails::Engine.subclasses.select do |engine| + engine.root.join("app/assets/tailwind/#{engine.engine_name}/engine.css").exist? + end.each do |engine| + file_path = Rails.root.join("app/assets/builds/tailwind/#{engine.engine_name}.css") + FileUtils.rm(file_path) if File.exist?(file_path) + template = <<~TEMPLATE + /* DO NOT MODIFY THIS FILE, it was auto-generated by tailwindcss-rails */ + + @import "#{engine.root.join("app/assets/tailwind/#{engine.engine_name}/engine.css")}"; + TEMPLATE + File.open(file_path, 'w') do |file| + file.puts template + end + end + end + end + end +end diff --git a/lib/tailwindcss/version.rb b/lib/tailwindcss/version.rb index 98efde4f..d1d65d16 100644 --- a/lib/tailwindcss/version.rb +++ b/lib/tailwindcss/version.rb @@ -1,3 +1,3 @@ module Tailwindcss - VERSION = "4.0.0.rc2" + VERSION = "4.3.0.rc2" end diff --git a/lib/tasks/build.rake b/lib/tasks/build.rake index 3044ff05..d176f2cd 100644 --- a/lib/tasks/build.rake +++ b/lib/tasks/build.rake @@ -1,23 +1,36 @@ namespace :tailwindcss do desc "Build your Tailwind CSS" - task build: :environment do |_, args| + task build: [:environment, :engines] do |_, args| debug = args.extras.include?("debug") + verbose = args.extras.include?("verbose") + command = Tailwindcss::Commands.compile_command(debug: debug) - puts command.inspect if args.extras.include?("verbose") - system(*command, exception: true) + env = Tailwindcss::Commands.command_env(verbose: verbose) + puts "Running: #{Shellwords.join(command)}" if verbose + + system(env, *command, exception: true) end desc "Watch and build your Tailwind CSS on file changes" - task watch: :environment do |_, args| + task watch: [:environment, :engines] do |_, args| debug = args.extras.include?("debug") poll = args.extras.include?("poll") always = args.extras.include?("always") + verbose = args.extras.include?("verbose") + command = Tailwindcss::Commands.watch_command(always: always, debug: debug, poll: poll) - puts command.inspect if args.extras.include?("verbose") - system(*command) + env = Tailwindcss::Commands.command_env(verbose: verbose) + puts "Running: #{Shellwords.join(command)}" if verbose + + system(env, *command) rescue Interrupt puts "Received interrupt, exiting tailwindcss:watch" if args.extras.include?("verbose") end + + desc "Create Tailwind CSS entry point files for Rails Engines" + task engines: :environment do + Tailwindcss::Engines.bundle + end end Rake::Task["assets:precompile"].enhance(["tailwindcss:build"]) diff --git a/tailwindcss-rails.gemspec b/tailwindcss-rails.gemspec index 0b31c4a8..45c19c28 100644 --- a/tailwindcss-rails.gemspec +++ b/tailwindcss-rails.gemspec @@ -20,4 +20,18 @@ Gem::Specification.new do |spec| spec.add_dependency "railties", ">= 7.0.0" spec.add_dependency "tailwindcss-ruby", "~> 4.0" + + # TODO: remove this after a suitable period of time after the v4.0.0 release. + spec.post_install_message = <<~TEXT + == Upgrading to Tailwind CSS v4 == + + If you are upgrading to tailwindcss-rails 4.x, please read the upgrade guide at: + + https://github.com/rails/tailwindcss-rails/blob/main/README.md#upgrading-your-application-from-tailwind-v3-to-v4 + + If you're not ready to upgrade yet, please pin to version 3 in your Gemfile: + + gem "tailwindcss-rails", "~> 3.3.1" + + TEXT end diff --git a/test/integration/user_install_test.sh b/test/integration/user_install_test.sh index aaf00a67..bfd7a87c 100755 --- a/test/integration/user_install_test.sh +++ b/test/integration/user_install_test.sh @@ -7,7 +7,8 @@ set -eux # set up dependencies rm -f Gemfile.lock -bundle remove actionmailer +bundle remove actionmailer || true +bundle remove rails || true bundle add rails --skip-install ${RAILSOPTS:-} bundle install --prefer-local @@ -37,7 +38,7 @@ bin/rails tailwindcss:install # TEST: tailwind was installed correctly grep -q "
> Rakefile @@ -46,8 +47,8 @@ task :still_here do end EOF -cat >> app/assets/tailwind/application.tailwind.css <> app/assets/tailwind/application.css <