Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Discussion options

importmap-rails and propshaft do not require node and yarn to be installed, although cssbundling-rails requires.

Are there any options to patch ActiveAdmin to have no dependence on node/yarn?

References:

You must be logged in to vote

Replies: 14 comments · 52 replies

Comment options

Hi @amkisko. First and foremost, thank you for creating a discussion. This may be doable from some past experimenting so I will share my thoughts on how I think it could work but it's not something that the library will support. I know some others are interested in this as well.

You would have to use and customize tailwindcss-rails since it is designed for a single entrypoint file. You could install that gem and start copying it's tasks to work with the tailwind-active_admin.config.js file or if you aren't using Tailwind in your app, and only plan to do so with ActiveAdmin, then just update the files to work directly with the tailwindcss-rails defaults, assuming your application styles can live in a different named entrypoint file.

From there, you'll have to copy the plugin.js file to the root of your project and keep it up to date. Since you don't want to run Node, you will need that file locally because we provide some CSS through a Tailwind plugin and for the standalone CLI to run that plugin, it has to be relative/local. I've tried executing it from the gem path since it's included in the gem but it fails with an error. Then update your config to require the relative file require("./plugin") and it may work.

Resources:

You must be logged in to vote
1 reply
@amkisko
Comment options

Thanks, sounds promising. First thought was if it is possible to use importmap-rails for fetching artefacts out from tailwindcss-rails... seems to be not that straight forward thing.

To me it seems that with ActiveAdmin v4 got strong requirement of node due to cssbundling-rails only, but previously it was possible to detach from node, using propshaft and importmap-rails for example. 🤔

Reasons to switch to Tailwind are quite clear.

Comment options

...

Would it be possible to get some kind of example app or at least more detailed solution? I'm trying to setup exactly this, but still struggling and can't quite make it work. What should we put in this config file, is there a need for another tailwind css file besides generated one and where from to call require plugin... I'm doing something wrong, but not sure what.
Thanks!

You must be logged in to vote
0 replies
Comment options

@amkisko @djolereject @javierjulio

This is what I did as part of my upgrade from ActiveAdmin 3.x to the latest 4.0 (beta.4).

I took inspiration in the tailwindcss-rails code and basically used the same pattern, which together with Procfile.dev makes my rails setup completely node less.

I think this also could be a good default for ActiveAdmin, since I think many are wanting to not have node installed when developing with Rails (dartsass-rails, tailwindcss-rails, mrml-rails are examples of this)

How to do it

  1. I moved tailwind-active_admin.config.js into the config/ directory. Since the other config from tailwindcss-rails is there.
  2. Changed the plugin require statement to require(${activeAdminPath}/plugin.js) since the code is in the gem anyways, and the path is already resolved. This way I don't need to maintain anything separately.
  3. Then I ran bundle binstub tailwindcss so that I get a bin/tailwindcss bin script
  4. Dumped the following into lib/tasks/active_admin.rb https://gist.github.com/henrikbjorn/cf9ab168bb6ff9195691d7add5cb7d1b It will hook into the precompile tasks (as tailwindcss-rails)
  5. Into Procfile.dev add a line active_admin: bin/rails active_admin:watch.
  6. 🥳
You must be logged in to vote
14 replies
@amkisko
Comment options

Yes, I saw this one and tried to hook into ActiveAdmin importmap without proper success. Probably it should be done in combination with javascript_import_module_tag "application" after javascript_importmap_tags. Resolved by fully copying javascript from ActiveAdmin and having custom importmap class.

@henrikbjorn
Comment options

@amkisko you should be able to just pin stuff into it there. No need for anything custom

@amkisko
Comment options

Works perfect! Thanks @henrikbjorn!

In views/active_admin/_html_head.html.erb:

<%= javascript_importmap_tags "active_admin", importmap: ActiveAdmin.importmap %>
<%= javascript_import_module_tag "application" %>

In config/initializers/active_admin.rb:

ActiveAdmin.importmap.draw do
  pin "@rails/actioncable", to: "actioncable.esm.js", preload: true
  pin "@rails/activestorage", to: "activestorage.esm.js", preload: true

  pin "@hotwired/turbo-rails", to: "turbo.js", preload: true
  pin "@hotwired/stimulus", to: "stimulus.js", preload: true
  pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true

  pin "application", preload: true
  pin_all_from "app/assets/javascripts/controllers", under: "controllers"
