palantir / blueprint

A React-based UI toolkit for the web
https://blueprintjs.com/
Apache License 2.0
20.6k stars 2.16k forks source link

svg-icon - (path: (fill: #5f6b7c)) isn't a valid CSS value #5334

Closed yshterev closed 1 year ago

yshterev commented 2 years ago

Hello,

I am trying to build the sass in custom webpack setup. I get this error ☝️ It is reproducible in the example below 👇 using create-react-app

I think it has to do with the @vgrid/sass-inline-svg , but I don't have anything like this locally. Is this even expected to work anymore?

Environment

Code Sandbox

Sandbox example

Steps to reproduce

  1. Open sandbox
  2. Check main.scss

Actual behavior

Fails to compile sass

Expected behavior

Should compile without issues ... like in v3

adidahiya commented 2 years ago

You will have to include the Sass plugins Blueprint uses in order to re-compile its Sass source code. See more discussion about this in https://github.com/palantir/blueprint/issues/5297 and my comment here https://github.com/palantir/blueprint/issues/4032#issuecomment-1086175879.

yshterev commented 2 years ago

@adidahiya Thanks for the answer! Still I have not managed to figure out a way around this issue.

As I understand, If I can't build imported sass files I can't use the sass variables to customize components. From what I know CSS vars are not supported.

For this to work @vgrid/sass-inline-svg should be part of my app build and I should also have the icon files locally, however I can't seem to find a way to use it with webpack in sass-loader as a custom function. I assume it should go there somewhere...

Also @vgrid/sass-inline-svg was introduced in https://github.com/palantir/blueprint/commit/8f25ff1c41990a3b81f688883df587e8c4387165 as part of the dart-sass migration, but @vgrid/sass-inline-svg still depends on node-sass. IMO kind of weird.

Maybe I am missing something out.. any feedback appreciated. As you said in your comments locking to 4.0.0 works without issues.

naylinnpkv commented 2 years ago

@adidahiya I am running into the same issue, when trying to use BlueprintJs with ViteJs, any progress or tips to work around it?

sumeet07 commented 2 years ago

@adidahiya I am running into the same issue, when trying to use BlueprintJs (version > 4.1.0) with React18. What blueprint css plugin are you referring to address the issue?

adidahiya commented 2 years ago

This is our build script to compile our Sass sources: https://github.com/palantir/blueprint/blob/f8415b517c307e7c7fe0c76acdfbfdeae332e233/packages/node-build-scripts/sass-compile.ts#L61-L69

Note that I don't recommend pinning yourself to version ~4.0.0, that's just a way to prevent build breakage from automatic upgrades. You should always try to upgrade to the latest version of Blueprint, as we continuously release bug fixes and improvements.

We've migrated to dart-sass and we're not going back, so I suggest trying to get your build working with the latest Blueprint if you have the time to upgrade. If you can share your experience & roadblocks along the way so the Blueprint community can learn from them, that's even better. Perhaps try the suggestion of the @use syntax here: https://github.com/palantir/blueprint/issues/5297#issuecomment-1139676466

knalinne commented 1 year ago

Hello,

I'm experiencing the same issue.

my index.scss file use blueprint, with a custom primary color.

@use '@blueprintjs/core/src/blueprint' with (
    $pt-intent-primary: $custom-primary-color,
);

I initially had this issue:

SassError: (path: (fill: #5f6b7c)) isn't a valid CSS value.                                         
   ╷                                                                                                
39 │       background: svg-icon("16px/chevron-right.svg", (path: (fill: $pt-icon-color)));          
   │                                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^            
   ╵                                                                                                
  node_modules\@blueprintjs\core\src\components\breadcrumbs\_breadcrumbs.scss 39:54  @import    

this problem come from a missing function:

https://github.com/palantir/blueprint/blob/df7c038bc5da95a4f021fc59395defeeb77e2d25/packages/core/scripts/sass-custom-functions.js#L26-L30

I was able to duplicate it in my webpack config, but .... the resources folder does not exists in the @blueprintjs core or icons dependency.

Any clue on how I can fix this ?

Thanks for your help :-)

yshterev commented 1 year ago

Hi @knalinne How did you add the function to webpack? Can you show code? As for ../../resources/icons .. I guess you can copy this folder from blueprint repo, add it to your project and make build resolve from there.

knalinne commented 1 year ago

Hello @yshterev I do not directly use webpack, I use craco.

I copied the function in my config file:

// craco.config.js
const CracoEsbuildPlugin = require("craco-esbuild");
const inliner = require("@vgrid/sass-inline-svg");
module.exports = {
  plugins: [{ plugin: CracoEsbuildPlugin }],
  style: {
    sass: {
      loaderOptions: {
        // functions from blueprint : https://github.com/palantir/blueprint/blob/develop/packages/core/scripts/sass-custom-functions.js
        sassOptions: {
          functions: {
            "svg-icon($path, $selectors: null)": inliner("resources/icons", {
              // run through SVGO first
              optimize: true,
              // minimal "uri" encoding is smaller than base64
              encodingFormat: "uri",
            }),
          },
        },
      },
    },
  },
};

As you suggest, I copied the resources folder in the root of my project and it seems to work.

artemavrin commented 1 year ago

Hey! How to solve this with vite?

adidahiya commented 1 year ago

With https://github.com/palantir/blueprint/pull/5904, you will be able to re-use Blueprint's SVG icon inliner if you want to compile its source files:

import { sassSvgInlinerFactory } from "@blueprintjs/node-build-scripts";
import sass from "sass";

const sassFunctions = {
    /**
     * Sass function to inline a UI icon svg and change its path color.
     *
     * Usage:
     * svg-icon("16px/icon-name.svg", (path: (fill: $color)) )
     */
    "svg-icon($path, $selectors: null)": sassSvgInlinerFactory("path/to/resources/icons", {
        optimize: true,
        encodingFormat: "uri",
    }),
};

const inputFilePath = "...";
const result = await sass.compileAsync(inputFilePath, {
    functions: sassFunctions,
    // more Sass options
});

or, in webpack config (EDIT: this doesn't currently work, see https://github.com/palantir/blueprint/issues/6051#issuecomment-1537241019):

import { sassSvgInlinerFactory } from "@blueprintjs/node-build-scripts";
import sass from "sass";

const sassFunctions = {
    /**
     * Sass function to inline a UI icon svg and change its path color.
     *
     * Usage:
     * svg-icon("16px/icon-name.svg", (path: (fill: $color)) )
     */
    "svg-icon($path, $selectors: null)": sassSvgInlinerFactory("path/to/resources/icons", {
        optimize: true,
        encodingFormat: "uri",
    }),
};

export default {
    module: {
        rules: [
            {
                test: /\.scss$/,
                use: [
                    require.resolve("style-loader"),
                    require.resolve("css-loader"),
                    {
                        loader: require.resolve("sass-loader"),
                        options: {
                            sassOptions: {
                                functions: sassFunctions,
                            },
                        },
                    },
                ],
            },
        ],
    },
};

or, just use the sass-compile script included in @blueprintjs/node-build-scripts.

Note that you will have to continue copying the resources/icons directory from this repo, since that's not available in an NPM package. I might publish those icon files in a more official public API at some point.