matyunya / smelte

UI framework with material components built with Svelte and Tailwind CSS
https://smeltejs.com/
MIT License
1.52k stars 114 forks source link

using with sveltekit #230

Open schmurfy opened 3 years ago

schmurfy commented 3 years ago

How to use this with sveltekit+postcss ? I hoped that with time passing the frontend stack would improve but on the configuration side I discovered that it has now gotten even worse, importing the component is the easy step but importing the css...

I tried importing it directly into a component but it complains that bg-dark-500 does not exists, I have a _global.postcss file imported into my layout which includes the tailwind directives so I tried to add an @import inside but after that I get another error:

TypeError: Cannot read property 'length' of undefined
    at posToNumber (/Users/Schmurfy/Dev/personal/projects/meetme/node_modules/vite/dist/node/chunks/dep-efe32886.js:4037:27)
    at generateCodeFrame (/Users/Schmurfy/Dev/personal/projects/meetme/node_modules/vite/dist/node/chunks/dep-efe32886.js:4062:13)
    at formatError (/Users/Schmurfy/Dev/personal/projects/meetme/node_modules/vite/dist/node/chunks/dep-efe32886.js:43488:42)
    at TransformContext.error (/Users/Schmurfy/Dev/personal/projects/meetme/node_modules/vite/dist/node/chunks/dep-efe32886.js:43447:19)
    at Object.transform (/Users/Schmurfy/Dev/personal/projects/meetme/node_modules/vite/dist/node/chunks/dep-efe32886.js:43652:25)
    at async transformRequest (/Users/Schmurfy/Dev/personal/projects/meetme/node_modules/vite/dist/node/chunks/dep-efe32886.js:59310:29)
    at async instantiateModule (/Users/Schmurfy/Dev/personal/projects/meetme/node_modules/vite/dist/node/chunks/dep-efe32886.js:68846:10)

I just wanted to quickly prototype an app and I already spent more time trying to make things work :/

ppusapati commented 3 years ago

Try importing each component individually. make sure tailwind css in configured.

import {Button} from 'smeltejs/src/components/Button.svelte'

MirrorBytes commented 3 years ago

Don't use @import inside a style block to import the directives with SvelteKit. Import the directive file into a script block using .css as the extension.

MirrorBytes commented 3 years ago

You could just setup a new SvelteKit project with tailwind and PostCSS in the setup window. Then install Smelte and import the non-compiled components. That should really be the only setup needed to begin.

SillyFreak commented 3 years ago

@MirrorBytes maybe you could help me out here? I basically did what you're suggesting by following this setup, once with --jit and once without. I then installed smelte as a dev dependency and tried to use it like this:

<script lang="ts">
import Button from 'smelte/src/components/Button/Button.svelte';
</script>

<Button>Button</Button>

I got some styling - the shape and shadow is correct and the text color is white, but there's no background color. fwiw, this is what my postcss.config.cjs...

const tailwindcss = require("tailwindcss");
const autoprefixer = require("autoprefixer");
const cssnano = require("cssnano");

const mode = process.env.NODE_ENV;
const dev = mode === "development";

module.exports = {
    plugins: [
        // Some plugins, like postcss-nested, need to run before Tailwind

        tailwindcss,

        // But others, like autoprefixer, need to run after

        autoprefixer,

        !dev && cssnano({
            preset: "default",
        }),
    ],
};

... and tailwind.config.cjs ...

const { tailwindExtractor } = require("tailwindcss/lib/lib/purgeUnusedStyles");

module.exports = {
    purge: {
        content: [
            "./src/**/*.{html,js,svelte,ts}",
        ],
        options: {
            defaultExtractor: (content) => [
                // If this stops working, please open an issue at https://github.com/svelte-add/tailwindcss/issues rather than bothering Tailwind Labs about it
                ...tailwindExtractor(content),
                // Match Svelte class: directives (https://github.com/tailwindlabs/tailwindcss/discussions/1731)
                ...[...content.matchAll(/(?:class:)*([\w\d-/:%.]+)/gm)].map(([_match, group, ..._rest]) => group),
            ],
            keyframes: true,
        },
    },
    theme: {
        extend: {},
    },
    variants: {
        extend: {},
    },
    plugins: [],
};

