0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Rails8でactiveadmin v4 (beta 15) with tailwindcss v4 を試してみる

Posted at

タイトル通りの内容です。
Rails8 を試してみてたところactive adminが必要になりactiveadminのリポジトリをみたらv4がベータリリースされてたので試してみました。(tailwindcss v4は既に導入済み)
スクリーンショット 2025-03-24 17.43.57.png

執筆時点(2025/03/24)ではまだrails8, tailwindcss v4は未対応でベータ版をgemfileに追加しても正しく動作してくれないのでその修正方法です。

  • Ruby on Rails 8 (執筆時点 v8.0.2)
  • Tailwindcss v4 (執筆時点 v4.2.1)
  • Activeadmin (執筆時点 4.0.0.beta15)

通常通りgemfileに gem "activeadmin", "4.0.0.beta15" を追加した後、rails g active_admin:install をします。
その後いくつかのファイルを修正します。

変更点は以下です。

activeadmin gem内

app/views/app/views/active_admin/_html_head.html.erb
- <%= stylesheet_link_tag "active_admin" %>
+ <%= stylesheet_link_tag :active_admin %>
lib/generators/active_admin/assets/templates/active_admin.css
- @tailwind base;
- @tailwind components;
- @tailwind utilities;
+ @import "tailwindcss";

