Skip to content

Commit a868259

Browse files
jzempelze-flo
andauthored
feat(theming): add componentStyles utility (#1986)
Co-authored-by: Florent Mathieu <[email protected]>
1 parent 4e43911 commit a868259

File tree

5 files changed

+85
-8
lines changed

5 files changed

+85
-8
lines changed

docs/api.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ ensuring the details live up to expectations.
4343
for an ideal example):
4444
- "Base" properties: display, position, flex, transition, direction, etc
4545
(anything NOT related to size or color)
46-
- `${sizeStyles(props)}`: a function that contains all properties related
46+
- `${sizeStyles}`: a function that contains all properties related
4747
to component sizing (usually based on calculated relationships), i.e.
4848
margin, padding, width, height, line-height, font-size – all grouped
4949
ordering (including pseudos, children, etc) applies within the
@@ -52,7 +52,7 @@ ensuring the details live up to expectations.
5252
- `:hover`
5353
- `:focus`
5454
- `:active`
55-
- `${colorStyles(props)}`: a function that contains all properties related
55+
- `${colorStyles}`: a function that contains all properties related
5656
to component color, i.e. border-color, background-color, color, box-shadow
5757
– including any color modifications based on pseudo-class states, in the
5858
order shown above – all grouped ordering (including psuedos, children,
@@ -63,8 +63,7 @@ ensuring the details live up to expectations.
6363
property groupings – note that children styled components should contain
6464
all their CSS properties, when possible
6565
- The last declaration in any view component is
66-
`${retrieveComponentStyles(COMPONENT_ID, props)}` which allows an
67-
implementer to leverage the
66+
`${componentStyles}` which allows an implementer to leverage the
6867
[`theme`](https://zendeskgarden.github.io/react-components/theming/)
6968
"components" object to override specific component styles.
7069
- The view component `defaultProps` must contain `theme: DEFAULT_THEME` for

packages/theming/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export { ThemeProvider } from './elements/ThemeProvider';
99
export { default as DEFAULT_THEME } from './elements/theme';
1010
export { default as PALETTE } from './elements/palette';
1111
export { default as retrieveComponentStyles } from './utils/retrieveComponentStyles';
12+
export { componentStyles } from './utils/componentStyles';
1213
export { getArrowPosition } from './utils/getArrowPosition';
1314
export { getCheckeredBackground } from './utils/getCheckeredBackground';
1415
export { getColor } from './utils/getColor';
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* Copyright Zendesk, Inc.
3+
*
4+
* Use of this source code is governed under the Apache License, Version 2.0
5+
* found at http://www.apache.org/licenses/LICENSE-2.0.
6+
*/
7+
8+
import { componentStyles } from './componentStyles';
9+
10+
describe('componentStyles', () => {
11+
const VALUE = 'content: "test";';
12+
13+
it('returns component styles from the theme as expected', () => {
14+
const props = { 'data-garden-id': 'test', theme: { components: { test: VALUE } } } as any;
15+
const result = componentStyles(props);
16+
17+
expect(result).toBe(VALUE);
18+
});
19+
20+
it('returns undefined if no component styles are found', () => {
21+
const props = { 'data-garden-id': 'test', theme: {} } as any;
22+
const result = componentStyles(props);
23+
24+
expect(result).toBeUndefined();
25+
});
26+
27+
it('handles component styles provided as a function', () => {
28+
const fn = jest.fn().mockReturnValue(VALUE);
29+
const props = { 'data-garden-id': 'test', theme: { components: { test: fn } } } as any;
30+
const result = componentStyles(props);
31+
32+
expect(result).toBe(VALUE);
33+
});
34+
35+
it('accepts a custom component ID', () => {
36+
const componentId = 'custom';
37+
const props = { theme: { components: { [componentId]: VALUE } } } as any;
38+
const result = componentStyles({ ...props, componentId });
39+
40+
expect(result).toBe(VALUE);
41+
});
42+
});
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* Copyright Zendesk, Inc.
3+
*
4+
* Use of this source code is governed under the Apache License, Version 2.0
5+
* found at http://www.apache.org/licenses/LICENSE-2.0.
6+
*/
7+
8+
import { DataAttributes, DefaultTheme } from 'styled-components';
9+
10+
/**
11+
* CSS for component customizations based on `theme.components[componentId]`.
12+
*
13+
* @param {Object} props.theme Provides `components` object use to resolve the given component ID
14+
* @param {String} [props.componentId] Specifies the lookup id for * `theme.components` styles.
15+
* The ID will be inferred from the `'data-garden-id'` attribute if not provided.
16+
*
17+
* @returns component CSS styles
18+
*/
19+
export const componentStyles = (props: { theme: DefaultTheme; componentId?: string }) => {
20+
let retVal: string | undefined;
21+
const components = props.theme.components;
22+
const componentId = props.componentId || (props as unknown as DataAttributes)['data-garden-id'];
23+
24+
if (components && componentId) {
25+
retVal = components[componentId];
26+
27+
if (typeof retVal === 'function') {
28+
const fn = retVal as (p: { theme: DefaultTheme } & unknown) => string;
29+
30+
retVal = fn(props);
31+
}
32+
}
33+
34+
return retVal;
35+
};

packages/theming/src/utils/retrieveComponentStyles.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
* found at http://www.apache.org/licenses/LICENSE-2.0.
66
*/
77

8-
import { ThemeProps, DefaultTheme } from 'styled-components';
8+
import { DefaultTheme } from 'styled-components';
99

10-
/** @component */
10+
/** @deprecated Use `componentStyles` instead. */
1111
export default function retrieveComponentStyles(
1212
componentId: string,
13-
props: Partial<ThemeProps<Partial<DefaultTheme>>>
13+
props: { theme?: Partial<DefaultTheme> }
1414
) {
15-
const components = props.theme && props.theme.components;
15+
const components = props.theme?.components;
1616

1717
if (!components) {
1818
return undefined;

0 commit comments

Comments
 (0)