... look right now. I also tried to add "./node_modules/smelte/src/**/*.{html,js,svelte,ts}" to purge.content, but at this point I'm only guessing.

MirrorBytes commented 3 years ago

Ok, so I see your issue. Since SvelteKit doesn't use Rollup, you won't get the theme unless you modify a bit..

I'll create a repo to get it functioning.

MirrorBytes commented 3 years ago

Actually, I'll just post the fix here. Change the following in a fresh SvelteKit project with tailwind (JIT or not) and static adapter:

module.exports = { purge: { content: ['./src/*/.{html,js,svelte,ts}'], options: { defaultExtractor: (content) => [ // If this stops working, please open an issue at https://github.com/svelte-add/tailwindcss/issues rather than bothering Tailwind Labs about it ...tailwindExtractor(content), // Match Svelte class: directives (https://github.com/tailwindlabs/tailwindcss/discussions/1731) ...[...content.matchAll(/(?:class:)*([\w\d-/:%.]+)/gm)].map( ([_match, group, ..._rest]) => group ) ], keyframes: true } }, theme: { extend: { width: { '1/7': '14.2857143%', '2/7': '28.5714286%', '3/7': '42.8571429%', '4/7': '57.1428571%', '5/7': '71.4285714%', '6/7': '85.7142857%' } }, fontSize: { '5xl': '6rem', '4xl': '3.75rem', '3xl': '3rem', '2xl': '2.125rem', xl: '1.5rem', lg: '1.25rem', base: '1rem', sm: '0.875rem', xs: '0.75rem' }, breakpoints: { sm: { max: '639px' }, md: { max: '767px' }, lg: { max: '1023px' }, xl: { max: '1279px' } }, lineHeight: { none: 1, tight: 1.25, normal: 1.45, relaxed: 1.75, loose: 2 }, colors: { transparent: 'transparent', white: '#fff', 'white-trans': 'rgba(255,255,255,0.2)', 'white-transLight': 'rgba(255,255,255,0.2)', 'white-transDark': 'rgba(255,255,255,0.2)', 'black-trans': 'rgba(0,0,0,0.2)', 'black-transLight': 'rgba(0,0,0,0.2)', 'black-transLight': 'rgba(0,0,0,0.2)', 'black-transDark': 'rgba(0,0,0,0.35)', 'white-500': '#fff', black: '#000',

        ...buildPalette({
            primary: '#b027b0',
            secondary: '#009688',
            error: '#f44336',
            success: '#4caf50',
            alert: '#ff9800',
            blue: '#2196f3',
            dark: '#212121'
        }),

        // brown: {
        //   "50": "#efebe9",
        //   "100": "#d7ccc8",
        //   "200": "#bcaaa4",
        //   "300": "#a1887f",
        //   "400": "#8d6e63",
        //   "500": "#795548",
        //   "600": "#6d4c41",
        //   "700": "#5d4037",
        //   "800": "#4e342e",
        //   "900": "#3e2723",
        //   trans: "rgba(62,39,35,0.5)",
        //   transLight: "rgba(62,39,35,0.1)",
        //   transDark: "rgba(62,39,35,0.35)"
        // },

        gray: {
            50: '#fafafa',
            100: '#f5f5f5',
            200: '#eeeeee',
            300: '#e0e0e0',
            400: '#bdbdbd',
            500: '#9e9e9e',
            600: '#757575',
            700: '#616161',
            800: '#424242',
            900: '#212121',
            trans: 'rgba(250, 250, 250, 0.5)',
            transLight: 'rgba(250, 250, 250, 0.1)',
            transDark: 'rgba(100, 100, 100, 0.2)'
        }

        // "blue-gray": {
        //   "50": "#eceff1",
        //   "100": "#cfd8dc",
        //   "200": "#b0bec5",
        //   "300": "#90a4ae",
        //   "400": "#78909c",
        //   "500": "#607d8b",
        //   "600": "#546e7a",
        //   "700": "#455a64",
        //   "800": "#37474f",
        //   "900": "#263238",
        //   trans: "rgb(236,239,241,0.5)",
        //   transLight: "rgb(236,239,241,0.6)",
        //   transDark: "rgb(236,239,241,0.2)"
        // }
    }
},
variants: {
    backgroundColor: ['dark', 'dark-hover', 'hover'],
    borderColor: ['dark', 'dark-focus'],
    textColor: ['dark', 'dark-hover', 'dark-active']
},
plugins: [
    require('tailwind-css-variables')(),
    function ({ addUtilities }) {
        return addUtilities({
            ['.border-box']: {
                boxSizing: 'border-box'
            },
            ['.content-box']: {
                boxSizing: 'content-box'
            }
        });
    },
    addUtility({
        prop: 'caret-color',
        className: '.caret'
    }),
    addUtility({
        prop: 'stroke',
        className: '.stroke'
    }),
    function ({ addVariant, e }) {
        const d = '.mode-dark';

        addVariant('dark', ({ modifySelectors, separator }) => {
            modifySelectors(({ className }) => {
                return `${d} .${e(`dark${separator}${className}`)}`;
            });
        });

        addVariant('dark-hover', ({ modifySelectors, separator }) => {
            modifySelectors(({ className }) => {
                return `${d} .${e(`dark-hover${separator}${className}`)}:hover`;
            });
        });

        addVariant('dark-focus', ({ modifySelectors, separator }) => {
            modifySelectors(({ className }) => {
                return `${d} .${e(`dark-focus${separator}${className}`)}:focus`;
            });
        });

        addVariant('dark-active', ({ modifySelectors, separator }) => {
            modifySelectors(({ className }) => {
                return `${d} .${e(`dark-active${separator}${className}`)}:active`;
            });
        });
    }
]

};


- root `$layout.svelte`
```html
<script>
    import 'smelte/src/tailwind.css';
</script>

<slot />

Hello world!

Visit svelte.dev to learn how to build Svelte apps.


- `Counter.svelte`
```html
<script lang="ts">
    import Button from 'smelte/src/components/Button/Button.svelte';

    let count = 0;

    const increment = (): void => {
        count += 1;
    };
</script>

<Button dark on:click={increment}>
    Clicks: {count}
</Button>
MirrorBytes commented 3 years ago

A permanent fix for this, to make it usable with existing Svelte projects and SvelteKit projects, would be to convert the Rollup plugin to a postcss "plugin". It might be a bit ugly, but it would do the job.

SillyFreak commented 3 years ago

thank you for the quick and comprehensive help!! fyi, it did not work with --jit - that automatically purges the styles and still makes problems, I'll investigate that.

MirrorBytes commented 3 years ago

No problem! And that's odd, hopefully it's a simple fix.

SillyFreak commented 3 years ago

So I wasn't so far off with adding './node_modules/smelte/src/**/*.{html,js,svelte,ts}' to purge.content in tailwind.config.cjs - tailwind-jit will scan all components for classes they are using - this is a simple string search. But the issue is that smelte assembles many class strings programmatically, e.g. in Button (excerpt):

  const basicDefault = 'text-white duration-200 ease-in';

  $: classes = cb
      .flush()
      .add(basicClasses, basic, basicDefault)
      .add(`${bg(normal)} hover:${bg(lighter)}`, basic)

So text-white is detected, but bg-primary-500 obviously isn't.

(A complication to properly debugging this was that styles once detected will linger until the dev server is restarted; this made me think that not doing anything already mostly worked, when the purge.content experiment was actually responsible for some of that - the theme was still missing of course.)

The fix: add a safelist to purge.content that lists all the styles actually used by smelte on my site. The exact format doesn't matter, as long as it contains all classnames with whitespace in between.

I guess this will have a better solution by the time tailwind-jit is declared stable.

MirrorBytes commented 3 years ago

I hope it has a more solid solution, because that safelist can get insanely large depending on the project... given that programmatic generation in general is pretty standard amongst add-in components with svelte.

sjmcdowall commented 3 years ago

Hey guys! If I may beg for some assistance here -- I am in the same prediciment -- except I want to also have access to the default tailwind colors, etc. AND use Smelte ..

I started with the vanilla SvelteKit project and followed the tailwindcss add-ons and those all worked. However, adding Smelte is a nightmare. :) I followed the above -- but now it appears the "stock" tailwind things are gone -- for example this 500 error message:

Thetext-red-600class does not exist, buttext-gray-600does. If you're sure thattext-red-600exists, make sure that any@importstatements are being properly processed before Tailwind CSS sees your CSS, as@applycan only be used for classes in the same CSS tree.

I have a global.css (from the tailwind stuff) that looks like

/* Write your global styles here, in PostCSS syntax */
/* @tailwind base;
@tailwind components;
@tailwind utilities; */
/* @import 'tailwindcss/base';

@import 'tailwindcss/components';

@import 'tailwindcss/utilities'; */

And my $layout.svelte looks like:

<script lang="ts">
    import '../global.css';
    import 'smelte/src/tailwind.css';
</script>

<slot />

The purge discussion above is -- well -- a bit over my head -- if that is the solution as to what to do -- if that even makes sense ...

TIA!

MirrorBytes commented 3 years ago

@sjmcdowall Sorry about that, inside the colors object, wrap the custom colors in an extend object, like:

...
colors: {
    extend: {
        ...
    }
}
...

This will extend the default palette instead of overwriting it.

sjmcdowall commented 3 years ago

@MirrorBytes --Yep! WOOHOO! Still, that's quite a bit of modiciation to get this going -- hope it becomes easier somehow in the future .. I would NEVER have figured out the changes to the tailwind.config.cjs to do all that !

