Enable local build of TailwindCSS/DaisyUI CSS

Created on 20 February 2025, about 2 months ago

Problem/Motivation

Many site owners would like to be in control of the code they deliver. In this respect, some configuration steps are required to add NPM packages, create configuration file, and define the location of the destination CSS.

Steps to reproduce

npm install -D tailwindcss "@tailwindcss/forms" "@tailwindcss/typography" daisyui@beta autoprefixer postcss "@tailwindcss/postcss" postcss-import postcss-nested cssnano

Create two script definitions in the `package.json` file

"scripts": {
    "dev": "NODE_ENV=development postcss ./style/style.pcss.css -o ./dist/style.css -w -m",
    "build": "NODE_ENV=production postcss ./style/style.pcss.css -o ./dist/style.css"
  },

Create a postcss.config.js file

module.exports = (ctx) => ({
  map: ctx.options.map,
  plugins: {
    "postcss-import": {},
    "postcss-nested": {},
    "@tailwindcss/postcss": {},
    autoprefixer: {},
    ...(process.env.NODE_ENV === "production"
      ? { cssnano: { preset: "default" } }
      : {}),
  },
});

- Create a folder /style, if it does not already exist

- Create the style.pcss.css file in the above folder with the following contents

@import "tailwindcss";

@plugin "@tailwindcss/typography";
@plugin "@tailwindcss/forms";
@plugin "daisyui";

- Update ui_suite_daisyui.info.yml
Remove reference to the following libraries

- ui_suite_daisyui/daisyui_cdn
- ui_suite_daisyui/daisyui_themes_cdn
- ui_suite_daisyui/custom_css

Add reference to the following library

- ui_suite_daisyui/daisyui

Update ui_suite_daisyui.libraries.yml
Add definition of the daisyui library

daisyui:
  css:
    theme:
      dist/style.css: { minified: true }

- Create a folder /dist, if it does not already exist

- npm run build - to build a compressed CSS file
- npm run dev - to build a non-compressed CSS file and watch for changes, and rebuild after change

Proposed resolution

Update configuration to cater for own built version CSS for eventual publication to production environments.

Remaining tasks

- Validate concept
- Ensure that the reference to DaisyUI 5 beta in the configuration, is updated as and when DaisyUI 5 is released

User interface changes

None

API changes

- Remove dependency on externally delivered CSS files
- Host code to automatically (re)generate CSS files

- Running npm update will download and make available most recent versions of TailwindCSS and DaisyUI and other libraries
- Running npm run build will rebuild CSS with the most recently installed versions of TailwindCSS and DaisyUI

Data model changes

none

Feature request
Status

Active

Version

5.0

Component

Code

Created by

