diff --git a/CHANGELOG.md b/CHANGELOG.md
index d0b1737c..d662d7a9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,10 +1,46 @@
# `tailwindcss-rails` Changelog
-## next / unreleased
+## v4.2.3 / 2025-05-02
-Style changes to templates:
+### Improved
+
+* 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
+
+
+## v4.2.0 / 2025-03-02
+
+### 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
diff --git a/Gemfile.lock b/Gemfile.lock
index 1e88abcd..9b0500db 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,23 +1,23 @@
PATH
remote: .
specs:
- tailwindcss-rails (4.0.0)
+ tailwindcss-rails (4.2.2)
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
@@ -69,7 +69,7 @@ GEM
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,27 +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)
- nokogiri (1.18.2)
+ net-smtp (0.5.1)
+ net-protocol
+ 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
@@ -109,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)
@@ -124,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.6)
- tailwindcss-ruby (4.0.6-aarch64-linux-gnu)
- tailwindcss-ruby (4.0.6-arm64-darwin)
- tailwindcss-ruby (4.0.6-x86_64-darwin)
- tailwindcss-ruby (4.0.6-x86_64-linux-gnu)
+ stringio (3.1.5)
+ tailwindcss-ruby (4.1.7)
+ tailwindcss-ruby (4.1.7-aarch64-linux-gnu)
+ tailwindcss-ruby (4.1.7-arm64-darwin)
+ tailwindcss-ruby (4.1.7-x86_64-darwin)
+ tailwindcss-ruby (4.1.7-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 649feb2b..158b1750 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@
- [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)
@@ -20,9 +20,10 @@
* [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)
+- [Troubleshooting](#troubleshooting)
* [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)
@@ -123,7 +124,7 @@ Then, run `bin/rails tailwindcss:upgrade`. Among other things, this will try to
- 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).
@@ -144,7 +145,7 @@ $ bin/rails tailwindcss:upgrade
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.css`
@@ -171,7 +172,7 @@ 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) 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.
@@ -195,7 +196,7 @@ With some additional manual work the upstream upgrade tool will update your appl
/node_modules
```
-**Create** a `package.json` in the root of the project:
+**Create** or **update** a `package.json` in the root of the project:
```jsonc
{
@@ -232,7 +233,9 @@ With some additional manual work the upstream upgrade tool will update your appl
Then, once you've run that successfully, clean up:
-- **Delete** `package.json`, `node_modules/` and `package-lock.json` (or `yarn.lock`), plus remove `/node_modules` from `.gitignore`.
+- **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';
@@ -273,7 +276,6 @@ 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.
@@ -286,8 +288,12 @@ The `tailwindcss:build` task is automatically attached to the `test:prepare` Rak
### 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
@@ -331,6 +337,32 @@ If you are running `rails tailwindcss:watch` in a docker container without a tty
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.
@@ -371,33 +403,66 @@ If you need to use a custom input or output file, you can run `bundle exec tailw
## 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
We've addressed the issue and you can avoid the problem by upgrading `tailwindcss-rails` to [v2.4.1](https://github.com/rails/tailwindcss-rails/releases/tag/v2.4.1) or later versions.
+
### Running in a docker container exits prematurely
If you are running `rails tailwindcss:watch` as a process in a Docker container, set `tty: true` in `docker-compose.yml` for the appropriate container to keep the watch process running.
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`.
+
### Conflict with sassc-rails
Tailwind uses modern CSS features that are not recognized by the `sassc-rails` extension that was included by default in the Gemfile for Rails 6. In order to avoid any errors like `SassC::SyntaxError`, you must remove that gem from your Gemfile.
+
### Class names must be spelled out
For Tailwind to work, your class names need to be spelled out. If you need to make sure Tailwind generates class names that don't exist in your content files or that are programmatically composed, use the [safelist option](https://tailwindcss.com/docs/content-configuration#safelisting-classes).
+
### `ERROR: Cannot find the tailwindcss executable` for supported platform
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.
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 1296be6f..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
@@ -15,7 +15,7 @@
- <%%= 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 c37333e6..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
@@ -11,7 +11,7 @@
- <%%= 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 0858f34f..1821201c 100644
--- a/lib/generators/tailwindcss/scaffold/templates/_form.html.erb.tt
+++ b/lib/generators/tailwindcss/scaffold/templates/_form.html.erb.tt
@@ -12,7 +12,7 @@
<%% end %>
<% attributes.each do |attribute| -%>
-
+
">
<% if attribute.password_digest? -%>
<%%= form.label :password %>
<%%= 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?}] %>
@@ -23,13 +23,13 @@
<%%= 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 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 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 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 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 -%>
@@ -38,6 +38,6 @@
<% 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/upgrade_tailwindcss.rb b/lib/install/upgrade_tailwindcss.rb
index 6266583a..d6ecadab 100644
--- a/lib/install/upgrade_tailwindcss.rb
+++ b/lib/install/upgrade_tailwindcss.rb
@@ -45,8 +45,14 @@
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/commands.rb b/lib/tailwindcss/commands.rb
index fb90f4f6..99ad30e0 100644
--- a/lib/tailwindcss/commands.rb
+++ b/lib/tailwindcss/commands.rb
@@ -4,6 +4,7 @@ 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 = [
@@ -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/version.rb b/lib/tailwindcss/version.rb
index 144cea79..7ab2db8d 100644
--- a/lib/tailwindcss/version.rb
+++ b/lib/tailwindcss/version.rb
@@ -1,3 +1,3 @@
module Tailwindcss
- VERSION = "4.0.0"
+ VERSION = "4.2.3"
end
diff --git a/lib/tasks/build.rake b/lib/tasks/build.rake
index 3044ff05..603c8059 100644
--- a/lib/tasks/build.rake
+++ b/lib/tasks/build.rake
@@ -2,9 +2,13 @@ namespace :tailwindcss do
desc "Build your Tailwind CSS"
task build: :environment 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"
@@ -12,9 +16,13 @@ namespace :tailwindcss do
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
diff --git a/test/integration/user_install_test.sh b/test/integration/user_install_test.sh
index df3aa8f2..bfd7a87c 100755
--- a/test/integration/user_install_test.sh
+++ b/test/integration/user_install_test.sh
@@ -61,7 +61,10 @@ fi
# TEST: presence of the generated file
bin/rails generate scaffold post title:string body:text published:boolean
-grep -q "Show this post" app/views/posts/index.html.erb
+grep -q "Show" app/views/posts/index.html.erb
+
+# TEST: the "accept_confirm" system test change was applied cleanly
+grep -q "accept_confirm { click_on \"Destroy this post\"" test/system/posts_test.rb
# TEST: contents of the css file
bin/rails tailwindcss:build[verbose]
diff --git a/test/lib/tailwindcss/commands_test.rb b/test/lib/tailwindcss/commands_test.rb
index 3c7e5302..d09481a4 100644
--- a/test/lib/tailwindcss/commands_test.rb
+++ b/test/lib/tailwindcss/commands_test.rb
@@ -33,6 +33,32 @@ def setup
end
end
+ test ".compile_command debug environment variable" do
+ begin
+ Rails.stub(:root, File) do # Rails.root won't work in this test suite
+ ENV["TAILWINDCSS_DEBUG"] = ""
+ actual = Tailwindcss::Commands.compile_command
+ assert_kind_of(Array, actual)
+ assert_includes(actual, "--minify")
+
+ actual = Tailwindcss::Commands.compile_command(debug: true)
+ assert_kind_of(Array, actual)
+ assert_includes(actual, "--minify")
+
+ ENV["TAILWINDCSS_DEBUG"] = "any non-blank value"
+ actual = Tailwindcss::Commands.compile_command
+ assert_kind_of(Array, actual)
+ refute_includes(actual, "--minify")
+
+ actual = Tailwindcss::Commands.compile_command(debug: true)
+ assert_kind_of(Array, actual)
+ refute_includes(actual, "--minify")
+ end
+ ensure
+ ENV.delete('TAILWINDCSS_DEBUG')
+ end
+ end
+
test ".compile_command when Rails compression is on" do
Rails.stub(:root, File) do # Rails.root won't work in this test suite
Tailwindcss::Commands.stub(:rails_css_compressor?, true) do