Skip to content

Commit 876f25e

Browse files
authored
feat(theming): add system opacity values to the theme (#1797)
1 parent 55eefa6 commit 876f25e

File tree

8 files changed

+68
-5
lines changed

8 files changed

+68
-5
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
- [ ] :ok_hand: design updates will be Garden Designer approved (add the designer as a reviewer)
2626
- [ ] :globe_with_meridians: demo is up-to-date (`npm start`)
2727
- [ ] :arrow_left: renders as expected with reversed (RTL) direction
28+
- [ ] :black_circle: renders as expected in dark mode
2829
- [ ] :metal: renders as expected with Bedrock CSS (`?bedrock`)
2930
- [ ] :guardsman: includes new unit tests. Maintain existing coverage (always >= 96%)
3031
- [ ] :wheelchair: tested for WCAG 2.1 AA accessibility compliance

packages/theming/demo/stories/GetColorStory.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ const Color = ({ dark, hue, light, offset, shade, theme, transparency, variable
4242
offset,
4343
shade,
4444
theme,
45-
transparency: transparency ? transparency / 100 : undefined,
45+
transparency,
4646
variable
4747
});
4848

@@ -71,6 +71,7 @@ const Color = ({ dark, hue, light, offset, shade, theme, transparency, variable
7171
interface IArgs extends Omit<IColorProps, 'theme'> {
7272
theme: {
7373
colors: Omit<IGardenTheme['colors'], 'base'>;
74+
opacity: IGardenTheme['opacity'];
7475
palette: IGardenTheme['palette'];
7576
};
7677
}
@@ -89,6 +90,7 @@ export const GetColorStory: StoryFn<IArgs> = ({
8990
const theme = {
9091
...parentTheme,
9192
colors: { ..._theme.colors, base: parentTheme.colors.base },
93+
opacity: _theme.opacity,
9294
palette: _theme.palette
9395
};
9496

packages/theming/demo/utilities.stories.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ import README from '../README.md';
7777
light: { control: { type: 'object' } },
7878
offset: { control: { type: 'number' } },
7979
shade: { control: { type: 'number' } },
80-
transparency: { control: { type: 'range', min: 1 } },
80+
transparency: { control: { type: 'range', min: 100, max: 1200, step: 100 } },
8181
variable: { control: { type: 'text' } }
8282
}}
8383
>

packages/theming/src/elements/theme/__snapshots__/index.spec.ts.snap

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,20 @@ exports[`DEFAULT_THEME matches snapshot 1`] = `
155155
"xxl": "32px",
156156
"xxxl": "44px",
157157
},
158+
"opacity": {
159+
"100": 0.08,
160+
"1000": 0.8,
161+
"1100": 0.88,
162+
"1200": 0.96,
163+
"200": 0.16,
164+
"300": 0.24,
165+
"400": 0.32,
166+
"500": 0.4,
167+
"600": 0.48,
168+
"700": 0.56,
169+
"800": 0.64,
170+
"900": 0.72,
171+
},
158172
"palette": {
159173
"azure": {
160174
"100": "#eff7fe",

packages/theming/src/elements/theme/index.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,21 @@ const lineHeights = {
191191
xxxl: `${BASE * 11}px`
192192
};
193193

194+
const opacity = {
195+
100: 0.08,
196+
200: 0.16,
197+
300: 0.24,
198+
400: 0.32,
199+
500: 0.4,
200+
600: 0.48,
201+
700: 0.56,
202+
800: 0.64,
203+
900: 0.72,
204+
1000: 0.8,
205+
1100: 0.88,
206+
1200: 0.96
207+
};
208+
194209
const palette = { ...PALETTE };
195210

196211
/* Exclude product palette from the theme */
@@ -237,6 +252,7 @@ const DEFAULT_THEME: IGardenTheme = {
237252
fontWeights,
238253
iconSizes,
239254
lineHeights,
255+
opacity,
240256
palette,
241257
rtl: false,
242258
shadowWidths,

packages/theming/src/types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ export interface IGardenTheme {
177177
xxl: string;
178178
xxxl: string;
179179
};
180+
opacity: Record<number, number>;
180181
palette: Record<string, Hue>;
181182
shadowWidths: {
182183
xs: string;

packages/theming/src/utils/getColor.spec.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,15 @@ describe('getColor', () => {
197197
expect(color).toBe(expected);
198198
});
199199

200+
it('applies transparency via theme `opacity` as expected', () => {
201+
const hue = 'blue';
202+
const transparency = 1000;
203+
const color = getColor({ theme: DEFAULT_THEME, hue, transparency });
204+
const expected = rgba(PALETTE[hue][700], DEFAULT_THEME.opacity[1000]);
205+
206+
expect(color).toBe(expected);
207+
});
208+
200209
it('applies mode transparency as expected', () => {
201210
const hue = 'blue';
202211
const transparency = 0.5;
@@ -345,5 +354,13 @@ describe('getColor', () => {
345354
it('throws an error if shade is invalid', () => {
346355
expect(() => getColor({ theme: DEFAULT_THEME, hue: 'blue', shade: NaN })).toThrow(TypeError);
347356
});
357+
358+
it('throws an error if transparency is invalid', () => {
359+
const invalid = DEFAULT_THEME.opacity[100] + 1;
360+
361+
expect(() => getColor({ theme: DEFAULT_THEME, hue: 'blue', transparency: invalid })).toThrow(
362+
Error
363+
);
364+
});
348365
});
349366
});

packages/theming/src/utils/getColor.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ const toHex = (
7171
const toColor = (
7272
colors: Omit<IGardenTheme['colors'], 'base' | 'variables'>,
7373
palette: IGardenTheme['palette'],
74+
opacity: IGardenTheme['opacity'],
7475
scheme: 'dark' | 'light',
7576
hue: string,
7677
shade?: number | string,
@@ -109,7 +110,13 @@ const toColor = (
109110
}
110111

111112
if (retVal && transparency) {
112-
retVal = rgba(retVal, transparency);
113+
const alpha = transparency > 1 ? opacity[transparency] : transparency;
114+
115+
if (alpha === undefined) {
116+
throw new Error('Error: invalid `transparency` parameter');
117+
}
118+
119+
retVal = rgba(retVal, alpha);
113120
}
114121

115122
return retVal;
@@ -147,7 +154,7 @@ const toProperty = (object: object, path: string) => {
147154
* - `'chromeHue'` = `theme.colors.chromeHue`
148155
* @param {number} [options.shade] A hue shade
149156
* @param {number} [options.offset] A positive or negative value to adjust the shade
150-
* @param {number} [options.transparency] An alpha-channel value between 0 and 1
157+
* @param {number} [options.transparency] A `theme.opacity` key or an alpha-channel value between 0 and 1
151158
*/
152159
export const getColor = memoize(
153160
({ dark, hue, light, offset, shade, theme, transparency, variable }: ColorParameters) => {
@@ -184,7 +191,12 @@ export const getColor = memoize(
184191
}
185192

186193
if (_hue) {
187-
retVal = toColor(colors, palette, scheme, _hue, _shade, _offset, _transparency);
194+
const opacity =
195+
theme.opacity && Object.keys(theme.opacity).length > 0
196+
? theme.opacity
197+
: DEFAULT_THEME.opacity;
198+
199+
retVal = toColor(colors, palette, opacity, scheme, _hue, _shade, _offset, _transparency);
188200
}
189201

190202
if (retVal === undefined) {

0 commit comments

Comments
 (0)