🇱🇺Luxembourg paddy_deburca

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @paddy_deburca
  • 🇫🇷France G4MBINI Bègles

    Hello @paddy_deburca ,

    One of the main goal of this theme is to promote display building and no-code mapping between data and design elements. So the main persona here is Site Builder.

    It's important that this type of users who install the theme have directly a good visual experience and already built-in configs. That being said, I will keep the CDN libraries by default (and why not ship a DaisyUI CSS library already built that we can switch with theme settings).

    Other users like developers, are for most them already confortable with build processes (SASS, Tailwind, ...) so I guess they know how to do that, right ?

    IMHO, build process tools shouldn't be shipped inside the theme, but well documented instead, in the README or in the incoming htdocs.

    Do you want to take care of that ?

  • 🇱🇺Luxembourg paddy_deburca

    My proposal is to move this documentation to a starterkit theme. This would allow
    - existing theme to work as-is and un modified
    - create sub-theme from starterkit with documentation and examples on how to configure with own versions of CSS

    There are multiple ways to build the local CSS, and of these I propose to only document two
    - using TailwindCSS CLI to compile the CSS
    - using PostCSS to compile the CSS with some processors

    The file `package.json` is be required with a minimum configuration for TailwinsCSS, daisyUI, and TailwindCSS/CLI.

    Two extra files _could_ also be included
    - `package-postcss-example.json` - containing an example, working, configuration, with PostCSS, TailwindCSS, daisyUI
    - `postcss-example.js` - containing PostCSS configuration

    In both cases, we can include the script definitions to hide the complexity of `npm`/`npx` calls
    - `npm run build` to build and store CSS in `output.css`
    - `npm run dev` to build, and re-build on file updates, and store CSS in `output.css`

    The `README.md` file documents these configuration items, but having a sample file(s) to start with would make process easier.

    If this approach is OK, I will create the sample files, and create a merge request with the entire starterkit folder.

  • First commit to issue fork.
  • Merge request !139Resolve #3508143 "Starterkit followup" → (Closed) created by vasike
  • Merge request !140Resolve #3508143 "Starterkit followup" → (Open) created by vasike
  • 🇷🇴Romania vasike Ramnicu Valcea

    new MR available
    https://git.drupalcode.org/project/ui_suite_daisyui/-/merge_requests/140

    Which updates the previous one:
    - Use the daisyUI logo/icon
    - Delete the extra files that "needed renaming" - not actually needed
    - Fix the Regions and libraries
    - Remove not needed files ... empty or inherited from the base theme.
    - Emptied generated CSS file.
    - Update README file - simplify the process + remove older Drupal info.

    I could generate an working theme just with

    php core/scripts/drupal generate-theme my_daisyui_theme --starterkit ui_suite_daisyui_starterkit --path themes/custom
    npm install
    npm run build or npm run dev

    commands

  • 🇷🇴Romania vasike Ramnicu Valcea
  • 🇩🇪Germany Christian.wiedemann

    Hi all,

    I checked some frameworks like nuxt and next and other themes. But from my point of view there is no best practice. So here are my 5 cents about the folder structure and compile steps.

    • 1. CSS Folder/File structure in the Drupal way. Means 1 result file for each component. Same folder structure.
    • 2. CSS Linting "stylelint/Prettier". We ignore JS stuff.
    • 3. Base Blocks

    1. CSS compile in the Drupal core way.

    So I think we should do it like Drupal Core. Maybe other themes will follow. They use pcss.css as source files and generate the resulting file in the same folder without pcss.css extension. So I would change the src/css folder structure to:

    css/global.pcss.css
    css/global.css > generated. in gitignore etc.
    css/themes.pcss.css
    # Not sure if we need. But I am
    css/base.pcss.css
    css/utitilites.pcss.css
    
    # Components look like:
    components/component/component.pcss.css
    components/component/component.css > generated. in gitignore etc.
    

    So we don't have a dist folder. (Not 100% sure about this. But I think some CSS is in a dist folder and some not is not so clean)

    To generate the CSS I would do something similar core is doing. Following Script is part of core. Maybe we can use it or we copy and adapt it. I think it is easy to adapt to tailwind CLI. It uses a glob to add each CSS to a separate process so there is no need to adopt an config file if a CSS file is added.

    What do you think?

    
    /**
     * @file
     *
     * Provides the build:css command to compile *.pcss.css files to CSS.
     *
     * Run build:css with --file to only parse a specific file. Using the --check
     * flag build:css can be run to check if files are compiled correctly.
     * @example <caption>Only process misc/drupal.pcss.css and misc/drupal.init.pcss.css</caption>
     * yarn run build:css --file misc/drupal.pcss.css --file misc/drupal.init.pcss.css
     * @example <caption>Check if all files have been compiled correctly</caption>
     * yarn run build:css --check
     *
     * @internal This file is part of the core CSS build process and is only
     * designed to be used in that context.
     */
    
    'use strict';
    
    const { globSync } = require('glob');
    const argv = require('minimist')(process.argv.slice(2));
    const changeOrAdded = require('./changeOrAdded');
    const check = require('./check');
    const log = require('./log');
    
    // Match only on .pcss.css files.
    const fileMatch = './**/*.pcss.css';
    // Ignore everything in node_modules
    const globOptions = {
      ignore: './node_modules/**'
    };
    const processFiles = (filePaths) => {
      // Process all the found files.
      let callback = changeOrAdded;
      if (argv.check) {
        callback = check;
      }
      filePaths.forEach(callback);
    };
    
    if (argv.file) {
      processFiles([].concat(argv.file));
    }
    else {
      processFiles(globSync(fileMatch, globOptions).sort());
    }
    process.exitCode = 0;
    

    Style/lint

    We should add some tailwind specific style and linting configs.

    Blocks

    Not realy have a hard opionion about it.

    I think a vite startkit would be also nice. But this is a seperate issue.

  • 🇱🇺Luxembourg paddy_deburca

    I am inclined to agree with using the Drupal way - store custom CSS in *.pcss.css files and compile to an *.css file in the same folder. This changes the output folder, and possibly negates the need for a dist/ folder altogether.

    The code sample provided could be very interesting - at the moment I miss the context in which this code is executed. Is this build process publicly available? Is it possible to see the environment in which it is run, so that I can see if we can cherry pick utilities from the process?

  • 🇱🇺Luxembourg paddy_deburca

    Regarding Stylelint - we *could* include stylelint into the build process.

    By defining lints in a config file

    module.exports = {
      rules: {
        "at-rule-no-unknown": true,
        "block-no-empty": true,
        "color-no-invalid-hex": true,
        "comment-no-empty": true,
        "declaration-block-no-duplicate-properties": [
          true,
          {
            ignore: ["consecutive-duplicates-with-different-values"]
          }
        ],
        "declaration-block-no-shorthand-property-overrides": true,
        "font-family-no-duplicate-names": true,
        "font-family-no-missing-generic-family-keyword": true,
        "function-calc-no-unspaced-operator": true,
        "function-linear-gradient-no-nonstandard-direction": true,
        "keyframe-declaration-no-important": true,
        "media-feature-name-no-unknown": true,
        "no-descending-specificity": true,
        "no-duplicate-at-import-rules": true,
        "no-duplicate-selectors": true,
        "no-empty-source": true,
        "no-extra-semicolons": true,
        "no-invalid-double-slash-comments": true,
        "property-no-unknown": true,
        "selector-pseudo-class-no-unknown": true,
        "selector-pseudo-element-no-unknown": true,
        "selector-type-no-unknown": true,
        "string-no-newline": true,
        "unit-no-unknown": true
      }
    };
    

    we can invoke the stylelint plugin during the build process.

    An invalid CSS such as

    .dummy {
      color: var(--color-black);
      font-size: 12jon;
    }

    would provide an error such as

    ERROR in 
    src/css/components/dummy.css
     3:14 ✖ Unexpected unknown unit “jon” unit-no-unknown

    example source: https://jontorrado.medium.com/working-with-webpack-4-es6-postcss-with-pr...

    So: Yes! we can!! - but, should we?

  • 🇱🇺Luxembourg paddy_deburca

    And finally, my last comment before my next one.

    Using the following configuration syntax in vite we may be able to automatically target all subfolder of the components/ folder.

    import { globSync } from 'glob';
    import path from 'node:path';
    import { fileURLToPath } from 'node:url';
    
    export default {
    	input: Object.fromEntries(
    		globSync('components/**/*.pcss.css').map(file => [
    			'components/'.concat(path.split("/")[1]),
    			fileURLToPath(new URL(file.slice(0, file.length - ".pcss.css".length).concat(".css"), import.meta.url))
    		])
    	),
    	output: {
    		dir: 'components'
    	}
    };

    This would try to process all .pcss.css files found in a components folder into one components CSS file. This concept may or may not work.

    Further reading: https://rollupjs.org/configuration-options/#input and https://vite.dev/config/build-options#build-rollupoptions

  • 🇩🇪Germany Christian.wiedemann

    Hi @paddy_deburca,

    CSS

    The code sample provided could be very interesting - at the moment I miss the context in which this code is executed. Is this build process publicly available? Is it possible to see the environment in which it is run, so that I can see if we can cherry pick utilities from the process?

    The script is part of drupal core. (Or do I missunderstand your question.). You can find it in web/core/scripts/css. It should run during the local or CI build process. So we maybe can reuse the script from web/core/scripts/css or place a script in our scripts/css folder and execute it via package.json.

    Liniting

    I think we should at least provide it. Other frameworks deliver mostly more preconfigured tools. So a good starting point helps.
    I would vote for stylelint and prettier config.

    Vite

    I also vote for a separate starter kit with VITE support. When we finished we create it in a separate branch?

  • 🇱🇺Luxembourg paddy_deburca

    Stylelint

    Install stylelint NPM plugin npm install -D stylelint and then the TaildwindCSS companion linter npm install -D stylelint-config-tailwindcss

    Update postcss.config.js to include Srtylelint

    "postcss-import": {
          plugins: [
            stylelint()
          ]
        },

    This returns an error from Stylelint stating that there is not module the defined in package.json. So add
    "type": "module",
    to package.json.

    There is another complaint that requires renaming postcss.config.js to postcss.config.cjs.

    This in turn then complains that plugins should be configured in the correct manner

    import stylelint from "stylelint";
    import autoprefixer from "autoprefixer";

    Almost there.

    At this point there is a depreciation notice regarding the use of The CommonJS Node.js API. This then required renaming postcss.config.cjs to postcss.config.mjs.

    Now a npm run build executes and style checks the CSS.

    In summary

    • Two additional NPM modules
    • Additional stylelint.config.js file
    • Update to postcss.config.js to import and use stylelint plugin
    • Update package.json to define type as module
    • Rename postcss.config.js to postcss.config.mjs
  • 🇱🇺Luxembourg paddy_deburca

    Components

    Based on the scripts in Drupal/web/core/scripts/css, the *.pcss.css are compiled to *.css in each respective component folder.

    For this to work in the post stylelint configuration, I had to convert the JS config files to MJS - requiring slight changes to require statements (now import statements).

    I also limited the scope of the search for *.pcss.css files from . to components.

    The solution works - but I have a concern or two.

    In the *.pcss.css files, will there be TailwindCSS statements such as @apply or @import? Or, will the code be 'normal' CSS that can be applied directly yo an element?

  • 🇩🇪Germany Christian.wiedemann

    Hi @paddy_deburca, thanks for all your work!
    I am completly fine with styleint suggestion.
    To the components. Yes inside the components there should be @apply statements. Do you use the script from drupal core? Not sure if this is a problem because actually it is just another process with a diffent source file. So it should work or?

  • 🇱🇺Luxembourg paddy_deburca

    Christian,

    By copying the scripts to the theme folder and by making some compatibility updates - I have a process that works-ish.

    *.pcss.css files are processed and .css files are processed and created in the same folder.

    But adding stylelint to this process - the process either does nothing new or nothing at all - I may be doing something wrong (but I do not see where).

    To process '@apply' statements, it is necessary that TailwindCSS is loaded to understand the tag and know the utility classes - and this then includes tailwind css in all components - not just the expansion of the '@apply' statements.

    To have just the minimum CSS per component, it would be necessary to load both the component CSS and the tailwind CSS, and walk through the nodes, checking component nodes against tailwind nodes, and deleting from the component CSS if they match.

    This should not be impossible, but it add additional complexity and will impact the build process for component CSS.

    If someone knows of an efficient way to resolve this, I would be please to know and investigate further.

  • 🇩🇪Germany Christian.wiedemann

    Hi @paddy_deburca can you push your current theme?

  • 🇱🇺Luxembourg paddy_deburca

    Hej Christian,

    I have added my updated
    - npm run build - will use previous method using postcss to compile the CSS - with the addition of Stylelint
    - npm run build:css - will use scripts based on Drupal core to iterate through the components folder and compile *.pcss.css to *.css

    The final part is not producing the desired output - comments are not being removed and stylelint is not running (I think) - no errors are produced.

    I have worked with the compile.mjs file (previously compile.js) to make the process work - but I must be missing something.

    I have also added a .gitignore file to avoid pushing superfluous files.

  • 🇩🇪Germany Christian.wiedemann

    Hi @paddy_deburca,
    Thanks for all your work! I checked the PostCSS pipeline and I think it is probably not the right direction.
    We need to load the tailwind and its config in each post.css file and shrink out the not necessary part. It works for me more or less with this code (I did not load configs but it should):

    @import "tailwindcss/theme.css" ;
    
    @layer component {
      .select2-dropdown {
        @apply rounded-sm;
      }
      .select2-search {
        @apply rounded-md;
      }
      .select2-results__group {
        @apply text-lg rounded-xl;
      }
    
    }
    

    But we need to add include statements in each file. Webpack or Vite are working differnt. They merge the CSS files together and than split them into output files in a different step. So I think when we want to provide a CLI or PostCSS Variant we should stay with the one file solution and put everything into src/css directory and no CSS files in the component folder. I will try your posted Vite configuration example .

  • 🇩🇪Germany Christian.wiedemann

    and sorry for point to this postcss script.

  • 🇱🇺Luxembourg paddy_deburca

    Hej Cristian,

    With Vite, I have only succeeded in sourcing multiple files - but the output all goes into the same file - using the Object.fromEntries(globSync()) method. The advantage is that it automatically finds all *.pcss.css files; but the disadvantage is that only one *.css file is currently being created.

    Taking a step back..

    During the build process
    - create _tw.css with the current version of TailwindCSS
    - this file contains all the CSS statements, followed by @property statements
    - split the _tw.css in two sections, CSS statements and @properties to give number of lines of CSS and number of lines of @properties
    - process all the components to create .css files
    - remove the CSS statements from the beginning of components .css files
    - remove the @propertiesfrom the end of components .css files
    - the remaining CSS statements should be related to the specific component

    So some (pseudo) code such as

    echo "@import 'tailwindcss';" | npx tailwindcss -i - -o _tw.css # generate current Tailwind CSS file
    TWLEN=$(cat _tw.css | wc -l)  # get length in lines
    TWPRP=$(grep -n -m1 '@property' _tw.css | cut -f1 -d:) # get first occurrence of @property
    TWCSS=$(TWLEN - TWPRP) # number of lines with CSS statements
    
    npx tailwindcss -i components/button/button.pcss -o - | head --lines=-$TWCSS | tail -l +$TWPRP > components/button/button.css
    # generate all CSS required to display component (includes Tailwind CSS)
    # remove TailwindCSS statements from start of file
    # remove @properties from end of file
    # save in component CSS
    

    If we compress the code - we need to calculate in bytes rather than lines.

    The (only) advantage with this approach is that we could use the same approach to process the theme CSS as the component CSS (tailwindcss CLI, PostCSS, ...)

  • 🇩🇪Germany Christian.wiedemann

    Hi, I realized that you have to use @reference if you want to use multiple files without duplication of code.

    
    @reference '../../css/app.pcss.css';
    
    .alert a {
      @apply bg-coral;
      font-weight: 700;
    }
    

    With this postcss and vite and webpack works as expected. It works also for me with multiple files.

    import { defineConfig } from 'vite'
    import tailwindcss from '@tailwindcss/vite'
    import { globSync } from 'glob';
    
    const files = Object.fromEntries(globSync('components/**/*.pcss.css').map(file => [
      'components/' + file.split("/")[1],
      file
    ]))
    console.log(files);
    export default defineConfig({
      root: '.',
      build: {
        cssCodeSplit: true,
        outDir: '.',
    
        rollupOptions: {
          input: {
            'main': './css/app.pcss.css',
            ...files
          },
        },
      },
      plugins: [
        tailwindcss(),
      ],
    })
    

    The same works also with WEBPACK with one CSS file for each entry. But either webpack as VITE actually need a dist folder. And actually a dist folder is a very nice thing.

  • 🇱🇺Luxembourg paddy_deburca

    Christian,

    I have developed a JS script
    - loops through all the component .pcss.css stylesheets
    - runs them through PostCSS and Tailwind
    - removes the superfluous Tailwind CSS and properties from the component CSS file

    /*
     * Not possible to add alert-link class correctly in alert content.
     *
     * Reproduce style.
     */
    @import "tailwindcss";
    
    .select2-dropdown {
      @apply rounded-sm;
    }
    .select2-search {
      @apply rounded-md;
    }
    .select2-results__group {
      @apply text-lg rounded-xl;
    }

    produces in the component .css file

    .select2-dropdown {
      border-radius: var(--radius-sm);
    }
    .select2-search {
      border-radius: var(--radius-md);
    }
    .select2-results__group {
      border-radius: var(--radius-xl);
      font-size: var(--text-lg);
      line-height: var(--tw-leading, var(--text-lg--line-height));
    }

    I still have some finessing to complete - and add stylelint and cssnano.

  • 🇩🇪Germany Christian.wiedemann

    You don't need to remove the superfluous Tailwind CSS classes if you use @reference instead of "@import "tailwindcss";

    /*
     * Not possible to add alert-link class correctly in alert content.
     *
     * Reproduce style.
     */
    @reference '../../src/css/input.css';
    
    .select2-dropdown {
      @apply rounded-sm;
    }
    .select2-search {
      @apply rounded-md;
    }
    .select2-results__group {
      @apply text-lg rounded-xl;
    }
    
  • 🇱🇺Luxembourg paddy_deburca

    Christian,

    Yes - this is excellent. The use of @reference really simplifies and future proofs process.

    It may be necessary to embed the Vite PostCSS/TailwindCSS process within a loop over the components folders, such that the css is generated for a single component - we can then decide if the resultant css should be under dist/ or within the actual component folder itself.

    From my few tests, where I am trying to @apply round-sm to an element fails - as the utility round-sm is not defined in the app.css file. I will continue looking into this so that I can understand the process better.

  • 🇩🇪Germany Christian.wiedemann

    This took me also some time:) it is @apply rounded-sm;

  • 🇩🇪Germany Christian.wiedemann

    I was also thinking about to add the build variants as a subfolder to the theme. In each we add a package json. And maybe we share common stuff in .build folder. (not sure - I tend to overengineer stuff so what do you think?)

    .build
    - postcss
    - vite
    - webpack

  • 🇱🇺Luxembourg paddy_deburca

    Christian,

    I have

    @reference '../../dist/css/output.css';
    
    .select2-dropdown {
      @apply rounded-sm;
    }
    .select2-search {
      @apply rounded-md;
    }
    .select2-results__group {
      @apply text-lg rounded-xl;
    }

    Where output.css is the build of CSS for the theme - should contain TailwindCSS and DaisyUI.

    When I search output.css for rounded using grep rounded dist/css/output.css, I get

      .rounded {
      .rounded-box {
      .rounded-box {
      .rounded-full {
      .rounded-lg {
      .rounded-md {
      .rounded-sm {
      .rounded-xl {
    

    When I try to build a component CSS using npx tailwindcss -i components/button/button.pcss.css, I get Error: Cannot apply unknown utility class: rounded-sm

    The input CSS file for the theme contains @layer theme, base, components, utilities;.

    Is there something I am still missing from my setup with relation to using @reference?

  • 🇫🇷France G4MBINI Bègles

    rounded-sm is not present in UI Suite DaisyUI theme. For now I only find :

    • rounded-lg (hero.twig)
    • rounded (avatar.component.yml)
    • rounded-xl (avatar.component.yml)
    • rounded-full (avatar.component.yml)
    • rounded-box (carousel.default.story.yml)

    rounded-md & rounded-sm (which at the end comes from Tailwind) are not at all for now in the UI Suite DaisyUI theme.

    Also, small alert :

    .select2-dropdown {
      @apply rounded-sm;
    }
    .select2-search {
      @apply rounded-md;
    }
    .select2-results__group {
      @apply text-lg rounded-xl;
    }
    

    This piece of code doesn't come from Tailwind but Bootstrap. There's no select2-xxx class in DiasyUI. Also, in Bootstrap 4 you could find rounded-xxx classes.

    Hope this could help ...

  • 🇫🇷France G4MBINI Bègles
  • 🇱🇺Luxembourg paddy_deburca

    @g4mbini,

    As I am only doing tests, I took inspiration from what has been done with UI Bootstrap, and am trying to make things work.

    You are correct that rounded-sm does not exist in output.css in our current configuration - however, updating the button.twig to make reference to rounded-sm - results in rounded-sm being included in the output.css file.

    My challenge is, that when I want to expend a class (in this case a class name I borrowed from Bootstrap) with @apply rounded-sm, I get an error message.

    I may be missing utility class definitions (even though @layer statement is in the input.css file).

  • 🇱🇺Luxembourg paddy_deburca

    I figured it out ;-)

    Rather than using @reference "../../dist/css/output.css", I must use @reference "tailwindcss".

    The source CSS is

    @reference 'tailwindcss';
    
    .select2-dropdown {
      @apply rounded-sm;
    }
    .select2-search {
      @apply rounded-md;
    }
    .select2-results__group {
      @apply text-lg rounded-xl;
    }
    

    The generated CSS is

    /*! tailwindcss v4.0.13 | MIT License | https://tailwindcss.com */
    .select2-dropdown {
      border-radius: var(--radius-sm, 0.25rem);
    }
    .select2-search {
      border-radius: var(--radius-md, 0.375rem);
    }
    .select2-results__group {
      border-radius: var(--radius-xl, 0.75rem);
      font-size: var(--text-lg, 1.125rem);
      line-height: var(--tw-leading, var(--text-lg--line-height, calc(1.75 / 1.125)));
    }
    
  • 🇩🇪Germany Christian.wiedemann

    Hi @paddy_deburca,

    I checked that right now and you are right. The problem behind this that our theme in css/themes/themes.css disables the default theme with

    @theme {
      --*: initial;
    

    --*: initial; should be removed than everything works as expected with @reference '../../css/input.pcss.css';
    (Sorry propably I commited that)

  • 🇩🇪Germany Christian.wiedemann

    Hi Paddy,

    I have some open source time today. So if you push your scripts we may finalize them today so that we have a working postcss script with linting.

  • 🇱🇺Luxembourg paddy_deburca

    Christian,

    I will need to make some minor adjustments to my script - I will try to merge something later this morning.

    That being said, it would still be interesting to explore Vite as a possibility - and to see if we can produce one CSS file per component. Using rollup we can combine multiple input CSS into one output CSS. Question is, can we loop through the component folders, and do this for each folder.

    In reality, this is what I am doing with my script, looping through the components folder, and using PostCSS to process the CSS.

    Paddy.

  • 🇱🇺Luxembourg paddy_deburca

    Christian,

    I have added a process-tailwind.cjs (can be renamed) that
    - finds all *.pcss.css files under components/ folder
    - process each file using PostCSS and TailwindCSS
    - stores the process file in the same location as original - but with a .css extension

    It is assumed that each *.pcss.css file contains @reference 'tailwindcss'; (or similar that allows discovery of TailwindCSS utilities)

    Possible improvements would be to improve file management in PostCSS or replace PostCSS by Vite, such that all *.pcss.css within a component folder would be compiled into one .css file in that component folder.

  • 🇩🇪Germany Christian.wiedemann

    Hi Paddy,

    thanks! I will have a look.

  • 🇱🇺Luxembourg paddy_deburca

    Christian,

    I have added a Vite config file to the repo that also compiles the *.pcss.css to *.css.

    Again, possible improvement would be to combine all *.pcss.css for one component into one *.css for that component.

    This may require running such a script once for each component, such as find components -type d -depth 1 -exec npx vite build --dir "{}" \;, or something similar in JS (more portable).

    If this is the way we would like to go, I can update the Vite config to capture the --dir parameter, and build one CSS per folder.

    Paddy.

  • 🇱🇺Luxembourg paddy_deburca

    Christian,

    I have managed to be able to create a dynamic map of components with *.pcss.css file using

        // Step 2: Read the directory contents
        const files = await fs.readdir(componentsPath);
    
        // Step 3: Filter for directories only
        const folderPaths = await Promise.all(
          files.map(async (file) => {
            const fullPath = join(componentsPath, file);
            const stats = await fs.stat(fullPath);
            const isDirectory = stats.isDirectory();
            return { name: file, isDirectory, path: fullPath };
          })
        );
    
        // Filter only directories and return their names
        const folders = folderPaths
          .filter(item => item.isDirectory)
          .map(folder => folder.name);
    

    With this mapping, I can pass it to the build/rollupOptions

        build: {
          rollupOptions: {
            input: { ...entries },
    

    When run as npx vite build we get

    ❯ npx vite build

    vite v6.2.2 building for production...
    ✓ 4 modules transformed.
    dist/components/alert/alert.css          0.09 kB │ gzip: 0.10 kB
    dist/components/accordion/accordion.css  0.13 kB │ gzip: 0.13 kB
    dist/components/button/button.css        0.34 kB │ gzip: 0.22 kB
    ✓ built in 866ms
    

    I am quiet happy with this version of the Vite configuration as it _uses_ Vite, and does not work around Vite.

  • 🇩🇪Germany Christian.wiedemann

    Hi,
    I pushed a repo with an updated postcss script and basic VITE script I did during this afternoon which is actually tries to do the same as yours. It is not working now so probably we should go with your implementation. I used workspaces to manage two build types. Postscript and VITE. Postscript works fine now with (with linting and prettier). With VITE we probably need a custom copy command to copy the generated CSS files to component folder after they are build.

  • 🇩🇪Germany Christian.wiedemann

    You can do npm run watch:css -w .build/postcss to run code in a workspace.

  • 🇱🇺Luxembourg paddy_deburca

    Christian,

    Setting the dir to '.' in the config

       build: {
          rollupOptions: {
            input: { ...entries },
            output: {
              dir: '.',
              assetFileNames: '[name].[ext]',
              manualChunks: undefined,
            },
          },
        },
    

    we get the output into the components folder.

    ❯ npx vite build
    vite v6.2.2 building for production...
    
    (!) outDir /Users/paddy/Development/ui_suite_daisyui-3508143/starterkits/ui_suite_daisyui_starterkit is not inside project root and will not be emptied.
    Use --emptyOutDir to override.
    
    ✓ 4 modules transformed.
    ./components/alert/alert.css          0.09 kB │ gzip: 0.10 kB
    ./components/accordion/accordion.css  0.13 kB │ gzip: 0.13 kB
    ./components/button/button.css        0.34 kB │ gzip: 0.22 kB
    ✓ built in 901ms
    

    I am checking to see what may need to be configured to have npx vite dev recompile on change to component *.pcss.css files.

  • 🇱🇺Luxembourg paddy_deburca

    Well, as simple as npx vite build --watch

    ❯ npx vite build --watch
    vite v6.2.2 building for production...
    
    (!) outDir /Users/paddy/Development/ui_suite_daisyui-3508143/starterkits/ui_suite_daisyui_starterkit is not inside project root and will not be emptied.
    Use --emptyOutDir to override.
    
    
    watching for file changes...
    
    build started...
    ✓ 4 modules transformed.
    ./components/alert/alert.css          0.09 kB │ gzip: 0.10 kB
    ./components/accordion/accordion.css  0.13 kB │ gzip: 0.13 kB
    ./components/button/button.css        0.44 kB │ gzip: 0.23 kB
    built in 1147ms.
    
    build started...
    ✓ 0 modules transformed.
    [vite:css] [postcss] Cannot apply unknown utility class: text-md
    file: /Users/paddy/Development/ui_suite_daisyui-3508143/starterkits/ui_suite_daisyui_starterkit/components/button/button.pcss.css:undefined:NaN
    
    build started...
    ✓ 1 modules transformed.
    ./components/alert/alert.css          0.09 kB │ gzip: 0.10 kB
    ./components/accordion/accordion.css  0.13 kB │ gzip: 0.13 kB
    ./components/button/button.css        0.44 kB │ gzip: 0.23 kB
    built in 441ms.
    
  • 🇱🇺Luxembourg paddy_deburca

    Christian,

    I have updated the Vite config to also include the theme CSS (/src/css/input.css).

    ❯ npx vite build
    vite v6.2.2 building for production...
    
    (!) outDir /Users/paddy/Development/ui_suite_daisyui-3508143/starterkits/ui_suite_daisyui_starterkit is not inside project root and will not be emptied.
    Use --emptyOutDir to override.
    
    transforming (1) components/accordion/accordion.pcss.css/*! 🌼 daisyUI 5.0.2 */
    [vite:css][postcss] Parse error on line 1: 
    ...calc(var(--radius-field) + var(--radius-field) + var(--radius-field)))
    ------------------------------------------------------------------------^
    Expecting end of input, "ADD", "SUB", "MUL", "DIV", got unexpected "RPAREN"
    
    ✓ 5 modules transformed.
    ./components/alert/alert.css            0.09 kB │ gzip:  0.10 kB
    ./components/accordion/accordion.css    0.13 kB │ gzip:  0.13 kB
    ./components/button/button.css          0.44 kB │ gzip:  0.23 kB
    ./dist/css/style.css                  168.64 kB │ gzip: 28.06 kB
    ✓ built in 1.32s
    

    Vite is using PostCSS to process the CSS with TailwindCSS, stylelint, and cssnano.

    Is there anything else that needs to be considered?

    Should we write some Vite tests? I have never done so before, but at the moment I cannot think of anything else. :-)

    Paddy.

  • 🇩🇪Germany Christian.wiedemann

    Hi Paddy,

    your VITE config is very cool! The only thing is that --emptyOutDir will propably delete the whole project. So I think the we need a dist folder and only copy the CSS files back to the src folder. According to chatgpt there are two possibilities.:

    Copy after

    export default defineConfig({
      build: {
        rollupOptions: {
          output: {
            assetFileNames: (assetInfo) => {
              if (assetInfo.name.endsWith(".css")) {
                return "../src/styles/[name][extname]"; // Ändere den Pfad für CSS-Dateien
              }
              return "assets/[name][extname]"; // Andere Dateien bleiben im dist-Ordner
            },
          },
        },
      },
    });
    

    Change dest folder

    import { defineConfig } from "vite";
    import postcss from "postcss";
    import viteStaticCopy from "vite-plugin-static-copy";
    
    export default defineConfig({
      plugins: [
        viteStaticCopy({
          targets: [
            {
              src: "dist/assets/*.css", // Der Pfad der generierten CSS-Dateien
              dest: "src/styles", // Der gewünschte Zielpfad
            },
          ],
        }),
      ],
      css: {
        postcss,
      },
      build: {
        rollupOptions: {
          output: {
            assetFileNames: (assetInfo) => {
              if (assetInfo.name.endsWith(".css")) {
                return "../src/styles/[name][extname]"; // Speichert CSS neben den Quelldateien
              }
              return "assets/[name][extname]"; // Andere Dateien bleiben in dist
            },
          },
        },
      },
    });
    

    I think I would go with the copy because then it is simple to go with a dist only variant.
    But I think we are nearly ready! Very cool. So the next steps from my point of view.

    1. Finalize VITE config.
    2. I would move the VITE config to a workspace folder under .build. (As in ui_suite_daisyui-3508143-starterkit-postcss ).
    Or should we go with the VITE only? What is your opinion?
    3. In the root package.json we can define a default build method which calls the watch:css and build:css in the related folder.
    4. Add the example components
    5. Cleanup
    6. Add docs.

    If you like I can do 2. and 3. @g4mbini can you help us with 4.?

  • 🇩🇪Germany Christian.wiedemann

    What I like on the workspace variant that we can easily integrate webpack (or something else in the future) and other tools like svg integration etc. without bloating the main project.

  • 🇱🇺Luxembourg paddy_deburca

    Christian,

    I have updated the Vite config - the outDir is now dest/css which gets overridden on each build, so it is OK to empty it.

    I have updated the packages.json with a list of scripts that can be run

      "scripts": {
        "dev":   "NODE_ENV=development vite build --emptyOutDir",
        "build": "NODE_ENV=production  vite build --emptyOutDir",
        "watch": "NODE_ENV=development vite build --emptyOutDir --watch"
      },
    
    

    I have 'played' with using the --mode to set production or development mode, but as PostCSS needs to know which mode we are using in order to compress CSS or not, I had to remain with the NODE_ENV environment variable.

    Building the CSS is as follows:

    ❯ npm run build
    
    > build
    > NODE_ENV=production  vite build --emptyOutDir
    vite v6.2.2 building for production...
    transforming (4) ../../components/alert/alert.pcss.css[vite:css][postcss] Parse error on line 1: 
    ...calc(var(--radius-field) + var(--radius-field) + var(--radius-field)))
    ------------------------------------------------------------------------^
    Expecting end of input, "ADD", "SUB", "MUL", "DIV", got unexpected "RPAREN"
    
    ✓ 5 modules transformed.
    ./components/alert/alert.css            0.09 kB │ gzip:  0.10 kB
    ./components/accordion/accordion.css    0.13 kB │ gzip:  0.13 kB
    ./components/button/button.css          0.44 kB │ gzip:  0.23 kB
    ./dist/css/style.css                  168.62 kB │ gzip: 28.10 kB
    ✓ built in 1.35s
    

    I can move the scripts to a .build folder and update the configuration to continue to deploy the CSS into the current folders. We will have three config files - Vite, PostCSS, and Stylelint.

    I will document the config files, and update the README.md file.

    When you mention a workspace folder - what do you mean exactly? My Vite config, and other configs, currently live in the root folder of the theme. The path looks the way it does due to one too many git clones.

  • 🇩🇪Germany Christian.wiedemann

    Hi Paddy,

    Can you push your changes. I will take your changes and merge the workspace stuff into one sum-up branch to show what I mean. Than maybe we a short meeting next week to dicuss it.

  • 🇩🇪Germany Christian.wiedemann

    Hi Paddy,
    the VITE setup works very well so let's use it and forget the multi build variants. I reviewed your config and I think there two problems with it.
    We should set the root folder to the root folder of the project. This is important for other plugins to ensure the right path.
    root: "dist/css",. And if I change the root folder --emptyOutDir deletes the whole project. So I updated the VITE config to:

    import { defineConfig } from 'vite';
    import { resolve, join, relative } from 'path';
    import { globSync } from 'glob';
    import { viteStaticCopy } from 'vite-plugin-static-copy';
    
    /**
     * CSS source folder globs.
     */
    const cssGlob = {
      'css': 'css/*.pcss.css',
      'components': 'components/**/*.pcss.css',
    }
    export default defineConfig(() => {
      const projectRoot = __dirname;
      const componentPaths = Object.keys(cssGlob);
    
      // Construct entry points using reduce for efficiency
      const entries = componentPaths.reduce((acc, componentFolder) => {
        const componentPath = join(projectRoot, cssGlob[componentFolder]);
        const files = globSync(componentPath);
    
        files.forEach(file => {
          const key = join(
            join('css', componentFolder),
            relative(join(projectRoot, componentFolder), file)
              .replace('.pcss.css', '')
          );
          acc[key] = resolve(projectRoot, file);
        });
    
        return acc;
      }, {});
    
      return {
        root: projectRoot,
        plugins: [
          viteStaticCopy({
            targets: [
              {
                src: "dist/css", // Path to generated CSS files
                dest: "../", // Target directory
              },
            ],
          }),
        ],
        css: {
          postcss: true,
        },
        build: {
          rollupOptions: {
            input: entries,
            output: {
              dir: join(projectRoot, 'dist'),
              assetFileNames: "[name].[ext]",
            },
          },
        },
        clean: true,
      };
    });
    

    I copied your stuff to a clean 5.0.x branch and pushed it to cleanup branch. (I think your branch was intial branched from 4.0 or?)
    I also added .prettier and a .styleignore. From my point of view only the example components are missing now.

    Thanks!

  • 🇩🇪Germany Christian.wiedemann

    I updated the CSS file structure and updated the documenation.

  • 🇫🇷France G4MBINI Bègles
Production build 0.71.5 2024