Skip to content

Commit 9fe39a3

Browse files
Material Engcopybara-github
authored andcommitted
Add documentation for Contrast and DynamicScheme (constructor).
PiperOrigin-RevId: 564392645
1 parent 799b6ba commit 9fe39a3

File tree

3 files changed

+291
-0
lines changed

3 files changed

+291
-0
lines changed

contrast.md

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
# Contrast
2+
3+
4+
5+
## Overview
6+
7+
MCU uses **contrast ratio** to measure the contrast between colors and ensure
8+
legibility. The `contrast` part of the library contains a few helper functions
9+
related to contrast ratios.
10+
11+
Contrast ratio is based on `Y`, a component in the CIEXYZ color space that
12+
measures brightness. `Y` is in a one-to-one relationship with `L*` from CIELab.
13+
14+
Given two colors where the lighter color's `Y` is `yL` the darker color's `Y` is
15+
`yD`, the contrast ratio is defined as:
16+
17+
```
18+
contrast_ratio = (yL + 5.0) / (yD + 5.0)
19+
```
20+
21+
The contrast ratio between a color and itself is 1.0.
22+
23+
The contrast ratio between black and white is 21.0.
24+
25+
Generally, text is considered legible against a background when the two colors
26+
have a contrast ratio of at least 4.5.
27+
28+
## Usage
29+
30+
The contrast library allows manual control of contrast. However, we recommend
31+
using the `DynamicColor` and `DynamicScheme` features in production, which are
32+
able to generate color schemes that contrast well.
33+
34+
## Measuring contrast
35+
36+
To measure the contrast of two colors, use the `ratioOfTones` method on the
37+
tones (`L*`) of the two colors.
38+
39+
The tone of an HCT color is the `tone` component. The tone of an ARGB color can
40+
be obtained by `ColorUtils.lstarFromArgb` method.
41+
42+
<section>
43+
44+
###### Dart
45+
46+
```dart
47+
final contrastRatio = Contrast.ratioOfTones(hct1.tone, hct2.tone);
48+
```
49+
50+
```dart
51+
final tone1 = ColorUtils.lstarFromArgb(argb1);
52+
final tone2 = ColorUtils.lstarFromArgb(argb2);
53+
final contrastRatio = Contrast.ratioOfTones(tone1, tone2);
54+
```
55+
56+
###### Java
57+
58+
```java
59+
double contrastRatio = Contrast.ratioOfTones(hct1.getTone(), hct2.getTone());
60+
```
61+
62+
```java
63+
double tone1 = ColorUtils.lstarFromArgb(argb1);
64+
double tone2 = ColorUtils.lstarFromArgb(argb2);
65+
double contrastRatio = Contrast.ratioOfTones(tone1, tone2);
66+
```
67+
68+
###### TypeScript
69+
70+
```typescript
71+
const contrastRatio = Contrast.ratioOfTones(hct1.tone, hct2.tone);
72+
```
73+
74+
```typescript
75+
const tone1 = ColorUtils.lstarFromArgb(argb1);
76+
const tone2 = ColorUtils.lstarFromArgb(argb2);
77+
const contrastRatio = Contrast.ratioOfTones(tone1, tone2);
78+
```
79+
80+
###### C++
81+
82+
```cpp
83+
double contrast_ratio = RatioOfTones(hct1.get_tone(), hct2.get_tone());
84+
```
85+
86+
```cpp
87+
double tone1 = LstarFromArgb(argb1);
88+
double tone2 = LstarFromArgb(argb2);
89+
double contrast_ratio = RatioOfTones(tone1, tone2);
90+
```
91+
92+
###### Swift
93+
94+
```swift
95+
let contrastRatio = Contrast.ratioOfTones(hct1.tone, hct2.tone)
96+
```
97+
98+
```swift
99+
let tone1 = ColorUtils.lstarFromArgb(argb1)
100+
let tone2 = ColorUtils.lstarFromArgb(argb2)
101+
let contrastRatio = Contrast.ratioOfTones(tone1, tone2)
102+
```
103+
104+
</section>
105+
106+
## Obtaining well-contrasting colors
107+
108+
The functions `darker` and `lighter` (and their variants `darkerUnsafe` and
109+
`lighterUnsafe`) allow one to obtain **tones** that contrast well against the
110+
**tone** of a given color.
111+
112+
The functions `darker` and `lighter` will return `-1` if the required contrast
113+
cannot be reached, whereas `darkerUnsafe` and `lighterUnsafe` will return `0`
114+
(tone of black) and `100` (tone of white), respectively, making the contrast
115+
ratio as high as possible.
116+
117+
The word "unsafe" in the names mean they may return a color without guaranteeing
118+
contrast ratio. These functions do not cause actual damage.
119+
120+
<section>
121+
122+
###### Dart
123+
124+
```dart
125+
final original = ColorUtils.lstarFromArgb(0xFF00AA00); // 60.56
126+
127+
final darker = Contrast.darker(original, 3.0); // 29.63
128+
final lighter = Contrast.lighter(original, 3.0); // 98.93
129+
final darkerUnsafe = Contrast.darkerUnsafe(original, 3.0); // 29.63
130+
final lighterUnsafe = Contrast.lighterUnsafe(original, 3.0); // 98.93
131+
132+
final darker = Contrast.darker(original, 7.0); // -1.0
133+
final lighter = Contrast.lighter(original, 7.0); // -1.0
134+
final darkerUnsafe = Contrast.darkerUnsafe(original, 7.0); // 0.0
135+
final lighterUnsafe = Contrast.lighterUnsafe(original, 7.0); // 100.0
136+
```
137+
138+
###### Java
139+
140+
```java
141+
double original = ColorUtils.lstarFromArgb(0xFF00AA00); // 60.56
142+
143+
double darker = Contrast.darker(original, 3.0); // 29.63
144+
double lighter = Contrast.lighter(original, 3.0); // 98.93
145+
double darkerUnsafe = Contrast.darkerUnsafe(original, 3.0); // 29.63
146+
double lighterUnsafe = Contrast.lighterUnsafe(original, 3.0); // 98.93
147+
148+
double darker = Contrast.darker(original, 7.0); // -1.0
149+
double lighter = Contrast.lighter(original, 7.0); // -1.0
150+
double darkerUnsafe = Contrast.darkerUnsafe(original, 7.0); // 0.0
151+
double lighterUnsafe = Contrast.lighterUnsafe(original, 7.0); // 100.0
152+
```
153+
154+
###### TypeScript
155+
156+
```typescript
157+
const original = ColorUtils.lstarFromArgb(0xFF00AA00); // 60.56
158+
159+
const darker = Contrast.darker(original, 3.0); // 29.63
160+
const lighter = Contrast.lighter(original, 3.0); // 98.93
161+
const darkerUnsafe = Contrast.darkerUnsafe(original, 3.0); // 29.63
162+
const lighterUnsafe = Contrast.lighterUnsafe(original, 3.0); // 98.93
163+
164+
const darker = Contrast.darker(original, 7.0); // -1.0
165+
const lighter = Contrast.lighter(original, 7.0); // -1.0
166+
const darkerUnsafe = Contrast.darkerUnsafe(original, 7.0); // 0.0
167+
const lighterUnsafe = Contrast.lighterUnsafe(original, 7.0); // 100.0
168+
```
169+
170+
###### C++
171+
172+
```cpp
173+
double original = LstarFromArgb(0xFF00AA00); // 60.56
174+
175+
double darker = Darker(original, 3.0); // 29.63
176+
double lighter = Lighter(original, 3.0); // 98.93
177+
double darker_unsafe = DarkerUnsafe(original, 3.0); // 29.63
178+
double lighter_unsafe = LighterUnsafe(original, 3.0); // 98.93
179+
180+
double darker = Darker(original, 7.0); // -1.0
181+
double lighter = Lighter(original, 7.0); // -1.0
182+
double darker_unsafe = DarkerUnsafe(original, 7.0); // 0.0
183+
double lighter_unsafe = LighterUnsafe(original, 7.0); // 100.0
184+
```
185+
186+
###### Swift
187+
188+
```swift
189+
let original = ColorUtils.lstarFromArgb(0xFF00AA00) // 60.56
190+
191+
let darker = Contrast.darker(tone: original, ratio: 3.0) // 29.63
192+
let lighter = Contrast.lighter(tone: original, ratio: 3.0) // 98.93
193+
let darkerUnsafe = Contrast.darkerUnsafe(tone: original, ratio: 3.0) // 29.63
194+
let lighterUnsafe = Contrast.lighterUnsafe(tone: original, ratio: 3.0) // 98.93
195+
196+
let darker = Contrast.darker(tone: original, ratio: 7.0) // -1.0
197+
let lighter = Contrast.lighter(tone: original, ratio: 7.0) // -1.0
198+
let darkerUnsafe = Contrast.darkerUnsafe(tone: original, ratio: 7.0) // 0.0
199+
let lighterUnsafe = Contrast.lighterUnsafe(tone: original, ratio: 7.0) // 100.0
200+
```
201+
202+
</section>

make_schemes.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,91 @@ Currently the following variants are available:
101101

102102
### Method 2 — Specifying palettes
103103

104+
You can also create a `DynamicScheme` object by specifying each individual
105+
palette and providing additional information (source color, variant, light or
106+
dark mode, contrast).
107+
108+
<section>
109+
110+
###### Dart
111+
112+
```dart
113+
final scheme = DynamicScheme(
114+
sourceColorArgb: 0xFFEB0057,
115+
variant: Variant.vibrant,
116+
isDark: false,
117+
contrastLevel: 0.0,
118+
primaryPalette: TonalPalette.fromHct(Hct.fromInt(0xFFEB0057)),
119+
secondaryPalette: TonalPalette.fromHct(Hct.fromInt(0xFFF46B00)),
120+
tertiaryPalette: TonalPalette.fromHct(Hct.fromInt(0xFF00AB46)),
121+
neutralPalette: TonalPalette.fromHct(Hct.fromInt(0xFF949494)),
122+
neutralVariantPalette: TonalPalette.fromHct(Hct.fromInt(0xFFBC8877)),
123+
);
124+
```
125+
126+
###### Java
127+
128+
```java
129+
DynamicScheme scheme = new DynamicScheme(
130+
/*sourceColorHct=*/ Hct.fromInt(0xFFEB0057),
131+
/*variant=*/ Variant.VIBRANT,
132+
/*isDark=*/ false,
133+
/*contrastLevel=*/ 0.0,
134+
/*primaryPalette=*/ TonalPalette.fromInt(0xFFEB0057),
135+
/*secondaryPalette=*/ TonalPalette.fromInt(0xFFF46B00),
136+
/*tertiaryPalette=*/ TonalPalette.fromInt(0xFF00AB46),
137+
/*neutralPalette=*/ TonalPalette.fromInt(0xFF949494),
138+
/*neutralVariantPalette=*/ TonalPalette.fromInt(0xFFBC8877));
139+
```
140+
141+
###### TypeScript
142+
143+
```typescript
144+
const scheme = new DynamicScheme({
145+
sourceColorArgb: 0xFFEB0057,
146+
variant: Variant.VIBRANT,
147+
isDark: false,
148+
contrastLevel: 0.0,
149+
primaryPalette: TonalPalette.fromInt(0xFFEB0057),
150+
secondaryPalette: TonalPalette.fromInt(0xFFF46B00),
151+
tertiaryPalette: TonalPalette.fromInt(0xFF00AB46),
152+
neutralPalette: TonalPalette.fromInt(0xFF949494),
153+
neutralVariantPalette: TonalPalette.fromInt(0xFFBC8877)
154+
});
155+
```
156+
157+
###### C++
158+
159+
```cpp
160+
DynamicScheme scheme = DynamicScheme(
161+
/*source_color_argb=*/ 0xFFEB0057,
162+
/*variant=*/ Variant::kVibrant,
163+
/*contrast_level=*/ 0.0,
164+
/*is_dark=*/ false,
165+
/*primary_palette=*/ TonalPalette(0xFFEB0057),
166+
/*secondary_palette=*/ TonalPalette(0xFFF46B00),
167+
/*tertiary_palette=*/ TonalPalette(0xFF00AB46),
168+
/*neutral_palette=*/ TonalPalette(0xFF949494),
169+
/*neutral_variant_palette=*/ TonalPalette(0xFFBC8877));
170+
```
171+
172+
###### Swift
173+
174+
```swift
175+
let scheme = DynamicScheme(
176+
sourceColorArgb: 0xFFEB0057,
177+
variant: Variant.vibrant,
178+
isDark: false,
179+
contrastLevel: 0.0,
180+
primaryPalette: TonalPalette.fromHct(Hct(0xFFEB0057)),
181+
secondaryPalette: TonalPalette.fromHct(Hct(0xFFF46B00)),
182+
tertiaryPalette: TonalPalette.fromHct(Hct(0xFF00AB46)),
183+
neutralPalette: TonalPalette.fromHct(Hct(0xFF949494)),
184+
neutralVariantPalette: TonalPalette.fromHct(Hct(0xFFBC8877)))
185+
```
186+
187+
</section>
188+
104189
## Step 2 — Obtaining colors
105190

106191
To obtain a color from a dynamic scheme, use a `DynamicColor` object on a

sitemap.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,7 @@ Sitemap
66

77
- [Extract colors from an image](extract_colors.md)
88
- [Make and use schemes](make_schemes.md)
9+
10+
* Finer controls
11+
12+
- [Contrast](contrast.md)

0 commit comments

Comments
 (0)