Skip to content

Commit 29a6375

Browse files
author
Barthélémy Ledoux
authored
New: Accept styles config as a function (#1490)
* accept styles as a function * fix error * update typings * add test for function * remove console.log * fix typings * avoid using custom styles * update documentation * update customized example * add cooment in example * typo in documentation Co-Authored-By: Artem Sapegin <[email protected]> * force rebuild for testing
1 parent 00a3261 commit 29a6375

File tree

9 files changed

+118
-49
lines changed

9 files changed

+118
-49
lines changed

docs/Configuration.md

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -599,12 +599,29 @@ Folder for static HTML style guide generated with `styleguidist build` command.
599599

600600
#### `styles`
601601

602-
Type: `object`, optional
602+
Type: `Object` or `Function`, optional
603603

604604
Customize styles of any Styleguidist’s component.
605605

606606
See example in the [cookbook](Cookbook.md#how-to-change-styles-of-a-style-guide).
607607

608+
> **Note:** Using a function allows access to theme variables as seen in the example below. See available [theme variables](https://github.com/styleguidist/react-styleguidist/blob/master/src/client/styles/theme.ts). The returned object folows the same format as when configured as a litteral.
609+
610+
```javascript
611+
module.exports = {
612+
styles: function(theme) {
613+
return {
614+
Logo: {
615+
logo: {
616+
// we can now change the color used in the logo item to use the theme's `link` color
617+
color: theme.color.link
618+
}
619+
}
620+
}
621+
}
622+
}
623+
```
624+
608625
#### `template`
609626

610627
Type: `Object` or `Function`, optional.
@@ -690,22 +707,22 @@ Function that modifies code example (Markdown fenced code block). For example, y
690707

691708
```javascript
692709
module.exports = {
693-
updateExample(props, exampleFilePath) {
694-
const { settings, lang } = props
695-
if (typeof settings.file === 'string') {
696-
const filepath = path.resolve(
697-
path.dirname(exampleFilePath),
698-
settings.file
699-
)
700-
const { file, ...restSettings } = settings;
701-
return {
702-
content: fs.readFileSync(filepath, 'utf8'),
703-
settings: restSettings,
704-
lang,
705-
}
706-
}
707-
return props
708-
}
710+
updateExample(props, exampleFilePath) {
711+
const { settings, lang } = props
712+
if (typeof settings.file === 'string') {
713+
const filepath = path.resolve(
714+
path.dirname(exampleFilePath),
715+
settings.file
716+
)
717+
const { file, ...restSettings } = settings
718+
return {
719+
content: fs.readFileSync(filepath, 'utf8'),
720+
settings: restSettings,
721+
lang
722+
}
723+
}
724+
return props
725+
}
709726
}
710727
```
711728

docs/Cookbook.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,23 @@ module.exports = {
266266
267267
> **Note:** Use [React Developer Tools](https://github.com/facebook/react) to find component and style names. For example a component `<LogoRenderer><h1 className="rsg--logo-53">` corresponds to an example above.
268268
269+
> **Note:** Use a function instead of an object for [styles](Configuration.md#styles) to access all heme variables in your custom styles.
270+
271+
```javascript
272+
module.exports = {
273+
styles: function(theme) {
274+
return {
275+
Logo: {
276+
logo: {
277+
// we can now change the color used in the logo item to use the theme's `link` color
278+
color: theme.color.link
279+
}
280+
}
281+
}
282+
}
283+
}
284+
```
285+
269286
## How to change the layout of a style guide?
270287

271288
You can replace any Styleguidist React component. But in most of the cases you’ll want to replace `*Renderer` components — all HTML is rendered by these components. For example `ReactComponentRenderer`, `ComponentsListRenderer`, `PropsRenderer`, etc. — [check the source](https://github.com/styleguidist/react-styleguidist/tree/master/src/client/rsg-components) to see what components are available.

examples/customised/styleguide.config.js

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,24 @@ module.exports = {
1111
border: '#e0d2de',
1212
font: ['Helvetica', 'sans-serif'],
1313
},
14-
styles: {
15-
Playground: {
16-
preview: {
17-
paddingLeft: 0,
18-
paddingRight: 0,
19-
borderWidth: [[0, 0, 1, 0]],
20-
borderRadius: 0,
21-
},
22-
},
23-
Markdown: {
24-
pre: {
25-
border: 0,
26-
background: 'none',
14+
styles: function styles(theme) {
15+
return {
16+
Playground: {
17+
preview: {
18+
paddingLeft: 0,
19+
paddingRight: 0,
20+
borderWidth: [[0, 0, 1, 0]],
21+
borderRadius: 0,
22+
},
2723
},
28-
code: {
29-
fontSize: 14,
24+
Code: {
25+
code: {
26+
// make inline code example appear the same color as links
27+
color: theme.color.link,
28+
fontSize: 14,
29+
},
3030
},
31-
},
31+
};
3232
},
3333
getComponentPathLine(componentPath) {
3434
const name = path.basename(componentPath, '.js');

src/client/rsg-components/Styled/Styled.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export interface JssInjectedProps {
88
}
99

1010
export default function StyleHOC<P extends JssInjectedProps>(
11-
styles: Styles
11+
styles: (t: Rsg.Theme) => Styles<string>
1212
): (WrappedComponent: ComponentType<P>) => ComponentType<Omit<P, keyof JssInjectedProps>> {
1313
return (WrappedComponent: ComponentType<P>) => {
1414
const componentName = WrappedComponent.name.replace(/Renderer$/, '');

src/client/styles/__tests__/createStyleSheet.spec.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ const customThemeMaxWidth = 9999;
77

88
const customStyleBorderColor = '#ABCDEF';
99

10+
const customThemeLinkColor = '#CCCAAA';
11+
1012
const testComponentName = 'TestComponentName';
1113
const testRuleName = 'testRule';
1214

@@ -21,10 +23,12 @@ const styles = ({ color, borderRadius, maxWidth }: Rsg.Theme) => ({
2123
});
2224

2325
const config = {
26+
hello: 0,
2427
theme: {
2528
color: {
2629
base: customThemeColor,
2730
border: customThemeBorderColor,
31+
link: customThemeLinkColor,
2832
},
2933
maxWidth: customThemeMaxWidth,
3034
},
@@ -37,6 +41,20 @@ const config = {
3741
},
3842
};
3943

44+
const configWithStylesAsAFunction = {
45+
hello: 1,
46+
...config,
47+
styles: (locTheme: Rsg.Theme) => {
48+
return {
49+
[testComponentName]: {
50+
[testRuleName]: {
51+
borderColor: locTheme.color.link,
52+
},
53+
},
54+
};
55+
},
56+
};
57+
4058
describe('createStyleSheet', () => {
4159
it('should use theme variables', () => {
4260
const styleSheet = createStyleSheet(styles, config, testComponentName);
@@ -60,4 +78,15 @@ describe('createStyleSheet', () => {
6078

6179
expect(style['border-color']).toBe(customStyleBorderColor);
6280
});
81+
82+
it('should override config theme variables with config styles as a function', () => {
83+
// remove cache from memoize since we changed config
84+
if (createStyleSheet && createStyleSheet.cache && createStyleSheet.cache.clear) {
85+
createStyleSheet.cache.clear();
86+
}
87+
const styleSheet = createStyleSheet(styles, configWithStylesAsAFunction, testComponentName);
88+
const style = (styleSheet.getRule(testRuleName) as any).style;
89+
90+
expect(style['border-color']).toBe(customThemeLinkColor);
91+
});
6392
});
Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
11
import merge from 'lodash/merge';
22
import memoize from 'lodash/memoize';
3-
import { Styles } from 'jss';
3+
import { Styles, StyleSheet } from 'jss';
44
import jss from './setupjss';
55
import * as theme from './theme';
66

7-
export default memoize((styles, config: Rsg.StyleguidistConfig, componentName) => {
8-
const mergedTheme: Rsg.Theme = merge({}, theme, config.theme);
9-
const mergedStyles: Partial<Styles<string>> = merge(
10-
{},
11-
styles(mergedTheme),
12-
config.styles && config.styles[componentName]
13-
);
14-
return jss.createStyleSheet(mergedStyles, { meta: componentName, link: true });
15-
});
7+
export default memoize(
8+
(
9+
styles: (t: Rsg.Theme) => Styles<string>,
10+
config: Rsg.StyleguidistConfig,
11+
componentName: string
12+
): StyleSheet<string> => {
13+
const mergedTheme: Rsg.Theme = merge({}, theme, config.theme);
14+
const customStyles =
15+
typeof config.styles === 'function' ? config.styles(mergedTheme) : config.styles;
16+
const mergedStyles: Partial<Styles<string>> = merge(
17+
{},
18+
styles(mergedTheme),
19+
customStyles && customStyles[componentName]
20+
);
21+
return jss.createStyleSheet(mergedStyles, { meta: componentName, link: true });
22+
}
23+
);

src/scripts/schemas/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ const configSchema: Record<StyleguidistConfigKey, ConfigSchemaOptions<Rsg.Styleg
275275
default: 'styleguide',
276276
},
277277
styles: {
278-
type: 'object',
278+
type: ['object', 'function'],
279279
default: {},
280280
example: {
281281
Logo: {

src/typings/RsgStyles.d.ts

Lines changed: 0 additions & 3 deletions
This file was deleted.

src/typings/StyleguidistConfig.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { TransformOptions } from 'buble';
44
import { Handler, DocumentationObject, PropDescriptor } from 'react-docgen';
55
import { ASTNode } from 'ast-types';
66
import { NodePath } from 'ast-types/lib/node-path';
7+
import { Styles } from 'jss';
78

89
declare global {
910
namespace Rsg {
@@ -73,7 +74,7 @@ declare global {
7374
sortProps(props: PropDescriptor[]): PropDescriptor[];
7475
styleguideComponents: Record<string, string>;
7576
styleguideDir: string;
76-
styles: Styles;
77+
styles: Styles | ((theme: Theme) => Styles);
7778
template: any;
7879
theme: Theme;
7980
title: string;

0 commit comments

Comments
 (0)