poimen / stencil-tailwind-plugin Goto Github PK
View Code? Open in Web Editor NEWPlugin for using tailwindcss with StencilJS
Home Page: https://www.npmjs.com/package/stencil-tailwind-plugin
License: MIT License
Plugin for using tailwindcss with StencilJS
Home Page: https://www.npmjs.com/package/stencil-tailwind-plugin
License: MIT License
As this plugin is a rollup plugin (no pluginType: 'css'), this is run AFTER the stencil hydrate plugin is run.
The problem:
Stencil hydrate adds comments to the css classes so the scoped classes can later be rewritten to work hydrated component again.
Now with this plugin, all tailwind inline-classes and utility classes, which generate more classes (:hover
, lg:, md:
and so on) are added AFTER the comments for the hydrate package have been created. Resulting in broken styles with SSR.
We have created our own plugin thanks to your source code (and searching the tailwindcss source) which runs as a css
plugin, fully creating all css classes BEFORE any Stencil plugin runs.
One drawback is that we need to load the tsx file manually (like tailwindcss does with changedContent) and don't have any _sourceTsx already set (has same content as sourceCss), as the plugin is run only on css files.
Thanks for all your hard work.
Importing javascript files that include .css
in the middle of the file name (e.g. my-file.css.js
) leads to a rollup error:
Rollup: Plugin Error
Cannot read properties of undefined (reading 'text') (plugin: tailwind, transform)
The package that triggered this error for me is @spectrum-web-components/overlay
. So this can be reproduced by adding this package to a project and importing it into a stencil component as follows:
import { Overlay } from '@spectrum-web-components/overlay';
The useStyleSheetTransform
check is too loose so javascript ends up being treated as CSS
Hi,
thanks for the plugin. Right now I struggle with one thing. If I add the tailwind classes all works fine, as long as I have a styleUrl. With just style or even without an empty file set it doesn't work. If I use Tailwindcss I usually add a css file.
Best regards,
Dominik
Stencil imports use a ?...shadow
that causes tailwind jit to input shadow styles into the final out even when shadows are not used
Hey,
I am running newest Tailwind (3.1.8) and plugin version (1.5.1) and I am getting following error:
[ERR] Oh noes! Something went wrong! Cannot read properties of undefined (reading 'separator')
[ERR] TypeError: Cannot read properties of undefined (reading 'separator')
at buildRegExps (/Users/dennis/Local Sites/fabrikat/app/public/wp-content/plugins/streamline/package/node_modules/tailwindcss/lib/lib/defaultExtractor.js:67:44)
at buildRegExps.next (<anonymous>)
at Function.from (<anonymous>)
at defaultExtractor (/Users/dennis/Local Sites/fabrikat/app/public/wp-content/plugins/streamline/package/node_modules/tailwindcss/lib/lib/defaultExtractor.js:51:26)
at b (/Users/dennis/Local Sites/fabrikat/app/public/wp-content/plugins/streamline/package/node_modules/purgecss/lib/purgecss.js:1:4289)
at PurgeCSS.extractSelectorsFromFiles (/Users/dennis/Local Sites/fabrikat/app/public/wp-content/plugins/streamline/package/node_modules/purgecss/lib/purgecss.js:1:6443)
at async /Users/dennis/Local Sites/fabrikat/app/public/wp-content/plugins/streamline/package/node_modules/@fullhuman/postcss-purgecss/lib/postcss-purgecss.js:1:1153
at async LazyResult.runAsync (/Users/dennis/Local Sites/fabrikat/app/public/wp-content/plugins/streamline/package/node_modules/postcss/lib/lazy-result.js:433:15)
at async I (/Users/dennis/Local Sites/fabrikat/app/public/wp-content/plugins/streamline/package/node_modules/stencil-tailwind-plugin/dist/index.js:7:4202)
at async /Users/dennis/Local Sites/fabrikat/app/public/wp-content/plugins/streamline/package/node_modules/stencil-tailwind-plugin/dist/index.js:7:7752
It goes away when I don't use the defaultExtractor.
It would be cool if by default the components without any reference to a CSS file guarantee the usage of the TW. At the moment it seems that if there aren't components with CSS files associated, the TW classes fail. I guess this happens because the TW utility classes are not included by default or something like that (more research might be necessary). However, when there is at least one component that has a reference to a CSS file, other components seem to not require the CSS file.
Using the example project:
https://github.com/Poimen/stencil-tailwind-plugin-example
Reproduction:
npm start
)hero-section.css
After the above, the component is refreshed but the @apply directive is directly put onto the component, without being transformed into it's proper tailwind class. For example if I add
@apply text-clip
My component ends up with this style:
If I manually reload the page, the style appears properly (e.g. text-overflow: clip;
in the above example). But it would be great if this worked properly. Happy to help with a fix but not really sure where to start.
See:
https://github.com/ionic-team/stencil-postcss/pull/35/files
Could this be used to map dependent files better when in FCs are used?
Hi, me again ๐ .
I have worked on this for a few days but can't get it fixed. Not entirely sure if this is related to your plugin though. But basically when I open the Developer tools everything things become slow. Also I have the feeling that the same issues causes the browser to be slow, but can't say that for sure yet.
I am quite certain I know the problem for the slow Developer Tools though. Let me paint the picture (I added some new commits to my example project, so you can follow along whilst I paint this picture. I have the following DOM structure:
index.html
<my-page></my-page>
<my-component></my-component>
<my-second-component></my-second-component>
I count four custom components that are used. The problem I am having is when I open the Developer Tools I get the styling reference for the body
four times. See screenshot:
When you remove a component from the DOM structure, for example <my-third-component></my-third-component>
which makes it three custom components in the DOM, the body
styling also drops to three references.
Now, imagine a component library of 40-50 components and an application which consumes said component library. The application has some pretty complex pages which use a ton of those custom UX components from the library. From a single navigation component to tens of custom input components. You can imagine that the Developer Tools gets a ton of duplicate styling references to the DOM elements like in the simple example I gave earlier. I also suspect it slows down the performance of my application while using it, but can't say that for sure.
This is because the same configuration is applied per component, so each component generates the same safelist. With Web Components in the shadow DOM, the idea is that they are self contained with all their CSS without leaking (or as little as possible). Hence, the "pass in the config and capture the CSS per component" works.
Quote from here. So reading that, I understand that Stencil JS generates this for each of the used components in the DOM? Hence the amount of references?
Is there a way to prevent those extra references? Because in combination with the generated TW CSS and the amount of components I have/use, it's becoming a performance nightmare to be honest. See the short video. This is filtered on one particular class for one specific element. This is not even the biggest list of references I had one a single element.
If you think it has nothing to do with your plugin just let me know, I'll move the issue to the Stencil JS repository. Thanks anyway!
It seems that plain html files, like index.html
are not supported. Also, global CSS/Sass/Scss files are not supported. The @apply
utility doesn't work.
I'm trying to get postcss working, but it seems the examples and docs aren't working for me.
Project to reproduce here: hirosystems/connect#346
yarn
npx lerna run build --scope @stacks/connect-ui
This builds the stencil component in the monorepo. Inspecting the file at packages/connect-ui/dist/cjs/connect-modal.cjs.entry.js
shows the modalCss
is NOT renamed. Anything I'm missing?
Also, removing
tailwindHMR
removes CSS completely -- not sure if that is intended ๐ค
Thanks for the project, thanks for the help ๐
Thank you for this plugin! I think it's going to make things much easier for a project I'm on.
For my project we have a separate package where we use stencil to build web components, and most of them are using scoped CSS instead of shadow DOM. We're then using these components in an app with tailwind, so we have an app-wide global tailwind stylesheet with styles that will be available to the web components since they're not isolated in the shadow DOM. This plugin allows us to use @apply
in our component stylesheets, but if the .tsx
file uses a utility like flex
it will also end up in the compiled stylesheet even though that class is already in the global stylesheet.
I've been trying to get the plugin to exclude utilities it finds in .tsx
files without much luck. Is this possible with the current config options, or would this optimization require changes to the actual plugin itself?
Original issue: tailwindlabs/tailwindcss#5296
As far as I can tell there's currently no way to run the Tailwind output through additional PostCSS plugins, but some classes need vendor prefixes to work in certain browsers, e.g. bg-clip-text
It would be nice if you could specify additional PostCSS plugins. Alternatively, Autoprefixer could be added by default, similar to how postcss-import
and cssnano
are already.
I am getting the above warning. But the classes seems to be generated properly. Is there something I am doing wrong? Any way to get rid of the warning?
module.exports = {
content: [
'./src/**/*.{html,tsx,txt}',
'./src/safelist.txt'
],
prefix: 'ux-',
theme: {},
plugins: []
};
Also small side question. It seems to be ignoring './src/safelist.txt'
in the content. Is that a tailwind thingy or is this something the plugin doesn't process? Thanks in advance!
I'm using this plugin with enablePurge
set to 'false'.
I thought that if I set it to 'false', 'purgecss' would not work and the tailwind CSS would not be removed.
However, in fact, the unused CSS was removed.
Was this the correct behavior?
I apologize if I am using it incorrectly.
export const config: config = {
plugins: [tailwind({ enablePurge: false })],
};
I have created a repository to check the behavior of this configuration.
The 'text-blue-500' provided by tailwind has been removed.
I hope it will be useful for your investigation.
https://github.com/contiki9/stencil-test-tailwind
Thank you for creating a nice plugin.
Hey,
first of all, great plugin! Works wonderfully besides the problem in the title.
I've seen the entry in the readme, but for me no styles are being generated at all, even when the build command is run.
Hi there,
first thanks a lot for your plugin - it work's really great!
But I am facing issues with a tailwind breakpoint "flex flex-col md:flex-row" that get's applied, but does not take effect due to the wrong order of css styles... I have a root component that is using shadow=true. The root component uses other components, which may also use other components. The only component I tagged with shadow=true is the root component. I do this, because the subcomponents always get mounted into the root, so I don't need a shadow dom for those anymore. Shadow would duplicate my styles a lot, e.g. I am rendering a list of components, that would each repeat my styles when using shadow -> would blow up my dom a lot.
So there is some workarounds I found that this issue does not happen, e.g.:
The thing is I plan to use this plugin for a lot of more components, some of them need shadow as they are getting used as root components, other components don't need it as I simply use them in other components. I can't use functional components as they require a state.
Is there any configuration option, I can use to control the order of the styles generated or tell the plugin to put all css of non shadow components into one <style></style> directive?
Thanks a lot for you help
Regarding the `safelist` option in the Tailwind config. Yeah, I've tried using that but it messes up the performance when starting the project for development. Takes minutes before it starts and I don't want that ๐
. Basically, I need every text and background color to be present in the Tailwind output. This is because I have an `Avatar` component that gets it background color and text color (when profile image is not available) based on the user that is currently logged in. So, it's dynamic.
I've tried the following patterns to add those classes. These aren't even all the available colors and it took too long to process. I even tried adding them manually in the safelist
array. So I though adding one more file that contains all the classes I want in, into the source and content
option would be far more performant. So I guess that's not an option then?
safelist: [
'ux-bg-white',
'ux-bg-black',
'ux-text-white',
'ux-text-black',
{
pattern: /ux-bg-(gray|red|yellow|green|blue|purple)-(50|100|200|300|400|500|600|700|800|900)/
},
{
pattern: /ux-text-(gray|red|yellow|green|blue|purple)-(50|100|200|300|400|500|600|700|800|900)/
}
],
Regarding the warning. I got a lot of components (about 40 now) with loads of TW styling, so thats why I thought the warning weird ๐. Perhaps it is because I use ux-
prefix for the TW classes? I don't know. Looks like it doesn't cause any problems though. Not sure if problems will arise in the near future while developing the UX project. I surely hope not ๐.
Originally posted by @dtaalbers in #23 (comment)
Hi,
first thanks for great plugin.
I have problem with tailwinds predefined animations. I am using animate-ping
as you see in example below.
<span class="absolute -top-1 -right-1 flex h-3 w-3">
<span class="absolute inline-flex h-full w-full animate-ping rounded-full bg-red-400 opacity-75"></span>
<span class="relative inline-flex h-3 w-3 rounded-full bg-red-500"></span>
</span>
The problem is that after build there is missing keyframe declaration in styles so the animation never run. Is there a way how to resolve this? Thank You guys..
My stencil config
import { Config } from '@stencil/core';
import tailwind, { tailwindHMR } from 'stencil-tailwind-plugin';
import tailwindConfig from './tailwind.config';
export const config: Config = {
namespace: 'm29-components',
plugins: [
tailwind({
tailwindConf: tailwindConfig,
tailwindCssPath: './src/styles/tailwind.css',
}),
tailwindHMR(),
],
outputTargets: [
{
type: 'dist',
esmLoaderPath: '../loader',
},
{
type: 'dist-custom-elements',
},
{
type: 'docs-readme',
},
{
type: 'www',
serviceWorker: null, // disable service workers
},
],
};
My tailwind config:
const defaultTheme = require('tailwindcss/defaultTheme');
module.exports = {
content: [],
theme: {
fontFamily: {
mono: [...defaultTheme.fontFamily.mono],
sans: ['Montserrat', ...defaultTheme.fontFamily.sans],
title: ['Dongle', ...defaultTheme.fontFamily.sans]
},
},
plugins: [
],
}
Doing:
<Host class="flex items-center justify-center fixed left-0 top-0 h-screen w-full">
doesn't compile/build the classes.
But if the classes are moved to CSS, then work just fine:
:host {
@apply flex items-center justify-center fixed left-0 top-0 h-screen w-full;
}
Hi,
Am trying to this plugin along with @stencil/sass
plugin.
Am getting the below error:
Rollup: Parse Error Unexpected token (Note that you need plugins to import files that are not JavaScript)
The code below:
import { sass } from '@stencil/sass';
import tailwind from 'stencil-tailwind';
autoprefixCss: true,
plugins: [
sass({
injectGlobalPaths: ['src/styles/index.scss'],
}),
tailwind(),
],
Can you please help on this.
Thanks
Thank you for creating this plugin! I failed to get it to work properly though. I am not sure if and what I am doing wrong. I've made a quick example project in which I am trying to get the plugin to work.
See https://github.com/dtaalbers/tailwindcss-stenciljs-example for the complete setup that I am using. The issues that I am having are described in the README of the repository. I will paste them below for clarity. I am running in two issues that really block me during development of components with the latest version 3 (including the JIT engine) of Tailwind CSS. I would appreciate if you can help me out.
npm start
bg-red-400
to bg-blue-400
bg-blue-400
. Because I have --watch
running I'd expect the tailwind classes in www/build/tailwindcss-stenciljs-example.css
to be refreshed based on the current classes in the component and or stylesheets. At the moment for the changes to be visible you have to re-run npm start
.src/index.html
and/or other html files in the src folder.npm start
src/index.html
. The component should be centered in the page, which it isn't. Only when a tailwind class is used in the component it gets added to the www/build/tailwindcss-stenciljs-example.css
stylesheet and when the same class from the component is used in the HTML file you can see the styling being applied. Of course, that is because the tailwind class gets added due to it being used in the component. I'd expect the tailwind classes in al HTML files (provided by content
in the tailwind config) to be added as well when starting via npm start
and when making a change in one of the HTML files or components.src/index.html
(and in the future more HTML files) to create a nice application to show case my developed components.Thank you in advance!
Node version: 16.14.0
I'm using NX workspaces and trying to integrate stencil/tailwind but I'm getting this error
I followed this example. This error happens when I set tailwindCssPath in stencil.config.ts
import { Config } from '@stencil/core';
import { sass } from '@stencil/sass';
import tailwind, { tailwindHMR } from 'stencil-tailwind-plugin';
import tailwindcss from 'tailwindcss';
import { defaultExtractor } from 'tailwindcss/lib/lib/defaultExtractor';
import tailwindConf from './tailwind.config';
import purgecss from '@fullhuman/postcss-purgecss';
import autoprefixer from 'autoprefixer';
export const config: Config = {
namespace: 'design-system',
taskQueue: 'async',
plugins: [
sass(),
tailwind({
tailwindConf,
tailwindCssPath: './src/styles/tailwind.css',
postcss: {
plugins: [
tailwindcss(),
purgecss({
content: ['./**/*.tsx'],
safelist: [
':root',
':host',
':shadow',
'/deep/',
'::part',
'::theme',
],
defaultExtractor,
}),
autoprefixer(),
],
},
}),
tailwindHMR(),
],
outputTargets: [
{
type: 'dist',
esmLoaderPath: '../loader',
dir: '../../dist/libs/design-system/dist',
},
{
type: 'www',
dir: '../../dist/libs/design-system/www',
serviceWorker: null, // disable service workers
},
],
};
my package.json
{
"name": "monorepo-frontend",
"version": "0.0.0",
"license": "MIT",
"scripts": {
"ng": "nx",
"postinstall": "node ./decorate-angular-cli.js && ngcc --properties es2015 browser module main",
"start": "nx serve",
"build": "nx build",
"test": "nx test",
"ds:build": "npx nx build design-system",
"ds:start": "npx nx run design-system:serve"
},
"private": true,
"dependencies": {
"@angular-architects/module-federation": "^13.0.1",
"@angular/animations": "~13.2.0",
"@angular/common": "~13.2.0",
"@angular/compiler": "~13.2.0",
"@angular/core": "~13.2.0",
"@angular/forms": "~13.2.0",
"@angular/platform-browser": "~13.2.0",
"@angular/platform-browser-dynamic": "~13.2.0",
"@angular/router": "~13.2.0",
"@nrwl/angular": "13.8.3",
"@nxext/stencil": "^13.1.2",
"autoprefixer": "^10.4.2",
"rxjs": "~7.4.0",
"tslib": "^2.0.0",
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "~13.2.0",
"@angular-eslint/eslint-plugin": "~13.0.1",
"@angular-eslint/eslint-plugin-template": "~13.0.1",
"@angular-eslint/template-parser": "~13.0.1",
"@angular/cli": "~13.2.0",
"@angular/compiler-cli": "~13.2.0",
"@angular/language-service": "~13.2.0",
"@fullhuman/postcss-purgecss": "^4.1.3",
"@nrwl/cli": "13.8.3",
"@nrwl/cypress": "13.8.3",
"@nrwl/eslint-plugin-nx": "13.8.3",
"@nrwl/jest": "13.8.3",
"@nrwl/linter": "13.8.3",
"@nrwl/tao": "13.8.3",
"@nrwl/workspace": "13.8.3",
"@stencil/angular-output-target": "^0.4.0",
"@stencil/core": "^2.12.0",
"@stencil/postcss": "2.1.0",
"@stencil/sass": "1.5.2",
"@tailwindcss/forms": "^0.4.0",
"@types/autoprefixer": "^9.7.2",
"@types/jest": "27.0.2",
"@types/node": "16.11.7",
"@types/puppeteer": "~5.4.4",
"@typescript-eslint/eslint-plugin": "~5.10.0",
"@typescript-eslint/parser": "~5.10.0",
"cssnano": "^5.0.17",
"cypress": "^9.1.0",
"eslint": "~8.7.0",
"eslint-config-prettier": "8.1.0",
"eslint-plugin-cypress": "^2.10.3",
"jest": "26.6.3",
"jest-config": "26.6.3",
"jest-preset-angular": "11.1.1",
"prettier": "^2.5.1",
"puppeteer": "~5.3.1",
"stencil-tailwind-plugin": "^1.2.2",
"tailwindcss": "^3.0.23",
"ts-jest": "26.5.6",
"typescript": "~4.5.2"
}
}
The sass
and scss
syntax are not supported.
NOTE: The scss
syntax is most likely supported only if it's 1:1 with plain CSS.
I would like to experiment adding a tailwind plugin... I tried to follow the steps below and pass this new tailwind.config.js like in this example:
tailwind({
tailwindConf: tailwindConfig
}),
Install DaisyUI as Tailwind CSS plugin
(You need Node.js and Tailwind CSS installed.)
i tried to rebuild my apps with this using the latest TailwindCSS 3.0.0 release, but it appears that requires changes to this plugin. I tried to update this plugin locally, but i haven't been successful in getting something that runs...
Steps to reproduce:
Prop() foo = "bar"
<div class="bg-gray-100"></div>
Workaround:
Hi everyone, i followed the doc of stencil-tailwind-plugin to setup it to my stencil-storybook project but it's not working.
As you can see to the screenshot the font-bold class is correctly working but the text color is not applied.
๐ https://github.com/hotchpotch-lab/stencilfy/tree/1-setup-storybook
// stencil.config.ts
import { Config } from '@stencil/core';
import tailwind, { tailwindHMR } from 'stencil-tailwind-plugin';
export const config: Config = {
namespace: 'stencilfy',
devServer: {
port: 4000,
reloadStrategy: 'pageReload',
openBrowser: false
},
outputTargets: [
{
type: 'dist',
esmLoaderPath: '../loader',
},
{
type: 'dist-custom-elements',
},
{
type: 'docs-readme',
footer: 'Built by Aperrix & Damokless'
},
{
type: 'www',
serviceWorker: null, // disable service workers
},
],
plugins: [
tailwind(),
tailwindHMR()
],
};
// my-component.tsx
export class MyComponent {
/**
* The first name
*/
@Prop() first: string;
/**
* The middle name
*/
@Prop() middle: string;
/**
* The last name
*/
@Prop() last: string;
/**
* The text color
*/
@Prop() textColor: string = 'black'
private getText(): string {
return format(this.first, this.middle, this.last);
}
render() {
return <div class={`font-bold text-${this.textColor}-500`}>Hello, World! I'm {this.getText()}</div>;
}
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.