0

I have an Angular 11 application that we build in several configurations specific to a customer. I am trying to implement a sensible theming pattern to allow each dist of the app to have it's own colour scheme relevant to the customers branding.

So far I have a styles folder that contains the following scss files for each customer: -

a palette.scss file

$custom-primary: (
    50: #e3e7ec,
    100: #b9c4d0,
    200: #8a9db1,
    300: #5b7691,
    400: #37587a,
    500: #143b62,
    600: #12355a,
    700: #0e2d50,
    800: #0b2646,
    900: #061934,
    A100: #6d9dff,
    A200: #3a7bff,
    A400: #0759ff,
    A700: #004eec,
    contrast: (
        50: $black-87-opacity,
        100: $black-87-opacity,
        200: $black-87-opacity,
        300: $black-87-opacity,
        400: $black-87-opacity,
        500: white,
        600: white,
        700: white,
        800: $white-87-opacity,
        900: $white-87-opacity,
        A100: $black-87-opacity,
        A200: white,
        A400: white,
        A700: white,
    ),
);

$custom-accent: (
    50: #eaf3fa,
    100: #cae0f2,
    200: #a7cce9,
    300: #84b7e0,
    400: #69a7da,
    500: #4f98d3,
    600: #4890ce,
    700: #3f85c8,
    800: #367bc2,
    900: #266ab7,
    A100: #f5f9ff,
    A200: #c2ddff,
    A400: #8fc0ff,
    A700: #75b2ff,
    contrast: (
        50: $black-87-opacity,
        100: $black-87-opacity,
        200: $black-87-opacity,
        300: $black-87-opacity,
        400: $black-87-opacity,
        500: white,
        600: white,
        700: white,
        800: $white-87-opacity,
        900: $white-87-opacity,
        A100: $black-87-opacity,
        A200: white,
        A400: white,
        A700: white,
    ),
);

$custom-warn: (
    50: #ffe0e0,
    100: #ffb3b3,
    200: #ff8080,
    300: #ff4d4d,
    400: #ff2626,
    500: #ff0000,
    600: #ff0000,
    700: #ff0000,
    800: #ff0000,
    900: #ff0000,
    A100: #ffffff,
    A200: #fff2f2,
    A400: #ffbfbf,
    A700: #ffa6a6,
    contrast: (
        50: $black-87-opacity,
        100: $black-87-opacity,
        200: $black-87-opacity,
        300: $black-87-opacity,
        400: $black-87-opacity,
        500: white,
        600: white,
        700: white,
        800: $white-87-opacity,
        900: $white-87-opacity,
        A100: $black-87-opacity,
        A200: white,
        A400: white,
        A700: white,
    ),
);

and then there is a theme.scss file

@import "~@angular/material/theming";
@import "./cchub-palette.scss";

@include mat-core();

$cchub-app-primary: mat-palette($custom-primary);
$cchub-app-accent: mat-palette($custom-accent, A200, A100, A400);
$cchub-app-warn: mat-palette($custom-warn);

$cchub-app-theme: mat-light-theme(
    (
        color: (
            primary: $cchub-app-primary,
            accent: $cchub-app-accent,
            warn: $cchub-app-warn,
        ),
    )
);

@include angular-material-theme($cchub-app-theme);

$primary: mat-color($cchub-app-primary);
$accent: mat-color($cchub-app-accent);
$warn: mat-color($cchub-app-warn);

$grey-text: rgba(0, 0, 0, 0.45);
$border: rgba(0, 0, 0, 0.25);
$light-grey: rgba(0, 0, 0, 0.1);

I also have a standard styles.scss file that holds all of my structural styles and I then created a variables.scss to allow access to the theme colours within each component

@import "~@angular/material/theming";

@mixin material-theme($theme) {
    $primary-palette: map-get($theme, primary);
    $accent-palette: map-get($theme, accent);
    $warn-palette: map-get($theme, warn);

     $primary: mat-color($cchub-app-primary);
     $accent: mat-color($cchub-app-accent);
     $warn: mat-color($cchub-app-warn);
}

$grey-text: rgba(0, 0, 0, 0.45);
$border: rgba(0, 0, 0, 0.25);
$light-grey: rgba(0, 0, 0, 0.1);

I then use the styles: [] entry within the angular.json file to include the relevant brand specific files for each customer. unfortunately I cannot access the $primary, $accent and $warn colours from the variables.scss file because they are scoped inside the @mixin.

I'm trying to avoid having @mixin statements inside every component just because I want to access the current $primary colour or such.

Any ideas?

Andrew HB
  • 332
  • 1
  • 3
  • 11

1 Answers1

1

Going by this approach this will not only make your application heaver but also it will increase complexity when you wanted to introduce some new color/variable only for one theme but not for the other. This will hamper the scalability of the application.

A better way would be creating two different files such as index-dark-theme.scss or index-light-theme.scss define all the related properties into respective file such as.

Inside your index-dark-theme.scss or index-light-theme-scss file you can import something like this

  • @import '~/<node_module imports>' eg(bootstrap);

  • @import 'varible-.scss';

  • @import 'utils.scss';

  • @import 'component-one-(theme).scss';

  • .... (Define all your same theme components here)

Structure for component-one component will look something like this

component-one

  • component-one.ts
  • component-one.html
  • component-one.scss
  • component-one-dark.scss
  • component-one-light-scss

In component-one.scss will hold all the css properties with variable assigned to each css property eg:

    $container-padding-left;
    $container-maring-right;
    $container-background;

.container {
 background: $container-background;
 padding-left: $container-padding-left;
 margin-right: $container-margin-right;
}

In component-one-(theme).scss theme file you just need to assign the values to variables defined by importing ```component-one.scss```` into your theme file.

@import 'component-one.scss';

    $container-padding-left : 20px !default;
    $container-margin-right: 50px  !default;
    $container-background: $bg-black-400 !default;

If you don't want to give any value to variable you can assign null so that that particular property will not render in css itself. eg: container-margin-right: null

Inside your utils.scss file you can define your generic functions or mixins and then you can use by both the themes. Just passing a different value form a particular theme file should work fine.

If incase in near future you wanted to introduce a new theme such as blue theme same pattern can be followed.

Depending on selection of theme you have to just replace index-<theme-name>.scss dynamically. Rest everything will work fine :).

By this approach it will become more dynamic as and will improve the scalability of your application.

Himanshu Saxena
  • 340
  • 3
  • 13