MirrorBytes commented 3 years ago

Like I said, hopefully it's ported to a usable plugin for SvelteKit since Rollup isn't available.

JanMalch commented 3 years ago

I'm having issues with the fix above and the latest @sveltejs/kit@1.0.0-next.107. Not sure if I'm missing something in my configs. Does this fix still work? Could you provide a working repository @MirrorBytes ?

thienpow commented 3 years ago

can try look into this quick workaround hack... export the css from sapper and dump it into sveltekit's app.css... https://sveltekit-smelte.vercel.app/ https://github.com/thienpow/sveltekit-smelte

JanMalch commented 3 years ago

I've uploaded my minimal working setup in my sveltekit-smelte-setup repository. It uses the Tailwind config from above without any (other?) hacks.

geoidesic commented 3 years ago

This works fine unless TailwindCSS is in JIT mode, in which case Smelte styling vanishes. Any ideas why or how to fix this?

SillyFreak commented 3 years ago

yes, that is what I discussed above; it's not too pretty...

mysticaltech commented 3 years ago

Please do a pull request folks, this good project needs SvelteKit support ASAP.

benmccann commented 3 years ago

@schmurfy your error looks like Vite crashing while trying to print an error and so you can't see what the actual error is. If you have repo that reproduces this, I'd be happy to put together a fix and send it to Vite

benjamin-kirkbride commented 2 years ago

I can't even execute npm run dev with latest sveltekit and smelte..