end

ActiveAdmin.setup do |config|
  ...
end
@ryanckulp
Comment options

nice work @henrikbjorn ! just a couple things:

  1. your docs (Step 4) should say lib/tasks/active_admin.rake vs .rb
  2. the task itself is not super DRY and also does not take advantage of minification; slightly better gist here

thanks again!

@RathanKumar
Comment options

If anyone is facing issue while running bin/dev after updating Procfile.dev. I noticed that bundle binstub tailwindcss-rails doesn't add tailwindcss binary into bin. Instead, try bundle binstub tailwindcss-ruby

Comment options

Thank for the detailed explanation!

You must be logged in to vote
0 replies
Comment options

What is the suggestion on extending header and layout of ActiveAdmin v4?

That's what I been up to before:

module AdminPageLayoutOverride
  def build_page(*args)
    within super do
      render "active_admin/layout_additions"
    end
  end

  def build_active_admin_head
    within super do
      render "active_admin/header"
    end
  end
end

ActiveAdmin::Views::Pages::Base.prepend AdminPageLayoutOverride
You must be logged in to vote
1 reply
@henrikbjorn
Comment options

Overwrite the partials that you can get from bin/rails g active_admin:views

Comment options

This thread might become a more general "migration to v4" topic.

I've got another one, that can't figure out how to fix, getting this for all resources except custom pages:

No route matches {:action=>"index", :controller=>"active_admin/users", :format=>:csv}
No route matches {:action=>"index", :controller=>"active_admin/user_metrics"}
You must be logged in to vote
2 replies
@amkisko
Comment options

This one happens during migration from v3 to v4. Does not happen in the project started from scratch.

@amkisko
Comment options

This one is resolved, details here: #8279

Comment options

Also it was not really clear how main_app variable change affects the migration, basically I started using it everywhere for all routes paths, even this one:

# PATH: config/initializers/active_admin.rb
ActiveAdmin.setup do |config|
  ...
  config.logout_link_path = ->(*) { main_app.destroy_user_session_path }
  ...
end
You must be logged in to vote
0 replies
Comment options

It would be much easier if you just shipped bundled versions of active_admin.css. Having strict dependency on cssbundling-rails and tailwind to build CSS for third party library in the host app sounds weird. It will make adoption of new version harder. Personally, I very rarely have the need to customize ActiveAdmin CSS and I would rather add regular CSS classes when necessary.

Here's an example of how Avo solves it:
https://avohq.io/blog/how-to-bundle-assets-in-a-rails-engine

But it can be even simpler. Just a pre-commit hook that will run tailwind building and save the output into app/assets/stylesheets/active_admin.css.

You must be logged in to vote
2 replies
@javierjulio
Comment options

@kirillplatonov it would not have been easier. From your perspective but not from the library's. There are more Rails asset management libraries now than before which means more possible combinations of them and others expect each to just work without much effort. That's difficult and time consuming to figure out how to get each implemented (e.g. you may not be familiar with some) and then also having each tested in an engine. It doesn't sound weird at all when you put yourself in the shoes of someone that actually has to do the work.

I've read their approach before I started working on v4 last year. I made a deliberate choice to not do that. Compiling the library CSS in advance is a bad choice as styles can clash with the parent app (ordering, colors, etc.). While you may not want to make changes, others do. The approach they shared works well for a library UI that you wouldn't need to make changes. If I recall right, the inspiration for that approach came from Sidekiq. In my research, GoodJob does something similar as well.

@jaynetics
Comment options

There is a now gem that does this, see my answer below.

Comment options

@javierjulio what is the current support level for Turbo in ActiveAdmin? At least I have not seen any traces of usage here. One thing that does not properly work is form errors, there is a reply from server but HTML code from response is not applied to the current page, I've been experiencing such starting from v3. Have you seen such behaviour?

You must be logged in to vote
18 replies
@amkisko
Comment options

So I decided to go with <body data-turbo="false" for ActiveAdmin layout.

@hoquandai
Comment options

Hi @amkisko,
ActiveAdmin is using Flowbite.js version which is not compatible with Turbo, code line.
Therefore, you should consider to override the pinned package with the new one played well with Turbo, here.

