Skip to content
This repository has been archived by the owner on Aug 25, 2020. It is now read-only.
/ styler Public archive

CSS-in-JS tools for Angular applications

Notifications You must be signed in to change notification settings

ngx-kit/styler

Repository files navigation

Build Status npm version

Angular Styler

Keep CSS in TypeScript.

Currently in a deep beta!

Install

npm install @ngx-kit/styler --save

Usage

Provide module

import { StylerModule } from '@ngx-kit/styler';
...
@NgModule({
  imports: [
      ...
      StylerModule.forRoot(),
...

Use import with .forRoot() only once on the top level.

Add styles to component

...
@Component({
  ...
  viewProviders: [StylerComponent]
  ...
  constructor(private styler: StylerComponent) {
    this.styler.register({
      wrapper: {
        background: '#ffffff',
        color: 'red',
      },
      inside: {
        color: 'yellow',
        fontSize: '2rem',
      }
    });
    ...

Use styles in template

<div styler="wrapper">
  <div styler="inside">
  </div>
</div>

Cases

:host styling

Just define host element:

this.styler.register({
  host: {
    display: 'flex',
    flexDirection: 'column',
  },
});

Nested styles

this.styler.register({
  wrapper: {
    $nest: {
      '&:hover': {
        background: 'grey',
      },
      '& a': {
        textDecoration: 'none',
      },
    },
  },
});

Register media styles

this.styler.register({
  wrapper: {
    display: 'flex',
    flexDirection: 'row',
    $media: [
      [{maxWidth: 600}, {
        flexDirection: 'column',
      }],
    ],
  },
});

Element state styling

Define element states:

constructor(private def: StylerDefService)
...
this.styler.register({
  host: {
    ...
  },
  panel: (state) => {
    border: '1px solid green',
    // multi-state
    ...this.def.pick(state.size, {
      small: {
        padding: 2,
      },
      medium: {
        padding: 4,
      },
      large: {
        padding: 8,
      },
    }, 'medium'),
    // bool-state
    ...this.def.toggle(state.disabled, {
      color: '#666',
      background: '#999'
    }),
  },
  ...
});

Set state via service for host:

this.styler.host.applyState({size: 'small'});

Or set state with styler directive:

<div styler="panel" [stylerState]="{size: 'small'}"></div>

Move styles to a separate file

Provide styler view built-it module method:

@Component({
  ...
  viewProviders: [StylerModule.forComponent(ThisComponentStyle)],

Define style injectable:

import { Injectable } from '@angular/core';
import { ComponentStyle, StylerDefService, StyleDef } from '@ngx-kit/styler';

@Injectable()
export class ThisComponentStyle implements ComponentStyle {
  
  constructor(private def: StylerDefService) {
  }
  
  host(): StyleDef {
    return {
      display: 'block',
    };
  }
  
  wrapper(): StyleDef {
    return {
      background: '#ffffff',
      color: 'red',
    };
  }
  
  // state handling
  panel(state): StyleDef {
    return {
      border: '1px solid green',
      // multi-state
      ...this.def.pick(state.size, {
        small: {
          padding: 2,
        },
        medium: {
          padding: 4,
        },
        large: {
          padding: 8,
        },
      }, 'medium'),
      // bool-state
      ...this.def.toggle(state.disabled, {
        color: '#666',
        background: '#999'
      }),
    };
  };
  
}

Multi-register

Styles deep-merged from left to right.

this.styler.register([
  {
    host: {
      background: '#ffffff',
      color: 'yellow'
    },
  },
  {
    host: {
      color: 'red',
      fontSize: '1.1rem',
    },
  },
]);

Similar to:

this.styler.register([
  {
    host: {
      background: '#ffffff',
      color: 'red',
      fontSize: '1.1rem',
    },
  },
]);

Provide few separated styles to component:

viewProviders: [
  StylerModule.forComponent(LayoutStyle),
  StylerModule.forComponent(ThisComponentStyle),
],

Fallback styles

TBD

Smart styles

  • padding: [10, 20] => padding: '10px 20px'
  • padding: {top: 10, left: 30} => paddingTop: '10px', paddingLeft: '30px'
  • margin: [10, 20, 30] => padding: '10px 20px 30px'
  • border: [1, 'solid', 'blue'] => border: '1px solid blue'

Mixins

TBD

@keyframes

constructor(private styler: StylerComponent) {
  this.styler.register({
    host: {
      animationDuration: '1s',
      animationName: this.styler.keyframes({
        '0%': {
          transform: 'rotate(0deg)',
        },
        '100%': {
          transform: 'rotate(360deg)',
        },
      }),
      animationTimingFunction: 'linear',
      animationIterationCount: 'infinite',
    },
  });
}

Automatically add classes

Styler can add classes to elements. Class attribute based on component name (should be setted), element name and element state.

Provide BemClassGenStrategy:

providers: [
  {
    provide: ClassGenStategy,
    useClass: BemClassGenStrategy,
  },
],

Set component name:

constructor(private styler: StylerComponent) {
  this.styler.classPrefix = 'component-name';
}

Helpers

Styles definition

  • defPick(state: string, styles: StyleDef, default?: string) - returns styles[state|default]
  • defToggle(state: boolean, styles: StyleDef, falseStyles?: StyleDef) - returns styles if state is true
  • defMerge(styles: StyleDef[]) - js deepMerge, needed if states have $nest props

Colors

Helpers for color manipulating.

...
background: darken(0.2, someColorVar),
  • adjustHue
  • complement
  • darken
  • desaturate
  • grayscale
  • hsl
  • hsla
  • invert
  • lighten
  • mix
  • opacify
  • rgb
  • rgba
  • saturate
  • setHue
  • setLightness
  • setSaturation
  • shade
  • tint
  • toColorString
  • transparentize