Skip to content

Commit 88f1c00

Browse files
committed
feat(theming-material): redesign api to correct usage of material-color-utilities
1 parent 5e189f0 commit 88f1c00

2 files changed

Lines changed: 83 additions & 55 deletions

File tree

packages/theming-material/src/scheme.spec.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,24 @@
22

33
import { TestBed } from '@angular/core/testing';
44
import { provideTheme, ThemeTokenRegistry } from '@angularity/theming';
5+
import { SchemeVibrant } from '@material/material-color-utilities';
6+
import { withThemeBuilder } from 'packages/theming/src/builder-composition';
57

68
import { provide } from '../../core/src/provide';
79
import { TestingThemeTokenRegistry } from '../../theming/src/token';
8-
import { SchemeBuilder, SchemeMode, SchemeVariant } from './scheme';
10+
import { SchemeBuilder, SchemeContrastLevel, SchemeMode } from './scheme';
911

1012
describe('SchemeBuilder', () => {
1113
it('should work', () => {
1214
TestBed.configureTestingModule({
1315
providers: [
1416
provideTheme(
15-
{ schemes: SchemeBuilder },
16-
{
17-
schemes: {
18-
primary: '#33bdff',
19-
mode: SchemeMode.Light,
20-
variant: SchemeVariant.CONTENT,
21-
},
22-
},
17+
withThemeBuilder('scheme', SchemeBuilder, {
18+
type: SchemeVibrant,
19+
source: '#33bdff',
20+
mode: SchemeMode.Light,
21+
contrast: SchemeContrastLevel.Standard,
22+
}),
2323
),
2424
TestingThemeTokenRegistry,
2525
provide({
@@ -29,7 +29,7 @@ describe('SchemeBuilder', () => {
2929
],
3030
});
3131
const tokens = TestBed.inject(TestingThemeTokenRegistry).tokens;
32-
expect(tokens['schemes-primary']).toBeDefined();
33-
expect(tokens['schemes-on-primary']).toBe('#ffffff');
32+
expect(tokens['scheme-primary']).toBeDefined();
33+
expect(tokens['scheme-on-primary']).toBe('#ffffff');
3434
});
3535
});

packages/theming-material/src/scheme.ts

Lines changed: 72 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6,43 +6,89 @@ import {
66
} from '@angularity/theming';
77
import {
88
argbFromHex,
9-
CorePalette,
109
DynamicColor,
1110
DynamicScheme,
11+
Hct,
1212
hexFromArgb,
1313
MaterialDynamicColors,
1414
} from '@material/material-color-utilities';
1515

1616
/**
17-
* Copy of the internal enum `Variant` from `@material/material-color-utilities`.
17+
* Mode for Material color schemes.
18+
* @see `SchemeBuilder`
1819
*/
19-
export enum SchemeVariant {
20-
/* eslint-disable @typescript-eslint/naming-convention */
21-
MONOCHROME = 0,
22-
NEUTRAL = 1,
23-
TONAL_SPOT = 2,
24-
VIBRANT = 3,
25-
EXPRESSIVE = 4,
26-
FIDELITY = 5,
27-
CONTENT = 6,
28-
RAINBOW = 7,
29-
FRUIT_SALAD = 8,
30-
/* eslint-enable @typescript-eslint/naming-convention */
31-
}
32-
3320
export enum SchemeMode {
3421
Light = 'Light',
3522
Dark = 'Dark',
3623
}
3724

25+
/**
26+
* Common contrast level values for Material color schemes.
27+
* @see `SchemeBuilder`
28+
*/
29+
export enum SchemeContrastLevel {
30+
Reduced = -1.0,
31+
Standard = 0.0,
32+
Medium = 0.5,
33+
High = 1.0,
34+
}
35+
36+
/**
37+
* Constructor of `DynamicScheme` from `material-color-utilities`.
38+
*
39+
* Available values include:
40+
* - `SchemeTonalSpot`: classic Material Design 3 colors
41+
* - `SchemeVibrant`: more vibrant colors
42+
* - `SchemeMonochrome`: grayscale colors
43+
* - `SchemeNeutral`: colors that are nearly grayscale
44+
* - `SchemeFidelity`: match the source color as closely as possible
45+
* - etc.
46+
*
47+
* @see https://github.com/material-foundation/material-color-utilities/tree/main/typescript/scheme for all available scheme types
48+
*
49+
* @example
50+
* ```ts
51+
* import { SchemeTonalSpot } from '@material/material-color-utilities';
52+
* const type: SchemeType = SchemeTonalSpot;
53+
* ```
54+
*/
55+
export interface SchemeType {
56+
new (source: Hct, isDark: boolean, contrast: number): DynamicScheme;
57+
}
58+
59+
/**
60+
* Configuration for `SchemeBuilder`.
61+
*/
3862
export interface SchemeBuilderConfig {
39-
primary: string;
40-
secondary?: string;
41-
tertiary?: string;
42-
variant: SchemeVariant;
63+
/**
64+
* The type of color scheme to generate. See `SchemeType` for details.
65+
*/
66+
type: SchemeType;
67+
68+
/**
69+
* The source/seed color to use for creating the color scheme. The generated
70+
* color scheme may deviate from this color at some extent, depending on the
71+
* chrome of the source color and the algorithm used by the `SchemeType`.
72+
*/
73+
source: string;
74+
75+
/**
76+
* The mode of the color scheme. Light or Dark.
77+
*/
4378
mode: SchemeMode;
79+
80+
/**
81+
* The contrast level of the color scheme. See `SchemeContrastLevel` for
82+
* common values, or use a number between -1 to 1 for custom values, where
83+
* -1 is the lowest contrast and 1 is the highest.
84+
*/
85+
contrast: SchemeContrastLevel | number;
4486
}
4587

88+
/**
89+
* Implementation of `ThemeBuilder` that generates hex color tokens for all
90+
* color roles under Material Design 3 color schemes.
91+
*/
4692
@Injectable({ providedIn: 'root' })
4793
export class SchemeBuilder implements ThemeBuilder<SchemeBuilderConfig> {
4894
build(context: ThemeBuilderContext<SchemeBuilderConfig>): ThemeTokens {
@@ -57,29 +103,11 @@ export class SchemeBuilder implements ThemeBuilder<SchemeBuilderConfig> {
57103
return tokens;
58104
}
59105

60-
getScheme(config: SchemeBuilderConfig): DynamicScheme {
61-
const palette = this.getCorePalette(config);
62-
const scheme = new DynamicScheme({
63-
sourceColorArgb: argbFromHex(config.primary),
64-
variant: config.variant as any,
65-
isDark: config.mode === SchemeMode.Dark,
66-
contrastLevel: 0.0,
67-
primaryPalette: palette.a1,
68-
secondaryPalette: palette.a2,
69-
tertiaryPalette: palette.a3,
70-
neutralPalette: palette.n1,
71-
neutralVariantPalette: palette.n2,
72-
});
73-
return scheme;
74-
}
75-
76-
getCorePalette(config: SchemeBuilderConfig): CorePalette {
77-
const read = (v: string) => argbFromHex(v);
78-
const readOpt = (v: string | undefined) => (v ? read(v) : undefined);
79-
return CorePalette.fromColors({
80-
primary: read(config.primary),
81-
secondary: readOpt(config.secondary),
82-
tertiary: readOpt(config.tertiary),
83-
});
106+
protected getScheme(config: SchemeBuilderConfig): DynamicScheme {
107+
return new config.type(
108+
Hct.fromInt(argbFromHex(config.source)),
109+
config.mode === SchemeMode.Dark,
110+
config.contrast,
111+
);
84112
}
85113
}

0 commit comments

Comments
 (0)