phoenixframework/tailwind

repository·main·Indexed 19 days ago

https://github.com/phoenixframework/tailwind

A Mix wrapper for the Tailwind CSS standalone CLI that provides installation, configuration, and integration for Elixir and Phoenix applications. It supports managing the Tailwind binary via Mix tasks or npm, defining execution profiles for different build settings, and provides specific integration guides for Tailwind v4 in Phoenix 1.8+ applications.

Tokens
3.5K
Snippets
13
Records
15
Agent score
60%

What's inside phoenixframework-tailwind

  1. Add Tailwind v4 to a Phoenix application

    main

    To integrate Tailwind v4 into a Phoenix application (version 1.8+):

    1. Dependencies: Add :tailwind to mix.exs with runtime: Mix.env() == :dev.
    2. Deployment: Add tailwind default --minify to your assets.deploy alias in mix.exs.
    3. Configuration: In config/config.exs, define the default profile with --input and --output paths. Ensure the output directory is served by Plug.Static in your endpoint.
    4. Umbrella Projects: If using an umbrella, set cd to the web application's directory.
    5. Development Watcher: Add the Tailwind watcher to config/dev.exs using Tailwind.install_and_run with the --watch flag.
    6. CSS Setup: Create assets/css/app.css using @import "tailwindcss"; and define @source paths to prevent excessive file watching.
    # mix.exs
    "assets.deploy": ["tailwind default --minify", ..., "phx.digest"]
    # config/config.exs
    config :tailwind,
      version: "4.3.0",
      default: [
        args: ~
          w(
            "--input=assets/css/app.css"
            "--output=priv/static/assets/css/app.css"
          ),
        cd: Path.expand("..", __DIR__)
      ]
    # config/dev.exs
    tailwind: {Tailwind, :install_and_run, [:default, ~w(--watch)]}
    /* assets/css/app.css */
    @import "tailwindcss";
    @source "../css";
    @source "../js";
    @source "../../lib/YOUR_APP_web";
    
    @custom-variant phx-click-loading (.phx-click-loading&, .phx-click-loading &);
    @custom-variant phx-submit-loading (.phx-submit-loading&, .phx-submit-loading &);
    @custom-variant phx-change-loading (.phx-change-loading&, .phx-change-loading &);
  2. Update from Tailwind v3 to v4

    main

    To upgrade a Phoenix application from Tailwind v3 to v4:

    1. Update Library: Change :tailwind dependency version to ~> 0.3.
    2. Update Config:
      • Change version to 4.3.0 (or higher).
      • Update args to use the new input/output paths.
      • Change cd to the project root (or web app root in umbrellas) so Tailwind can auto-detect sources.
    3. Update CSS: Replace the old three-part @import (base, components, utilities) with a single @import "tailwindcss";.
    4. Cleanup: Follow the official Tailwind v4 upgrade guide for deprecations and optionally remove tailwind.config.js in favor of CSS-based configuration.
    # config/config.exs migration
    config :tailwind,
      version: "4.3.0",
      default: [
        args: ~
          w(
            "--input=assets/css/app.css"
            "--output=priv/static/assets/css/app.css"
          ),
        cd: Path.expand("..", __DIR__)
      ]
    /* assets/css/app.css migration */
    @import "tailwindcss";
  3. Install Tailwind via Mix

    main

    To use the standalone Tailwind CLI in an Elixir project, add :tailwind as a dependency. It is recommended to set runtime: Mix.env() == :dev so it only runs in development environments.

    After adding the dependency, configure your desired Tailwind version in config/config.exs. Note that :tailwind 0.3+ defaults to Tailwind v4.

    Run mix tailwind.install to download the binary. If your platform is not supported, you can provide a URL to a third-party binary.

    # In mix.exs
    def deps do
      [ {:tailwind, "~> 0.3", runtime: Mix.env() == :dev} ]
    end
    
    # In config/config.exs
    config :tailwind, version: "4.3.0"
    # Install the binary
    $ mix tailwind.install
    
    # Or install from a specific URL
    $ mix tailwind.install https://people.freebsd.org/~dch/pub/tailwind/v3.2.6/tailwindcss-freebsd-x64
  4. Use Tailwind CLI from npm

    main

    If you prefer using the Tailwind CLI via NPM instead of the standalone binary, follow these steps:

    1. Install tailwindcss, @tailwindcss/cli, and any plugins (like daisyui) into your assets/ directory using npm.
    2. Update config/config.exs to disable the version check and point the path to the node_modules binary.
    3. Update your assets/css/app.css to use standard npm plugin imports instead of vendored paths.
    4. Remove any vendored JS files from assets/vendor/.
    # 1. Install via npm
    $ npm i --prefix assets -D tailwindcss @tailwindcss/cli daisyui
    # 2. Update config/config.exs
    config :tailwind,
      version_check: false,
      path: Path.expand("../assets/node_modules/.bin/tailwindcss", __DIR__)
    /* 3. Update assets/css/app.css */
    @plugin "daisyui" {
    }
    
    @plugin "daisyui/theme" {
    }
  5. How Tailwind profiles and versions work

    main

    The Tailwind module manages the lifecycle of the Tailwind CLI binary.

    1. Version Resolution: When a profile is used, the module first looks for a :version key within that profile. If not found, it falls back to the global :version setting. If that is also missing, it uses the library's internal latest_version/0.
    2. Binary Location: By default, binaries are stored in _build/tailwind-<target>-<version>. If a global :path is configured, the library uses that single executable for all profiles.
    3. Compatibility Constraint: You cannot mix a global :path (which implies a single fixed executable) with per-profile :version settings. Doing so will raise an ArgumentError at application boot.
  6. Configure Tailwind execution profiles

    main

    Tailwind execution profiles allow you to define multiple sets of arguments, working directories (cd), and environment-specific settings in config/config.exs.

    When you run mix tailwind <profile_name>, the task uses the arguments defined for that profile. The default profile is used when no name is provided.

    config :tailwind,
      version: "4.3.0",
      default: [
        args: ~
          w(
            "--input=assets/css/app.css"
            "--output=priv/static/assets/css/app.css"
          ),
        cd: Path.expand("..", __DIR__)
      ]
  7. Use an npm-managed Tailwind CLI

    main

    If you prefer to manage Tailwind via npm instead of letting the library download it, install the CLI in your assets directory and point the :path configuration to the node_modules binary. You should also set :version_check to false to prevent the library from attempting to download its own version.

    1. Install via npm:

      npm install tailwindcss @tailwindcss/cli
    2. Configure in Elixir:

    config :tailwind,
      version: "4.3.0",
      version_check: false,
      path: Path.expand("../assets/node_modules/.bin/tailwindcss", __DIR__),
      default: [
        args: ~w(--input=assets/css/app.css --output=priv/static/assets/app.css),
        cd: Path.expand("..", __DIR__),
      ]
  8. Install the Tailwind executable via mix tailwind.install

    main

    Use the mix tailwind.install task to download and install the Tailwind standalone binary and assets into your project. By default, it installs the latest version, but you can control the version or provide a custom download URL.

    Usage

    Standard installation:

    mix tailwind.install

    Install only if the binary is missing:

    mix tailwind.install --if-missing

    Install from a custom URL: If your platform is not officially supported, you can provide a third-party URL. Note that the URL must be able to resolve the $version and $target placeholders (e.g., for FreeBSD or other custom distributions).

    mix tailwind.install https://people.freebsd.org/~dch/pub/tailwind/$version/tailwindcss-$target
  9. Configure Tailwind profiles and global settings

    main

    Tailwind uses Elixir configuration to manage versions, build arguments, and execution paths. You can define a global configuration and multiple named profiles (e.g., :default).

    Global Configuration Keys

    • :version - The expected Tailwind version (e.g., "4.3.0").
    • :version_check - Boolean. If true (default), the library checks if the downloaded binary matches the configured version. Set to false if managing the binary externally (e.g., via npm).
    • :path - The absolute path to the Tailwind executable. If not set, the library automatically downloads and manages the binary in your _build directory.
    • :target - The target architecture (e.g., "linux-x64-musl"). Automatically detected if not provided.

    Profile Configuration

    Profiles allow you to define different build settings for different contexts. A profile is a keyword list containing:

    • args: A list of CLI arguments (e.g., --input, --output).
    • cd: The current working directory for the command.
    • version: (Optional) Overrides the global version for this specific profile. Note: If you set a global :path, you cannot use per-profile :version settings because :path points to a single executable.
    • env: (Optional) A map of environment variables to pass to the CLI.
    config :tailwind,
      version: "4.3.0",
      default: [
        args: ~w(--input=assets/css/app.css --output=priv/static/assets/app.css),
        cd: Path.expand("..", __DIR__),
      ]
  10. Install and run Tailwind via `Tailwind.install_and_run/2`

    main

    This helper function ensures the Tailwind binary for the configured version exists. If the binary is missing, it downloads it from the official Tailwind releases before executing the command.

    Signature: install_and_run(profile, args)

    # Downloads the binary if missing, then runs with watch mode
    Tailwind.install_and_run(:default, ["--watch"])
  11. Run Tailwind CLI via `Tailwind.run/2`

    main

    Execute the Tailwind CLI using a specific profile and additional arguments. The arguments provided in extra_args are appended to the args defined in the profile configuration. Output is streamed directly to stdio.

    Signature: run(profile, extra_args) where profile is an atom and extra_args is a list of strings.

    # Runs the :default profile with an extra flag
    Tailwind.run(:default, ["--watch"])