+ /* @config "../../../config/tailwind-+ active_admin.config.js"; */
+ @config "path/to/tailwind-active_admin.config.js";
lib/generators/active_admin/assets/templates/tailwind.config.js
- import { execSync } from 'child_process';
- import activeAdminPlugin from '@activeadmin/activeadmin/plugin';
-
- const activeAdminPath = execSync('bundle show activeadmin', { encoding: 'utf-8' }).trim();
-
- export default {
-  content: [
-    `${activeAdminPath}/vendor/javascript/flowbite.js`,
-    `${activeAdminPath}/plugin.js`,
+ execSync = require('child_process').execSync;
+ const activeAdminPath = execSync('bundle show activeadmin', { encoding: 'utf-8' }).trim();
+ const activeAdminPlugin = require(`${activeAdminPath}/plugin.js`).default;
+
+ module.exports = {
+  content: [
+    `${activeAdminPath}/vendor/javascript/flowbite.js`,
+    `${activeAdminPath}/plugin.js`,
lib/generators/active_admin/install/install_generator.rb
+      # def create_migrations
+      # ...
+      # end
+      
+      # create_migrationsブロックの下に追加
+      def copy_stylesheets
+        template "active_admin.css", "app/assets/stylesheets/active_admin.css"
+      end
plugin.js (長いので折りたたんでいます。差分は割愛)
plugin.js
import plugin from 'tailwindcss/plugin';
import defaultTheme from 'tailwindcss/defaultTheme';
import colors from 'tailwindcss/colors';
const { spacing, borderWidth, borderRadius } = defaultTheme;

// https://github.com/tailwindlabs/tailwindcss/discussions/9336
// https://github.com/tailwindlabs/tailwindcss/discussions/2049
// https://github.com/tailwindlabs/tailwindcss/discussions/2049#discussioncomment-45546

const svgToTinyDataUri = (() => {
  // Source: https://github.com/tigt/mini-svg-data-uri
  const reWhitespace = /\s+/g,
    reUrlHexPairs = /%[\dA-F]{2}/g,
    hexDecode = { '%20': ' ', '%3D': '=', '%3A': ':', '%2F': '/' },
    specialHexDecode = match => hexDecode[match] || match.toLowerCase(),
    svgToTinyDataUri = svg => {
      svg = String(svg);
      if (svg.charCodeAt(0) === 0xfeff) svg = svg.slice(1);
      svg = svg
        .trim()
        .replace(reWhitespace, ' ')
        .replaceAll('"', '\'');
      svg = encodeURIComponent(svg);
      svg = svg.replace(reUrlHexPairs, specialHexDecode);
      return 'data:image/svg+xml,' + svg;
    };
  svgToTinyDataUri.toSrcset = svg => svgToTinyDataUri(svg).replace(/ /g, '%20');
  return svgToTinyDataUri;
})();

export default plugin(
  function({ addBase, addComponents, theme }) {
    addBase({
      [[
        "[type='text']",
        "[type='email']",
        "[type='url']",
        "[type='password']",
        "[type='number']",
        "[type='date']",
        "[type='datetime-local']",
        "[type='month']",
        "[type='search']",
        "[type='tel']",
        "[type='time']",
        "[type='week']",
        'textarea',
        'select',
      ]]: {
        appearance: 'none',
        'background-color': '#fff',
        'border-color': theme('colors.gray.500', colors.gray[500]),
        'border-width': borderWidth['DEFAULT'],
        'border-radius': borderRadius.none,
        'padding-top': spacing[2],
        'padding-right': spacing[3],
        'padding-bottom': spacing[2],
        'padding-left': spacing[3],
        '--tw-shadow': '0 0 #0000',
        '&:focus': {
          outline: '2px solid transparent',
          'outline-offset': '2px',
          '--tw-ring-inset': 'var(--tw-empty,/*!*/ /*!*/)',
          '--tw-ring-offset-width': '0px',
          '--tw-ring-offset-color': '#fff',
          '--tw-ring-color': theme(
            'colors.blue.600',
            colors.blue[600]
          ),
          '--tw-ring-offset-shadow': `var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)`,
          '--tw-ring-shadow': `var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)`,
          'box-shadow': `var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)`,
          'border-color': theme('colors.blue.600', colors.blue[600]),
        },
      },
      [['input::placeholder', 'textarea::placeholder']]: {
        color: theme('colors.gray.500', colors.gray[500]),
        opacity: '1',
      },
      ['::-webkit-datetime-edit']: {
        display: 'inline-flex',
      },
      [[
        '::-webkit-datetime-edit',
        '::-webkit-datetime-edit-year-field',
        '::-webkit-datetime-edit-month-field',
        '::-webkit-datetime-edit-day-field',
        '::-webkit-datetime-edit-hour-field',
        '::-webkit-datetime-edit-minute-field',
        '::-webkit-datetime-edit-second-field',
        '::-webkit-datetime-edit-millisecond-field',
        '::-webkit-datetime-edit-meridiem-field',
      ]]: {
        'padding-bottom': '0',
        'padding-top': '0',
      },
      ['::-webkit-date-and-time-value']: {
        'min-height': '1.5em',
        'text-align': 'inherit',
      },
      ['select']: {
        'background-image': `url("${svgToTinyDataUri(
          `<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
            <path stroke="${theme('colors.gray.500', colors.gray[500])}" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
          </svg>`
        )}")`,
        'background-position': `right ${spacing[3]} center`,
        'background-repeat': `no-repeat`,
        'background-size': `0.75em 0.75em`,
        'padding-inline-end': spacing[8],
        'print-color-adjust': `exact`,
      },
      [':is(:where([dir=rtl]) select)']: {
        'background-position': `left ${spacing[3]} center`,
      },
      ['[multiple]']: {
        'background-image': 'initial',
        'background-position': 'initial',
        'background-repeat': 'unset',
        'background-size': 'initial',
        'padding-inline-end': spacing[3],
        'print-color-adjust': 'unset',
      },
      [[`[type='checkbox']`, `[type='radio']`]]: {
        appearance: 'none',
        padding: '0',
        'print-color-adjust': 'exact',
        display: 'inline-block',
        'vertical-align': 'middle',
        'background-origin': 'border-box',
        'user-select': 'none',
        'flex-shrink': '0',
        height: spacing[4],
        width: spacing[4],
        color: theme('colors.blue.600', colors.blue[600]),
        'background-color': '#fff',
        'border-color': theme('colors.gray.500', colors.gray[500]),
        'border-width': borderWidth['DEFAULT'],
        '--tw-shadow': '0 0 #0000',
      },
      [`[type='checkbox']`]: {
        'border-radius': borderRadius['none'],
      },
      [`[type='radio']`]: {
        'border-radius': '100%',
      },
      [[`[type='checkbox']:focus`, `[type='radio']:focus`]]: {
        outline: '2px solid transparent',
        'outline-offset': '2px',
        '--tw-ring-inset': 'var(--tw-empty,/*!*/ /*!*/)',
        '--tw-ring-offset-width': '2px',
        '--tw-ring-offset-color': '#fff',
        '--tw-ring-color': theme('colors.blue.600', colors.blue[600]),
        '--tw-ring-offset-shadow': `var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)`,
        '--tw-ring-shadow': `var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)`,
        'box-shadow': `var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)`,
      },
      [[
        `[type='checkbox']:checked`,
        `[type='radio']:checked`,
        `.dark [type='checkbox']:checked`,
        `.dark [type='checkbox']:indeterminate`,
        `.dark [type='radio']:checked`,
      ]]: {
        'border-color': `transparent`,
        'background-color': `currentColor`,
        'background-size': `0.65rem 0.65rem`,
        'background-position': `center`,
        'background-repeat': `no-repeat`,
      },
      [`[type='checkbox']:checked`]: {
        'background-image': `url("${svgToTinyDataUri(
          `<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 16 12">
            <path stroke="white" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M1 5.917 5.724 10.5 15 1.5"/>
          </svg>`
        )}")`,
        'background-repeat': `no-repeat`,
        'background-size': `0.65rem 0.65rem`,
        'print-color-adjust': `exact`,
      },
      [`[type='radio']:checked`]: {
        'background-image': `url("${svgToTinyDataUri(
          `<svg viewBox="0 0 16 16" fill="white" xmlns="http://www.w3.org/2000/svg"><circle cx="8" cy="8" r="3"/></svg>`
        )}")`,
        'background-size': `1rem 1rem`,
      },
      [`.dark [type='radio']:checked`]: {
        'background-image': `url("${svgToTinyDataUri(
          `<svg viewBox="0 0 16 16" fill="white" xmlns="http://www.w3.org/2000/svg"><circle cx="8" cy="8" r="3"/></svg>`
        )}")`,
        'background-size': `1rem 1rem`,
      },
      [`[type='checkbox']:indeterminate`]: {
        'background-image': `url("${svgToTinyDataUri(
          `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 16 16"><path stroke="white" stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="M2 8h12"/></svg>`
        )}")`,
        'background-color': `currentColor`,
        'border-color': `transparent`,
        'background-position': `center`,
        'background-repeat': `no-repeat`,
        'background-size': `.65rem .65rem`,
        'print-color-adjust': `exact`,
      },
      [[
        `[type='checkbox']:indeterminate:hover`,
        `[type='checkbox']:indeterminate:focus`,
      ]]: {
        'border-color': 'transparent',
        'background-color': 'currentColor',
      },
      [`[type='file']`]: {
        background: 'unset',
        'border-color': 'inherit',
        'border-width': '0',
        'border-radius': '0',
        padding: '0',
        'font-size': 'unset',
        'line-height': 'inherit',
      },
      [`[type='file']:focus`]: {
        outline: `1px auto inherit`,
      },
      [[`input[type=file]::file-selector-button`]]: {
        color: 'white',
        background: theme('colors.gray.800', colors.gray[800]),
        border: 0,
        'font-weight': theme('fontWeight.medium'),
        'font-size': theme('fontSize.sm'),
        cursor: 'pointer',
        'padding-top': spacing[2.5],
        'padding-bottom': spacing[2.5],
        'padding-inline-start': spacing[8],
        'padding-inline-end': spacing[4],
        'margin-inline-start': '-1rem',
        'margin-inline-end': '1rem',
        '&:hover': {
          background: theme('colors.gray.700', colors.gray[700]),
        },
      },
      [[`.dark input[type=file]::file-selector-button`]]: {
        color: 'white',
        background: theme('colors.gray.600', colors.gray[600]),
        '&:hover': {
          background: theme('colors.gray.500', colors.gray[500]),
        },
      },
      [['.tooltip-arrow', '.tooltip-arrow:before']]: {
        position: 'absolute',
        width: '8px',
        height: '8px',
        background: 'inherit',
      },
      ['.tooltip-arrow']: {
        visibility: 'hidden',
      },
      ['.tooltip-arrow:before']: {
        content: '""',
        visibility: 'visible',
        transform: 'rotate(45deg)',
      },
      [`.tooltip[data-popper-placement^='top'] > .tooltip-arrow`]: {
        bottom: '-4px',
      },
      [`.tooltip[data-popper-placement^='bottom'] > .tooltip-arrow`]: {
        top: '-4px',
      },
      [`.tooltip[data-popper-placement^='left'] > .tooltip-arrow`]: {
        right: '-4px',
      },
      [`.tooltip[data-popper-placement^='right'] > .tooltip-arrow`]: {
        left: '-4px',
      },
      ['.tooltip.invisible > .tooltip-arrow:before']: {
        visibility: 'hidden',
      },
      [['[data-popper-arrow]', '[data-popper-arrow]:before']]: {
        position: 'absolute',
        width: '8px',
        height: '8px',
        background: 'inherit',
      },
      ['[data-popper-arrow]']: {
        visibility: 'hidden',
      },
      ['[data-popper-arrow]:before']: {
        content: '""',
        visibility: 'visible',
        transform: 'rotate(45deg)',
      },
      [`[data-popover][role="tooltip"][data-popper-placement^='top'] > [data-popper-arrow]`]:
      {
        bottom: '-5px',
      },
      [`[data-popover][role="tooltip"][data-popper-placement^='bottom'] > [data-popper-arrow]`]:
      {
        top: '-5px',
      },
      [`[data-popover][role="tooltip"][data-popper-placement^='left'] > [data-popper-arrow]`]:
      {
        right: '-5px',
      },
      [`[data-popover][role="tooltip"][data-popper-placement^='right'] > [data-popper-arrow]`]:
      {
        left: '-5px',
      },
      ['[role="tooltip"].invisible > [data-popper-arrow]:before']: {
        visibility: 'hidden',
      },
      '[type=checkbox]': {
        '@apply w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-sm focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600': {}
      },
      '[type=radio]': {
        '@apply w-4 h-4 border-gray-300 focus:ring-2 focus:ring-blue-300 dark:focus:ring-blue-600 dark:focus:bg-blue-600 dark:bg-gray-700 dark:border-gray-600': {}
      },
      [['[type=datetime-local]', '[type=month]', '[type=week]', '[type=search]', '[type=date]', '[type=email]', '[type=number]', '[type=password]', '[type=tel]', '[type=text]', '[type=time]', '[type=url]', 'select', 'textarea']]: {
        '@apply bg-gray-50 border border-gray-300 text-gray-900 rounded-md focus:ring-blue-500 focus:border-blue-500 w-full dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500': {}
      },
      'a': {
        '@apply text-blue-600 underline underline-offset-[.2rem]': {}
      },
    });
    addComponents({
      '.action-item-button': {
        '@apply py-2 px-3 text-sm font-medium no-underline text-gray-900 focus:outline-hidden bg-white rounded-md border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700': {}
      },
      '.index-data-table-toolbar': {
        '@apply flex flex-col lg:flex-row gap-4 mb-4': {}
      },
      '.scopes': {
        '@apply flex flex-wrap gap-1.5': {}
      },
      '.index-button-group': {
        '@apply inline-flex flex-wrap items-stretch rounded-md': {}
      },
      // Prevent double borders when buttons are next to each other
      '.index-button-group > :where(*:not(:first-child))': {
        '@apply -ms-px my-0': {}
      },
      '.index-button': {
        '@apply inline-flex items-center justify-center px-3 py-2 text-sm font-medium no-underline text-gray-900 bg-white border border-gray-200 hover:bg-gray-100 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 first:rounded-s-md last:rounded-e-md dark:bg-gray-900 dark:border-gray-700 dark:text-gray-100 dark:hover:text-gray-200 dark:hover:bg-gray-800 dark:focus:ring-blue-500 dark:focus:text-white': {}
      },
      '.index-button-selected': {
        '@apply bg-gray-100 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-800': {}
      },
      '.scopes-count': {
        '@apply inline-flex items-center justify-center rounded-full bg-indigo-200/80 text-indigo-800 dark:bg-indigo-800 dark:text-indigo-200 px-1.5 py-1 text-xs font-normal ms-2 leading-none': {}
      },
      '.paginated-collection': {
        '@apply border border-gray-200 dark:border-gray-800 rounded-md shadow-xs overflow-hidden': {}
      },
      '.paginated-collection-contents': {
        '@apply overflow-x-auto': {}
      },
      '.paginated-collection-pagination': {
        '@apply p-2 lg:p-3 flex flex-col-reverse lg:flex-row gap-4 items-center justify-between': {}
      },
      '.paginated-collection-footer': {
        '@apply p-3 flex gap-2 items-center justify-between text-sm border-t border-gray-200 dark:border-gray-800': {}
      },
      '.pagination-per-page': {
        '@apply text-sm py-1 pe-7 w-auto w-min': {}
      },
      '.index-as-table': {
        '@apply relative overflow-x-auto': {}
      },
      '.data-table': {
        '@apply w-full text-sm text-gray-800 dark:text-gray-300': {}
      },
      '.data-table :where(thead > tr > th)': {
        '@apply px-3 py-3.5 whitespace-nowrap font-semibold text-start text-xs uppercase border-b text-gray-700 bg-gray-50 dark:bg-gray-950/50 dark:border-gray-800 dark:text-white': {}
      },
      '.data-table :where(thead > tr > th > a)': {
        '@apply text-inherit no-underline inline-flex items-center gap-2': {}
      },
      '.data-table-sorted-icon': {
        '@apply invisible w-[8px] h-[5px]': {}
      },
      ':where(th[data-sort-direction]) .data-table-sorted-icon': {
        '@apply visible': {}
      },
      ':where(th[data-sort-direction="asc"]) .data-table-sorted-icon': {
        '@apply rotate-180': {}
      },
      '.data-table :where(tbody > tr)': {
        '@apply border-b dark:border-gray-800': {}
      },
      '.data-table :where(td)': {
        '@apply px-3 py-4': {}
      },
      '.data-table-resource-actions': {
        '@apply flex gap-2': {}
      },
      '.filters-form': {
        '@apply text-sm mb-6': {}
      },
      '.filters-form-title': {
        '@apply text-gray-700 dark:text-gray-200 font-bold text-lg mb-4': {}
      },
      '.filters-form :where(.label)': {
        '@apply block mb-1.5 text-sm': {}
      },
      '.filters-form-input-group': {
        '@apply grid grid-cols-2 gap-2': {}
      },
      '.filters-form-field': {
        '@apply mb-4': {}
      },
      '.filters-form-field :where(.choices > label)': {
        '@apply flex gap-2 items-center mb-1': {}
      },
      '.filters-form-buttons': {
        '@apply flex gap-2 items-center': {}
      },
      '.filters-form-submit': {
        '@apply min-w-[6rem] font-bold text-white bg-blue-600 hover:bg-blue-700 focus:ring-4 focus:outline-hidden focus:ring-blue-300 rounded-md px-3 py-2 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800 cursor-pointer': {}
      },
      '.filters-form-clear': {
        '@apply rounded-md px-3 py-2 font-semibold text-gray-700 hover:bg-gray-100 no-underline dark:text-gray-400 dark:hover:bg-inherit dark:hover:text-gray-100 dark:focus:ring-blue-800': {}
      },
      '.active-filters-title': {
        '@apply text-gray-700 dark:text-gray-200 font-bold text-lg mb-4': {}
      },
      '.active-filters-list': {
        '@apply ps-5 list-disc space-y-1 text-gray-700 dark:text-gray-200': {}
      },
      '.batch-actions-dropdown': {
        '@apply relative': {}
      },
      '.batch-actions-dropdown-toggle': {
        '@apply transition-opacity rounded-md inline-flex items-center justify-center gap-2 px-3 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 dark:bg-gray-700 dark:border-gray-600 dark:text-white dark:hover:text-white dark:hover:bg-gray-600 dark:focus:ring-blue-500 dark:focus:text-white disabled:text-gray-400 disabled:border-gray-200/70 dark:disabled:bg-gray-900 dark:disabled:text-gray-700 dark:disabled:border-gray-800 disabled:pointer-events-none': {}
      },
      '.batch-actions-dropdown-arrow': {
        '@apply w-2.5 h-2.5': {}
      },
      '.batch-actions-dropdown-menu': {
        '@apply z-10 hidden min-w-[7rem] bg-white rounded-md shadow-lg ring-1 ring-black/5 focus:outline-hidden dark:bg-gray-700 py-1 text-sm text-gray-700 dark:text-gray-200': {}
      },
      '.batch-actions-dropdown-menu :where(li > a)': {
        '@apply block px-2.5 py-2 no-underline text-gray-700 hover:bg-gray-100 hover:text-gray-900 dark:text-white dark:hover:bg-gray-600 dark:hover:text-white': {}
      },
      '.panel': {
        '@apply mb-6 border border-gray-200 rounded-md shadow-xs dark:border-gray-800': {}
      },
      '.panel-title': {
        '@apply font-bold bg-gray-100 dark:bg-gray-900 rounded-t-md p-3': {}
      },
      '.panel-body': {
        '@apply py-5 px-3': {}
      },
      '.attributes-table': {
        '@apply overflow-hidden mb-6 border border-gray-200 rounded-md shadow-xs dark:border-gray-800': {}
      },
      '.attributes-table > :where(table)': {
        '@apply w-full text-sm text-gray-800 dark:text-gray-300': {}
      },
      '.attributes-table :where(tbody > tr)': {
        '@apply border-b dark:border-gray-800': {}
      },
      '.attributes-table :where(tbody > tr > th)': {
        '@apply w-32 sm:w-40 text-start text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-800/60 dark:text-gray-300': {}
      },
      '.attributes-table :where(tbody > tr > th, tbody > tr > td)': {
        '@apply p-3': {}
      },
      '.attributes-table-empty-value': {
        '@apply text-gray-400/50 dark:text-gray-700/60 text-xs uppercase font-semibold': {}
      },
      '.status-tag': {
        '@apply bg-gray-200 text-gray-600 dark:bg-gray-700 dark:text-gray-400 inline-flex items-center rounded-full text-sm font-medium px-2.5 py-0.5 whitespace-nowrap': {}
      },
      '.status-tag:where([data-status=yes])': {
        '@apply bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300': {}
      },
      '.tabs-nav': {
        '@apply flex flex-wrap mb-2 text-sm font-medium text-center border-b border-gray-200 dark:border-gray-700': {}
      },
      '.tabs-nav > :where(a)': {
        '@apply block p-4 border-b-2 border-transparent rounded-t-md hover:text-gray-600 dark:hover:text-gray-300 no-underline': {}
      },
      '.tabs-content': {
        '@apply p-4 mb-6': {}
      },
      // Forms
      '.formtastic': {
        '@apply text-sm': {}
      },
      '.formtastic :where(.fieldset-title, .has-many-fields-title)': {
        '@apply block w-full mb-3 border-b font-bold text-lg': {}
      },
      '.formtastic :where(.label)': {
        '@apply block mb-1.5': {}
      },
      '.formtastic :where(.label abbr)': {
        '@apply ms-1 no-underline': {}
      },
      '.formtastic :where(.input)': {
        '@apply py-3': {}
      },
      '.formtastic :where(.choice)': {
        '@apply mb-1': {}
      },
      '.formtastic :where(.boolean label, .choice label)': {
        '@apply flex gap-2 items-center': {}
      },
      '.formtastic :where(.fragments-group)': {
        '@apply inline-flex flex-wrap gap-1': {}
      },
      '.formtastic :where(.fragment label)': {
        '@apply sr-only': {}
      },
      '.formtastic :where(.inline-hints)': {
        '@apply text-gray-500 mt-2': {}
      },
      '.formtastic :where(.errors)': {
        '@apply p-4 mb-6 rounded-md space-y-2 bg-red-50 text-red-800 dark:bg-red-800 dark:text-red-300': {}
      },
      '.formtastic :where(.errors > li)': {
        '@apply list-disc ms-4': {}
      },
      '.formtastic :where(.inline-errors)': {
        '@apply font-bold mt-2 text-red-600 dark:text-red-300': {}
      },
      '.formtastic :where(.error [type=email], .error [type=number], .error [type=password], .error [type=tel], .error [type=text], .error [type=url], .error textarea)': {
        '@apply border-red-500': {}
      },
      '.formtastic :where(.buttons, .actions)': {
        '@apply mt-3': {}
      },
      '.formtastic :where(.actions > ol)': {
        '@apply flex items-center gap-6': {}
      },
      '.formtastic :where([type=submit], [type=button], button)': {
        '@apply font-bold text-white bg-blue-600 hover:bg-blue-700 focus:ring-4 focus:outline-hidden focus:ring-blue-300 rounded-lg px-4 py-2 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800 cursor-pointer': {}
      },
      '.formtastic :where(.actions .cancel-link)': {
        '@apply font-semibold leading-6 text-gray-900 dark:text-white no-underline': {}
      },
      '.formtastic :where(.has-many-add)': {
        '@apply inline-block py-3': {}
      },
      '.formtastic :where(.has-many-container)': {
        '@apply space-y-8': {}
      },
      '.formtastic :where(.has-many-fields)': {
        '@apply ps-3 border-s-4 border-s-gray-200 dark:border-s-gray-700': {}
      }
    });
  }
)

plugin.js にはtailwindのcssクラスを付与するメソッドがあるのですがそのcssクラスがv3のままなのでエラーが出ていたので修正しました。

次にapp/asesets/stylesheets/ 内に active_admin.css (無ければ作成して下さい。)

app/asesets/stylesheets/active_admin.css
@import "tailwindcss";

@config "tailwind-active_admin.config.jsへのパスを記述";
/* @config "../../../config/tailwind-active_admin.config.js"; */

lib/tasks/active_admin.rake を作成

lib/tasks/active_admin.rake
namespace :active_admin do
  desc "Build Active Admin Tailwind stylesheets"
  task build: :environment do
    command = [
      "tailwindcss",
      "-i", Rails.root.join("app/assets/stylesheets/active_admin.css").to_s,
      "-o", Rails.root.join("app/assets/builds/active_admin.css").to_s
    ]
    system(*command, exception: true)
  end

  desc "Watch Active Admin Tailwind stylesheets"
  task watch: :environment do
    command = [
      "tailwindcss",
      "-w",
      "-i", Rails.root.join("app/assets/stylesheets/active_admin.css").to_s,
      "-o", Rails.root.join("app/assets/builds/active_admin.css").to_s,
      "-m"
    ]

    system(*command, exception: true)
  end
end

Rake::Task["assets:precompile"].enhance([ "active_admin:build" ])

最後にProcfileに追加

Procfile.dev
web: bin/rails server -b 0.0.0.0
css: bin/rails tailwindcss:watch
active_admin: bin/rails active_admin:watch

これで ./bin/dev すればActiveadmin v4が!

スクリーンショット 2025-03-24 17.44.15.png

gactiveadminの4.0.0.beta15から変更したものをgithubに上げているのでそちらでも
gemfileに
gem "activeadmin", github: "mammosu/activeadmin_v4", branch: "rails8-tailwind4-activeadmin-4"
を追加すれば使用できると思います。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?