Hello All – my colleagues and I have been struggling with this one, so any help would be greatly appreciated!
Our project uses angular material and scss (including a custom material theme). We would like to add tailwind to this so that we can streamline as much of the styling as possible.
We know this is possible, as I was able to achieve it in my demo to the rest of the team; whereby I created a new project, set it up with scss and angular material, ran a custom theme, and then added tailwind to it, following the steps outlined here. This runs fine.
However, since then, I have failed in all attempts to apply tailwind to our existing project. Following the steps I took before (as in article), I am presented with the following errors when attempting to compile:
ERROR in Cannot read property 'flags' of undefinedERROR in ./src/styles/jml-theme.scss (C:/C4/C4UI_Feature/node_modules/css-loader/dist/cjs.js??ref--13-1!C:/C4/C4UI_Feature/node_modules/@angular-builders/custom-webpack/node_modules/postcss-loader/src??embedded!C:/C4/C4UI_Feature/node_modules/resolve-url-loader??ref--13-3!C:/C4/C4UI_Feature/node_modules/@angular-builders/custom-webpack/node_modules/sass-loader/dist/cjs.js??ref--13-4!C:/C4/C4UI_Feature/node_modules/postcss-loader/dist/cjs.js??ref--17!./src/styles/jml-theme.scss)
SassError: Plain CSS functions don't support keyword arguments.
╷
30 │ $fontConfig: mat-typography-config(
│ ┌──────────────^
31 │ │ $font-family: 'Lato, "Helvetica Neue", sans-serif',
32 │ │ $display-4: mat-typography-level(112px, 112px, 300),
33 │ │ $display-3: mat-typography-level(56px, 56px, 400),
34 │ │ $display-2: mat-typography-level(45px, 48px, 400),
35 │ │ $display-1: mat-typography-level(34px, 40px, 400),
36 │ │ $headline: mat-typography-level(32px, 48px, 500),
37 │ │ $title: mat-typography-level(24px, 33.6px, 400),
38 │ │ $subheading-2: mat-typography-level(16px, 22.4px, 500),
39 │ │ $subheading-1: mat-typography-level(16px, 22.4px, 400),
40 │ │ $body-1: mat-typography-level(16px, 22.4px, 400),
41 │ │ $body-2: mat-typography-level(16px, 22.4px, 500),
42 │ │ $button: mat-typography-level(14px, 14px, 500),
43 │ │ $caption: mat-typography-level(14px, 19.6px, 400),
44 │ │ $input: mat-typography-level(16px, 1, 400),
45 │ │ );
│ └─^
╵
projects\c4ui\src\styles\jml-theme.scss 30:14 root stylesheet
I find this odd, given that mat-typography-config is an scss mixin, and not a function. Removing this mixin and the code which subsequently relies upon it further down, namely:
@include mat-core($fontConfig);
Returns the first error again, followed by:
Module build failed (from C:/C4/C4UI_Feature/node_modules/@angular-builders/custom-webpack/node_modules/sass-loader/dist/cjs.js):
SassError: (main: #ffffff, lighter: #ffffff, darker: #ffffff, 200: #ffffff, contrast: (main: rgba(88, 88, 87, 0.87), lighter: rgba(88, 88, 87, 0.87), darker: rgba(88, 88, 87, 0.87))) isn't a valid CSS value.
╷
235 │ $theme-primary: mat-palette($mat-primary, main, lighter, darker);
│ ^^^^^^^^^^^^
╵
projects\c4ui\src\styles\jml-theme.scss 235:29 root stylesheet
As such, it is now refusing to recognise the following (defined in the line above the declaration of $theme-primary):
$mat-primary: (
main: colours.$base-white,
lighter: colours.$base-white,
darker: colours.$base-white,
200: colours.$base-white,
// For slide toggle,
contrast:
(
main: $dark-primary-text,
lighter: $dark-primary-text,
darker: $dark-primary-text,
),
);
For clarity, below is the entirety of the theme file:
/**
* Generated theme by Material Theme Generator
* https://materialtheme.arcsine.dev
*/
// @use "_colours.scss";
@use "colours";
@use "../../../../node_modules/@angular/material/_theming.scss";
// Include the common styles for Angular Material. We include this here so that you only
// have to load a single css file for Angular Material in your app.
// Fonts
// @import url("https://fonts.googleapis.com/icon?family=Material+Icons+Outlined");
// @import url("https://fonts.googleapis.com/css?family=Lato:300,400,500");
// @use "sass:map";
$fontConfig: mat-typography-config(
$font-family: 'Lato, "Helvetica Neue", sans-serif',
$display-4: mat-typography-level(112px, 112px, 300),
$display-3: mat-typography-level(56px, 56px, 400),
$display-2: mat-typography-level(45px, 48px, 400),
$display-1: mat-typography-level(34px, 40px, 400),
$headline: mat-typography-level(32px, 48px, 500),
$title: mat-typography-level(24px, 33.6px, 400),
$subheading-2: mat-typography-level(16px, 22.4px, 500),
$subheading-1: mat-typography-level(16px, 22.4px, 400),
$body-1: mat-typography-level(16px, 22.4px, 400),
$body-2: mat-typography-level(16px, 22.4px, 500),
$button: mat-typography-level(14px, 14px, 500),
$caption: mat-typography-level(14px, 19.6px, 400),
$input: mat-typography-level(16px, 1, 400),
);
// Foreground Elements
// Light Theme Text
$dark-text: colours.$greyish-brown;
$dark-primary-text: rgba($dark-text, 0.87);
$dark-accent-text: rgba($dark-primary-text, 0.54);
$dark-disabled-text: rgba($dark-primary-text, 0.38);
$dark-dividers: rgba($dark-primary-text, 0.12);
$dark-focused: rgba($dark-primary-text, 0.12);
$mat-light-theme-foreground: (
base: black,
divider: $dark-dividers,
dividers: $dark-dividers,
disabled: $dark-disabled-text,
disabled-button: rgba($dark-text, 0.26),
disabled-text: $dark-disabled-text,
elevation: black,
secondary-text: $dark-accent-text,
hint-text: $dark-disabled-text,
accent-text: $dark-accent-text,
icon: $dark-accent-text,
icons: $dark-accent-text,
text: $dark-primary-text,
slider-min: $dark-primary-text,
slider-off: rgba($dark-text, 0.26),
slider-off-active: $dark-disabled-text,
);
// Dark Theme text
$light-text: colours.$base-white;
$light-primary-text: $light-text;
$light-accent-text: rgba($light-primary-text, 0.7);
$light-disabled-text: rgba($light-primary-text, 0.5);
$light-dividers: rgba($light-primary-text, 0.12);
$light-focused: rgba($light-primary-text, 0.12);
$mat-dark-theme-foreground: (
base: $light-text,
divider: $light-dividers,
dividers: $light-dividers,
disabled: $light-disabled-text,
disabled-button: rgba($light-text, 0.3),
disabled-text: $light-disabled-text,
elevation: black,
hint-text: $light-disabled-text,
secondary-text: $light-accent-text,
accent-text: $light-accent-text,
icon: $light-text,
icons: $light-text,
text: $light-text,
slider-min: $light-text,
slider-off: rgba($light-text, 0.3),
slider-off-active: rgba($light-text, 0.3),
);
// Background config
// Light bg
$light-background: colours.$ice-blue;
$light-bg-darker-5: darken($light-background, 5%);
$light-bg-darker-10: darken($light-background, 10%);
$light-bg-darker-20: darken($light-background, 20%);
$light-bg-darker-30: darken($light-background, 30%);
$light-bg-lighter-5: lighten($light-background, 5%);
$dark-bg-tooltip: lighten(colours.$fill-primary-dark-blue, 20%);
$dark-bg-alpha-4: rgba(colours.$fill-primary-dark-blue, 0.04);
$dark-bg-alpha-12: rgba(colours.$fill-primary-dark-blue, 0.12);
$mat-light-theme-background: (
background: $light-background,
status-bar: $light-bg-darker-20,
app-bar: $light-bg-darker-5,
hover: $dark-bg-alpha-4,
card: $light-bg-lighter-5,
dialog: $light-bg-lighter-5,
tooltip: $dark-bg-tooltip,
disabled-button: $dark-bg-alpha-12,
raised-button: $light-bg-lighter-5,
focused-button: $dark-focused,
selected-button: $light-bg-darker-20,
selected-disabled-button: $light-bg-darker-30,
disabled-button-toggle: $light-bg-darker-10,
unselected-chip: $light-bg-darker-10,
disabled-list-option: $light-bg-darker-10,
);
// Dark bg
$dark-background: colours.$fill-primary-dark-blue;
$dark-bg-lighter-5: lighten($dark-background, 5%);
$dark-bg-lighter-10: lighten($dark-background, 10%);
$dark-bg-lighter-20: lighten($dark-background, 20%);
$dark-bg-lighter-30: lighten($dark-background, 30%);
$light-bg-alpha-4: rgba(colours.$ice-blue, 0.04);
$light-bg-alpha-12: rgba(colours.$ice-blue, 0.12);
// Background palette for dark themes.
$mat-dark-theme-background: (
background: $dark-background,
status-bar: $dark-bg-lighter-20,
app-bar: $dark-bg-lighter-5,
hover: $light-bg-alpha-4,
card: $dark-bg-lighter-5,
dialog: $dark-bg-lighter-5,
tooltip: $dark-bg-lighter-20,
disabled-button: $light-bg-alpha-12,
raised-button: $dark-bg-lighter-5,
focused-button: $light-focused,
selected-button: $dark-bg-lighter-20,
selected-disabled-button: $dark-bg-lighter-30,
disabled-button-toggle: $dark-bg-lighter-10,
unselected-chip: $dark-bg-lighter-20,
disabled-list-option: $dark-bg-lighter-10,
);
// Compute font config
@include mat-core($fontConfig);
// Theme Config
body {
--primary-color: colours.$base-white;
--primary-lighter-color: colours.$base-white;
--primary-darker-color: colours.$base-white;
--text-primary-color: #{$dark-primary-text};
--text-primary-lighter-color: #{$dark-primary-text};
--text-primary-darker-color: #{$dark-primary-text};
}
$mat-primary: (
main: colours.$base-white,
lighter: colours.$base-white,
darker: colours.$base-white,
200: colours.$base-white,
// For slide toggle,
contrast:
(
main: $dark-primary-text,
lighter: $dark-primary-text,
darker: $dark-primary-text,
),
);
$theme-primary: mat-palette($mat-primary, main, lighter, darker);
body {
--accent-color: colours.$fill-primary-dark-blue;
--accent-lighter-color: colours.$aqua-blue;
--accent-darker-color: colours.$fill-secondary-chronicle-blue;
--text-accent-color: #{$light-primary-text};
--text-accent-lighter-color: #{$dark-primary-text};
--text-accent-darker-color: #{$light-primary-text};
}
$mat-accent: (
main:colours.$fill-primary-dark-blue,
lighter:colours.$aqua-blue,
darker: colours.$fill-secondary-chronicle-blue,
200:colours.$fill-secondary-chronicle-blue,
// For slide toggle,
contrast:
(
main: $light-primary-text,
lighter: $dark-primary-text,
darker: $light-primary-text,
),
);
$theme-accent: mat-palette($mat-accent, main, lighter, darker);
body {
--warn-color: colours.$fill-secondary-chronicle-pink;
--warn-lighter-color:colours.$twilight;
--warn-darker-color: colours.$cherry;
--text-warn-color: #{$light-primary-text};
--text-warn-lighter-color: #{$dark-primary-text};
--text-warn-darker-color: #{$light-primary-text};
}
$mat-warn: (
main:colours.$fill-secondary-chronicle-pink,
lighter: colours.$twilight,
darker: colours.$cherry,
200: colours.$fill-secondary-chronicle-pink,
// For slide toggle,
contrast:
(
main: $light-primary-text,
lighter: $dark-primary-text,
darker: $light-primary-text,
),
);
$theme-warn: mat-palette($mat-warn, main, lighter, darker);
$theme: mat-light-theme($theme-primary, $theme-accent, $theme-warn);
$altTheme: mat-dark-theme($theme-primary, $theme-accent, $theme-warn);
// Theme Init
@include angular-material-theme($theme);
.theme-alternate {
@include angular-material-theme($altTheme);
}
// Specific component overrides, pieces that are not in line with the general theming
// Handle buttons appropriately, with respect to line-height
.mat-raised-button,
.mat-stroked-button,
.mat-flat-button {
padding: 0 1.15em;
margin: 0 0.65em;
min-width: 3em;
line-height: 36.4px;
}
.mat-standard-chip {
padding: 0.5em 0.85em;
min-height: 2.5em;
}
.material-icons {
font-size: 24px;
font-family: "Material Icons Outlined", "Material Icons";
.mat-badge-content {
font-family: "Lato";
};
color: map.get($mat-accent, "main");
}
My webpack and tailwind config files are located at the root of the project, and are set up, respectively, as follows:
const merge = require('webpack-merge');
module.exports = (config) => {
const isProd = config.mode === "production";
const tailwindConfig = require("./tailwind.config.js")(isProd);
return merge(config, {
module: {
rules: [
{
test: /\.scss$/,
loader: 'postcss-loader',
options: {
postcssOptions: {
ident: 'postcss',
syntax: 'postcss-scss',
plugins: [
require('postcss-import'),
require('tailwindcss')(tailwindConfig),
require('autoprefixer'),
]
}
}
}
]
}
});
};
module.exports = (isProd) => ({
corePlugins: {
preflight: false,
},
prefix: '',
future: {
removeDeprecatedGapUtilities: true,
purgeLayersByDefault: true
},
purge: {
enabled: isProd,
content: ['**/*.html', '**/*.ts']
},
theme: {
extend: {
colors: {
'jml-greyish-brown': 'rgba(88, 88, 87, 0.1)',
'jml-ice-blue': '#e5eef1',
'jml-fill-primary-dark-blue': '#015c75',
'jml-fill-secondary-bright-green': '#01753d',
}
}
}
});