# active_admin.rb

### Example:

########### ACTIVEADMIN IMPORTMAP ###########

ActiveAdmin.after_load do
  ActiveAdmin.importmap.draw do
    pin "application"
    pin "flowbite", to: "flowbite.turbo.min.js" # <- Override flowpite
    pin "@hotwired/turbo-rails", to: "turbo.min.js"
    pin "@hotwired/stimulus", to: "stimulus.min.js"
    pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
    pin_all_from "app/javascript/controllers", under: "controllers"
  end
end

############################################
@amkisko
Comment options

Thanks @hoquandai, probably this fix even eligible for Pull Request here? I have not thought in details and I am already aware that ActiveAdmin v4 works well with Rails 6 (no Turbo), so there might be some things that should be considered for such changes.

@jsntv200
Comment options

The following has been working for me with the benefit of retaining rails default behaviour for pinning and avoids duplication:

ActiveAdmin.after_load do
  ActiveAdmin.importmap.draw(Rails.root.join("config/importmap.rb"))
  ActiveAdmin.importmap.cache_sweeper(watches: [ Rails.root.join("app/javascript") ])
end

As a side note there's currenlty 2 open PR's for import-map rails to handle multiple imports:
rails/importmap-rails#241
rails/importmap-rails#253

@amkisko
Comment options

@jsntv200 thanks for sharing, one obvious problem is that all the pins from default importmap.rb will leak to activeadmin side too, sometimes it makes sense to split them, especially when there are possible naming conflicts.

Comment options

I've made a gem to allow running ActiveAdmin v4 without any asset setup: activeadmin_assets. Please note that it limits customizability as described in the README.

You must be logged in to vote
2 replies
@henrikbjorn
Comment options

Smart!

@atsjj
Comment options

This is excellent! Thanks for the gem!

Comment options

I wanted to get ActiveAdmin v4 (beta13) working with Rails v8.0.0, using tailwindcss-rails and importmaps-rails - so I didn't have to run a separate node / npm process.

In my case I wasn't using tailwind for anything else, and rails is mostly being used just as an API.

This is what I had to do:

  • install activeadmin, tailwindcss-rails and importmap-rails gems per their instructions

  • Move the activeadmin tailwind config to same location tailwindcss-rails puts theirs:

      mv tailwind-active_admin.config.js config/tailwind-active_admin.config.js
    
  • Make small alteration to tailwind-active_admin.config.js to get the plugin path correct

    const execSync = require('child_process').execSync;
    const activeAdminPath = execSync('bundle show activeadmin', { encoding: 'utf-8' }).trim();
    
    module.exports = {
      content: [
        `${activeAdminPath}/vendor/javascript/flowbite.js`,
        `${activeAdminPath}/plugin.js`,
        `${activeAdminPath}/app/views/**/*.{arb,erb,html,rb}`,
        './app/admin/**/*.{arb,erb,html,rb}',
        './app/views/active_admin/**/*.{arb,erb,html,rb}',
        './app/views/admin/**/*.{arb,erb,html,rb}',
        './app/views/layouts/active_admin*.{erb,html}',
        './app/javascript/**/*.js'
      ],
      darkMode: "selector",
      plugins: [
        // Need to correct path to plugin.js
        // require(`@activeadmin/activeadmin/plugin`)
        require(`${activeAdminPath}/plugin`)
      ]
    }
  • tailwindcss-rails has a few different ways to compile the tailwind css. I wanted to use the puma plugin, so need to override the command the puma-plugin uses so it would compile the ActiveAdmin tailwind files, rather than the tailwindcss-rails default.

    Presumably if you wanted both the default tailwindcss and activeadmin's tailwindcss, you'd do this a bit different - maybe the foreman Procfile.dev method would work better. But this worked for the puma plugin:

    Create this initializer:

    module TailwindCommandsOverride
      def compile_command(debug: false, **kwargs)
        command = [
          Tailwindcss::Ruby.executable(**kwargs),
          "-i", Rails.root.join("app/assets/stylesheets/active_admin.css").to_s,
          "-o", Rails.root.join("app/assets/builds/active_admin.css").to_s,
          "-c", Rails.root.join("config/tailwind-active_admin.config.js").to_s
        ]
    
        command << "--minify" unless debug || rails_css_compressor?
    
        postcss_path = Rails.root.join("config/postcss.config.js")
        command += [ "--postcss", postcss_path.to_s ] if File.exist?(postcss_path)
    
        command
      end
    end
    
    module Tailwindcss
      module Commands
        class << self
          prepend TailwindCommandsOverride
        end
      end
    end
    # config/puma.rb
    plugin :tailwindcss if ENV.fetch("RAILS_ENV", "development") == "development"
  • The ActiveAdmin import maps was a bit convoluted. First pin the package:

    bin/importmap pin @activeadmin/activeadmin
    
  • But the version of poppover downloaded doesn't include all the ESM modules, so need to download a different version that does. Also note the + character in the filename mucks the importmap up, so that needs to be renamed too:

    bin/importmap pin @popperjs/core@2.11.8/+esm  --from jsdelivr
    rm vendor/javascript/@popperjs--core.js
    mv vendor/javascript/@popperjs--core--+esm.js vendor/javascript/@popperjs--core.js
    
  • For some reason poppover doesn't load with the rest of the other importmaps when starting ActiveAdmin, so need to also tell activeadmin to explicitly load it, put this in an initializer

    ActiveAdmin.importmap.draw do
      pin "@popperjs/core", to: "@popperjs--core.js" # @2.11.8
    end
    

After that, I have a working ActiveAdmin installation, using tailwindcss-rails and importmap-rails. Hopefully the process could be simplfied in the future!

You must be logged in to vote
4 replies
@amkisko
Comment options

What's the reason to pin @activeadmin/activeadmin to main importmap? They are not used in ActiveAdmin layout as far as I understand.

@Fire-Dragon-DoL
Comment options

I would love some guidance too. I'm trying to use importmaps and my head hurts, for simplifying things it looks actually way more complicated.

@Fire-Dragon-DoL
Comment options

OK, I think I got it. ActiveAdmin uses its own defined importmap which the user can't really set things to.
This importmap is used in the main activeadmin layout, I suspect this is the place where user can add more custom JS.

Adding pin "@activeadmin/activeadmin", to: "@activeadmin--activeadmin.js" # @4.0.0-beta15 to your own config/importmap.rb file is a mistake that can/will load incorrect nested packages versions. This is why my flowbite was trying to load @popperjs/core, because it was an incorrect version, replacing the activeadmin one.

The solution was easy:

  • Do not put anything in your own importmap.rb
  • Do install @activeadmin/activeadmin package in package.json, you need that for CSS, not for JS
@amkisko
Comment options

A little corrections:

Do not put anything in your own importmap.rb

You don't have to put anything for ActiveAdmin in config/importmap.rb, ActiveAdmin has own importmap definition, you can find hints here in this thread.

Do install @activeadmin/activeadmin package in package.json, you need that for CSS, not for JS

You don't have to do this, you can fully avoid nodejs usage for ActiveAdmin v4.

Also you can append ActiveAdmin importmap with things you want to have there available, e.g. echarts or other javascript files/libraries.

Comment options

I have read through several conversations here about that subject, but I could figure it out.

My app was created with rails new . --database=postgresql --css=tailwind. So it uses propshaft.

Before Rails 8 (with sprocket), I could do the following to have ActiveAdmin work with Tailwind + SCSS

  • In Gemfile