(this will be run only when your dependencies or config have changed)
 > node_modules/rollup-pluginutils/dist/pluginutils.es.js:1:15: error: No matching export in "browser-external:path" for import "extname"
    1 │ import path, { extname, sep, resolve } from 'path';                                                                                                                                                         
      ╵                ~~~~~~~                                                                            

 > node_modules/rollup-pluginutils/dist/pluginutils.es.js:1:24: error: No matching export in "browser-external:path" for import "sep"
    1 │ import path, { extname, sep, resolve } from 'path';
      ╵                         ~~~                                                                                                                                                                                 

 > node_modules/rollup-pluginutils/dist/pluginutils.es.js:1:29: error: No matching export in "browser-external:path" for import "resolve"
    1 │ import path, { extname, sep, resolve } from 'path';
      ╵                              ~~~~~~~                                                              

 > node_modules/purgecss/lib/purgecss.esm.js:1:7: error: No matching export in "browser-external:fs" for import "access"
    1 │ import{access as e,readFile as t,constants as s}from"fs";import r from"glob";import i from"path";import{parse as a}from"postcss";import n from"postcss-selector-parser";import{promisify as o}from"util";...
      ╵        ~~~~~~                                                                                     

 > node_modules/purgecss/lib/purgecss.esm.js:1:19: error: No matching export in "browser-external:fs" for import "readFile"
    1 │ import{access as e,readFile as t,constants as s}from"fs";import r from"glob";import i from"path";import{parse as a}from"postcss";import n from"postcss-selector-parser";import{promisify as o}from"util";...
      ╵                    ~~~~~~~~

 > node_modules/purgecss/lib/purgecss.esm.js:1:33: error: No matching export in "browser-external:fs" for import "constants"
    1 │ import{access as e,readFile as t,constants as s}from"fs";import r from"glob";import i from"path";import{parse as a}from"postcss";import n from"postcss-selector-parser";import{promisify as o}from"util";...
      ╵                                  ~~~~~~~~~

 > node_modules/purgecss/lib/purgecss.esm.js:1:175: error: No matching export in "browser-external:util" for import "promisify"
    1 │ ...ort i from"path";import{parse as a}from"postcss";import n from"postcss-selector-parser";import{promisify as o}from"util";function c(e,t){t&&t.forEach(e.add,e)}class l{constructor(e){this.undetermine...
      ╵                                                                                                   ~~~~~~~~~

> Build failed with 7 errors:
node_modules/purgecss/lib/purgecss.esm.js:1:7: error: No matching export in "browser-external:fs" for import "access"
node_modules/purgecss/lib/purgecss.esm.js:1:19: error: No matching export in "browser-external:fs" for import "readFile"
node_modules/purgecss/lib/purgecss.esm.js:1:33: error: No matching export in "browser-external:fs" for import "constants"
node_modules/purgecss/lib/purgecss.esm.js:1:175: error: No matching export in "browser-external:util" for import "promisify"
node_modules/rollup-pluginutils/dist/pluginutils.es.js:1:15: error: No matching export in "browser-external:path" for import "extname"
...

Not sure if I'm missing something obvious, but I think at this point it is safe to say this is a pretty dire situation for the future of this package.

bugproof commented 2 years ago

I can't even execute npm run dev with latest sveltekit and smelte..

(this will be run only when your dependencies or config have changed)
 > node_modules/rollup-pluginutils/dist/pluginutils.es.js:1:15: error: No matching export in "browser-external:path" for import "extname"
    1 │ import path, { extname, sep, resolve } from 'path';                                                                                                                                                         
      ╵                ~~~~~~~                                                                            

 > node_modules/rollup-pluginutils/dist/pluginutils.es.js:1:24: error: No matching export in "browser-external:path" for import "sep"
    1 │ import path, { extname, sep, resolve } from 'path';
      ╵                         ~~~                                                                                                                                                                                 

 > node_modules/rollup-pluginutils/dist/pluginutils.es.js:1:29: error: No matching export in "browser-external:path" for import "resolve"
    1 │ import path, { extname, sep, resolve } from 'path';
      ╵                              ~~~~~~~                                                              

 > node_modules/purgecss/lib/purgecss.esm.js:1:7: error: No matching export in "browser-external:fs" for import "access"
    1 │ import{access as e,readFile as t,constants as s}from"fs";import r from"glob";import i from"path";import{parse as a}from"postcss";import n from"postcss-selector-parser";import{promisify as o}from"util";...
      ╵        ~~~~~~                                                                                     

 > node_modules/purgecss/lib/purgecss.esm.js:1:19: error: No matching export in "browser-external:fs" for import "readFile"
    1 │ import{access as e,readFile as t,constants as s}from"fs";import r from"glob";import i from"path";import{parse as a}from"postcss";import n from"postcss-selector-parser";import{promisify as o}from"util";...
      ╵                    ~~~~~~~~

 > node_modules/purgecss/lib/purgecss.esm.js:1:33: error: No matching export in "browser-external:fs" for import "constants"
    1 │ import{access as e,readFile as t,constants as s}from"fs";import r from"glob";import i from"path";import{parse as a}from"postcss";import n from"postcss-selector-parser";import{promisify as o}from"util";...
      ╵                                  ~~~~~~~~~

 > node_modules/purgecss/lib/purgecss.esm.js:1:175: error: No matching export in "browser-external:util" for import "promisify"
    1 │ ...ort i from"path";import{parse as a}from"postcss";import n from"postcss-selector-parser";import{promisify as o}from"util";function c(e,t){t&&t.forEach(e.add,e)}class l{constructor(e){this.undetermine...
      ╵                                                                                                   ~~~~~~~~~

> Build failed with 7 errors:
node_modules/purgecss/lib/purgecss.esm.js:1:7: error: No matching export in "browser-external:fs" for import "access"
node_modules/purgecss/lib/purgecss.esm.js:1:19: error: No matching export in "browser-external:fs" for import "readFile"
node_modules/purgecss/lib/purgecss.esm.js:1:33: error: No matching export in "browser-external:fs" for import "constants"
node_modules/purgecss/lib/purgecss.esm.js:1:175: error: No matching export in "browser-external:util" for import "promisify"
node_modules/rollup-pluginutils/dist/pluginutils.es.js:1:15: error: No matching export in "browser-external:path" for import "extname"
...

Not sure if I'm missing something obvious, but I think at this point it is safe to say this is a pretty dire situation for the future of this package.

Yup... Unfortunately seems like this project needs more maintainers. The other MUI library doesn't work neither. Pretty sad. I like Svelte a lot more than React and Vue but the community is very small. Look at Vuetify or material-ui for React. Those packages get new commits almost every day.

chetan commented 2 years ago

I'm not an expert when it comes to node packaging and the various bundles, but I was able to build on the work in this thread and some other samples I found to come up with a solution that seems to at least be working for me. I think the core issue is that smelte is not listing things like svelte and tailwind as a peer dependency.

I moved everything to peer deps in my fork and that appears to work for me. I tried moving only the core deps to peers in the peer2 branch but I couldn't get that working and eventually gave up and kept the first approach.

You can see an example with updated dependencies and notes on using this branch in my test repo.

djavorek commented 2 years ago

I'm not an expert when it comes to node packaging and the various bundles, but I was able to build on the work in this thread and some other samples I found to come up with a solution that seems to at least be working for me. I think the core issue is that smelte is not listing things like svelte and tailwind as a peer dependency.

I moved everything to peer deps in my fork and that appears to work for me. I tried moving only the core deps to peers in the peer2 branch but I couldn't get that working and eventually gave up and kept the first approach.

You can see an example with updated dependencies and notes on using this branch in my test repo.

Makes sense and looks clean, but also not sure about the side effects. Is there any chance we could merge this (after the some testing)? It would be really hacky to use your fork. @chetan

chetan commented 2 years ago

@djavorek Happy to open a PR, however there are still some issues with the integration that I haven't been able to fully resolve. Some components render perfectly while others (for ex, Chip) have some missing styles. Not clear if the issue is in tailwind, svelte, smelte, or elsewhere.

Personally, I gave up trying to get it perfect as the project where I'm using smelte is fairly trivial in scope and I didn't want to spend much more time trying to get it working.

djavorek commented 2 years ago

@chetan Well, I am working on a trivial use case as well, not sure I want to put much effort into this now. 😳

I switch to Svelte Material UI, which looks worse IMO, but it will get the job done for us and works out-of-the-box with SvelteKit.

Kuchiriel commented 2 years ago

Error: Error while preprocessing /mnt/c/IBeauty/node_modules/smelte/src/components/Icon/Icon.svelte - Cannot find module 'tailwindcss/lib/lib/purgeUnusedStyles' Require stack: