Skip to content

Commit

Permalink
feat(theming): add componentStyles utility (#1986)
Browse files Browse the repository at this point in the history
Co-authored-by: Florent Mathieu <[email protected]>
  • Loading branch information
jzempel and ze-flo authored Dec 12, 2024
1 parent 4e43911 commit a868259
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 8 deletions.
7 changes: 3 additions & 4 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ ensuring the details live up to expectations.
for an ideal example):
- "Base" properties: display, position, flex, transition, direction, etc
(anything NOT related to size or color)
- `${sizeStyles(props)}`: a function that contains all properties related
- `${sizeStyles}`: a function that contains all properties related
to component sizing (usually based on calculated relationships), i.e.
margin, padding, width, height, line-height, font-size – all grouped
ordering (including pseudos, children, etc) applies within the
Expand All @@ -52,7 +52,7 @@ ensuring the details live up to expectations.
- `:hover`
- `:focus`
- `:active`
- `${colorStyles(props)}`: a function that contains all properties related
- `${colorStyles}`: a function that contains all properties related
to component color, i.e. border-color, background-color, color, box-shadow
– including any color modifications based on pseudo-class states, in the
order shown above – all grouped ordering (including psuedos, children,
Expand All @@ -63,8 +63,7 @@ ensuring the details live up to expectations.
property groupings – note that children styled components should contain
all their CSS properties, when possible
- The last declaration in any view component is
`${retrieveComponentStyles(COMPONENT_ID, props)}` which allows an
implementer to leverage the
`${componentStyles}` which allows an implementer to leverage the
[`theme`](https://zendeskgarden.github.io/react-components/theming/)
"components" object to override specific component styles.
- The view component `defaultProps` must contain `theme: DEFAULT_THEME` for
Expand Down
1 change: 1 addition & 0 deletions packages/theming/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export { ThemeProvider } from './elements/ThemeProvider';
export { default as DEFAULT_THEME } from './elements/theme';
export { default as PALETTE } from './elements/palette';
export { default as retrieveComponentStyles } from './utils/retrieveComponentStyles';
export { componentStyles } from './utils/componentStyles';
export { getArrowPosition } from './utils/getArrowPosition';
export { getCheckeredBackground } from './utils/getCheckeredBackground';
export { getColor } from './utils/getColor';
Expand Down
42 changes: 42 additions & 0 deletions packages/theming/src/utils/componentStyles.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* Copyright Zendesk, Inc.
*
* Use of this source code is governed under the Apache License, Version 2.0
* found at http://www.apache.org/licenses/LICENSE-2.0.
*/

import { componentStyles } from './componentStyles';

describe('componentStyles', () => {
const VALUE = 'content: "test";';

it('returns component styles from the theme as expected', () => {
const props = { 'data-garden-id': 'test', theme: { components: { test: VALUE } } } as any;
const result = componentStyles(props);

expect(result).toBe(VALUE);
});

it('returns undefined if no component styles are found', () => {
const props = { 'data-garden-id': 'test', theme: {} } as any;
const result = componentStyles(props);

expect(result).toBeUndefined();
});

it('handles component styles provided as a function', () => {
const fn = jest.fn().mockReturnValue(VALUE);
const props = { 'data-garden-id': 'test', theme: { components: { test: fn } } } as any;
const result = componentStyles(props);

expect(result).toBe(VALUE);
});

it('accepts a custom component ID', () => {
const componentId = 'custom';
const props = { theme: { components: { [componentId]: VALUE } } } as any;
const result = componentStyles({ ...props, componentId });

expect(result).toBe(VALUE);
});
});
35 changes: 35 additions & 0 deletions packages/theming/src/utils/componentStyles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Copyright Zendesk, Inc.
*
* Use of this source code is governed under the Apache License, Version 2.0
* found at http://www.apache.org/licenses/LICENSE-2.0.
*/

import { DataAttributes, DefaultTheme } from 'styled-components';

/**
* CSS for component customizations based on `theme.components[componentId]`.
*
* @param {Object} props.theme Provides `components` object use to resolve the given component ID
* @param {String} [props.componentId] Specifies the lookup id for * `theme.components` styles.
* The ID will be inferred from the `'data-garden-id'` attribute if not provided.
*
* @returns component CSS styles
*/
export const componentStyles = (props: { theme: DefaultTheme; componentId?: string }) => {
let retVal: string | undefined;
const components = props.theme.components;
const componentId = props.componentId || (props as unknown as DataAttributes)['data-garden-id'];

if (components && componentId) {
retVal = components[componentId];

if (typeof retVal === 'function') {
const fn = retVal as (p: { theme: DefaultTheme } & unknown) => string;

retVal = fn(props);
}
}

return retVal;
};
8 changes: 4 additions & 4 deletions packages/theming/src/utils/retrieveComponentStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
* found at http://www.apache.org/licenses/LICENSE-2.0.
*/

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

/** @component */
/** @deprecated Use `componentStyles` instead. */
export default function retrieveComponentStyles(
componentId: string,
props: Partial<ThemeProps<Partial<DefaultTheme>>>
props: { theme?: Partial<DefaultTheme> }
) {
const components = props.theme && props.theme.components;
const components = props.theme?.components;

if (!components) {
return undefined;
Expand Down

0 comments on commit a868259

Please sign in to comment.