...
gem "activeadmin", "~> 3.2"
gem "sass-rails", "~> 6.0"
  • active_admin.scss was moved to vendor/assets/stylesheets (can't remember why).
  • In config/initializers/sassc_monkeypatch_for_tailwind.rb
module SassCompressorMonkeypatch
  def call_processor(processor, input)
    super
  rescue SassC::SyntaxError => e
    raise unless processor == Sprockets::SassCompressor
    puts "Warning: Could not compress #{input[:filename]} with Sprockets::SassCompressor. Returning uncompressed result." unless Rails.env.test?
    metadata = (input[:metadata] || {}).dup
    metadata[:data] = input[:data]
    metadata
  end
end
Sprockets::Base.prepend(SassCompressorMonkeypatch)

With Rails 8.0.0 (with propshaft), It seems I have to use the beta and I saw activeadmin_assets.

  • In Gemfile
gem 'activeadmin', '~> 4.0.0.beta7'
gem 'activeadmin_assets'

I might have done it wrong, but that didn't work out. So for now, I have no Idea how to use ActiveAdmin with Rails 8.0.0 (+ propshaft). :(

Is there a resource written somewhere that could guide me through the steps?

You must be logged in to vote
2 replies
@jaynetics
Comment options

hi! author of activeadmin_assets here. its not an official solution, so any issues are best posted in its repo. that being said, it works fine in a fresh rails 8 app, with or without propshaft, and with or without --css=tailwind. maybe you need to remove special asset setup or asset-related patches.

@amkisko
Comment options

There are multiple working solutions and options mentioned in this discussion, just select one of and follow it. Especially if you start from scratch, just follow the instructions from the beginning. I use the one I created (which works for Rails 8 too): https://gist.github.com/amkisko/c704c1a6462d573dfa4820ae07d807a6 -- there are things that I would already improve, but it does not matter for now.

Comment options

Rails developer for 10+ years here. I just want to express that it's 2025 and I'm struggling to set this up.

Rails is going in the direction of simplifying things, but active admin v4 seems to be going in the opposite direction. Adding a dependency on cssbundling-rails doesn't feel great.

You must be logged in to vote
4 replies
@henrikbjorn
Comment options

Just use tailwindcss-rails and the instructions above with the additional rake tasks. Works great for 5+ projects I have done it on.

Otherwise if you are willing, then vite_rails is great.

@tagliala
Comment options

Side note: tailwindcss-rails v3, the latest released version will install v4, which is not yet compatible with Active Admin. Ref #8621

@henrikbjorn
Comment options

@tagliala Add tailwindcss-ruby with the correct constraint ~> 3.4.0

TailwindcssRuby versions follow the released tailwind versions.

@amkisko
Comment options

Struggling here mostly related to lack of understanding how importmap and tailwindcss bundling works with Rails, once you get it - no more struggling. Basically studying/reading propshaft, importmap, tailwindcss-rails sources will help a lot. ActiveAdmin v4 does not do anything in addition.

I confirm too that "node-less" setup works, I went through it in multiple projects (some with fresh v4, some migrated from v3) which are already in production with real users.

Comment options

In case someone tries to set it up with Tailwindcss v4, tailwind-active_admin.config.js can be migrated to app/assets/stylesheets/active_admin.css as follows (given bundle gems location at vendor/bundle/ruby/xx/gems):

@import 'tailwindcss' source(none);
@source '../../../vendor/bundle/ruby/3.4.0/gems/activeadmin-4.0.0.beta15/vendor/javascript/flowbite.js';
@source '../../../vendor/bundle/ruby/3.4.0/gems/activeadmin-4.0.0.beta15/app/views';
@plugin '../../../vendor/bundle/ruby/3.4.0/gems/activeadmin-4.0.0.beta15/plugin.js';
@source '../../../vendor/bundle/ruby/3.4.0/gems/activeadmin-4.0.0.beta15/plugin.js';
/* add other @source tags from tailwind-active_admin.config.js if necessary */

As you see, I used ruby 3.4.0 and activeadmin-4.0.0.beta15. After this, the js config file can be deleted.
active_admin.rake from https://medium.com/@henrikbjorn/til-how-to-use-activeadmin-v4-without-installing-nodejs-ccdaf3ace005 can also be slightly updated by removing -c arg for both tasks.

It is not useful to add @source to folders in app/ because, when using tailwindcss v4 with rails, tailwindcss scans most files in the project already, including all of app/.

You must be logged in to vote
2 replies
@Olzhassss
Comment options

Also I noticed that sourcing plugin.js fails because tailwindcss v4 encounters unknown class ring-opacity-5, so this class would have to be manually removed from the file for this to work.

@amkisko
Comment options

ActiveAdmin tailwind v3 plugin is not compatible with tailwind v4, it requires full rewrite.

Partially working example available here: https://gist.github.com/amkisko/af1b2f7dc4f0f941437ea16400277864 (you may use any genai-powered editor to complete this and even maybe contribute if you want)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
🙏
Help
Labels
None yet
Morty Proxy This is a proxified and sanitized view of the page, visit original site.