The directive makes sure the color of texts and other elements inside the parent with dynamically changed background color will stay readable and visible. The new style is chosen from optionally provided styles declarations by calculating it's contrast ratio with the current value of the background color.
npm install @kolory/angular-match-style-to-background
// 1. Import the directive's module.
import {NgModule, Component} from '@angular/core'
import {MatchStyleModule} from '@kolory/angular-match-style-to-background'
@NgModule({
...
import: [MatchStyleModule, ...],
})
class App {}
// 2. Use in a component. For more advanced use case, refer to #examples
@Component({
template: `<div [match-style-to-background]="backgroundColor"> ... </div>`
})
class MyComponent {
backgroundColor = '#FFFFFF'
}
match-style-to-background: string | Color
Directive expect at least the match-style-to-background
to be set on the element to actually make it work.
This property holds the current value of the background color that will be used when choosing a proper style.
The property can handle a string of the valid hex, RGB or HSL color or a Color object.
styles: {[index: string]: anyColor | Color}
The styles
property is a kew-value map of the style name (the key) and it's corresponding color (a hex, RGB
or HSL string or a Color object). The name is later
used as a part of the class name set on the parent element and in the style definition object in the styleChange
event. It can be any valid string you want to name your style.
For example:
// Using the stirng values.
const myStyles = {
radiant: '#FFFFFF',
dire: '#000000'
}
// Using the Color object
const myStyles = {
radiant: Color.white,
dire: Color.black
}
By default, the directive changes the element's color CSS property to the color of the matched style to make
texts readable. This means that in the simplest scenario, when there's only the required match-style-to-background
property set, everything is still usable. Default colors are black for light backgrounds and white for dark ones.
Since setting the style attribute might be too intrusive in some designs, this behavior can be turned off
by setting the setColor
property to false. In this case, the text readability and it's color are responsibilities
of the component using this directive.
<!-- Turn off the automatic color changes. -->
<div [match-style-to-background]="color" [setColor]="false"> ... </div>
When the new style is selected, directive emits the styleChange
event with the selected style's properties as
an event value. The object looks like this:
{
name: 'light-style', // the style's name defined in the `styles` property
color: Color('#FFFFFF'), // Color object made from the style's color
contrast: 21 // the style's color contrast to the active background color
}
Example:
<div [match-style-to-background]="color" [styles]={light: Color('#FFFFFF'), ...}
(styleChange)="handleStyleChange($event)"> ... </div>
// In a component
handleStyleChange(event) {
// If the light style was matched, the event object is {name: 'light', color: Color('#FFFFFF'), contrast: 21}.
}
When the style is matched, the style match directive sets a class name on the host element to allow custom styling and more advanced changes of design.
Class name added in this way is constructed from two parts: "matched-" prefix and the matched style's name. For example, if the matched style was named "dark", then the newly appended class will be "matched-dark".
The simples use of the directive is to only set the match-style-to-background
property. The text color will be
changed using default black and white colors.
@Component({
template: `
<div [match-style-to-background]="randomlyPickColor()">
This text will have a different color depending on which button was clicked.
</div>`
})
class MyComponent {}
Color is updated after user picks a color.
@Component({
template: `
<button (click)="background = '#000000'">Black</button>
<button (click)="background = '#FFFFFF'">White</button>
<div [match-style-to-background]="background" [styles]="{'light': '#EEEEEE', dark: '#101010'}">
This text will have a different color depending on which button was clicked.
</div>`
})
class MyComponent {}
Style change is defined in the stylesheet using the .matched-
class names. Automatic color change is disabled
to make sure the CSS rules will be applied.
@Component({
styles: [`
.matched-light .child {
color: purple;
}
.matched-dark .child {
color: pink;
}
`],
template: `
<div [match-style-to-background]="background" [styles]="{'light': '#EEEEEE', dark: '#101010'}" [setColor]="false">
<p class="child"> ... </p>
</div>`
})
class MyComponent {}
// Import the Color constructor. Color utilities is a dependency of this directive, so it's already available.
import {Color} from '@kolory/color-utilities'
// Import style interfaces.
import {StylesDeclaration, Style} from '@kolory/angular-match-style-to-background'
@Component({
template: `
<div [angular-match-style-to-background]="background" [styles]="styles" (styleChange)="handleChange($event)"></div>`
})
class MyComponent {
styles: StylesDeclaration = {
'ultra-red': Color.create('#FF0000'),
'eco-green': Color.create('#00FF00'),
'sky-blue': Color.create('#0000FF')
}
handleChange(changedStyle: Style) {
// If 'ultra-red` was matched, then the method is called witn the object:
// {name: 'ultra-red', color: Color('#FF0000'), contrast: 9}
if (changedStyle.contrast < 10) {
alert(`The ${changedStyle.name}` constrast is too low. ${changedStyle.color.hex}" won't work.`)
}
}
}
MIT