Skip to content

Commit 5e108e5

Browse files
authored
feat(text): allow to pass intl message instead of children (#651)
1 parent 425e82d commit 5e108e5

File tree

4 files changed

+162
-44
lines changed

4 files changed

+162
-44
lines changed

src/components/typography/text/README.md

+37-25
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,15 @@ Wraps the given text in the given HTML header `size`.
2020

2121
#### Properties
2222

23-
| Props | Type | Required | Values | Default | Description |
24-
| ------------- | ---------------- | :------: | -------------------- | ------- | -------------------------------------------------------------- |
25-
| `elementType` | `String` || `['h1', 'h2', 'h3']` | - | - |
26-
| `children` | `PropTypes.node` || - | - | - |
27-
| `title` | `String` | - | - | - | Text to show in a tooltip on hover over the element |
28-
| `truncate` | `Bool` | - | - | `false` | Option for truncate content in case the screen has small width |
23+
| Props | Type | Required | Values | Default | Description |
24+
| ------------- | ---------------- | :------: | -------------------- | ------- | -------------------------------------------------------------------- |
25+
| `elementType` | `String` || `['h1', 'h2', 'h3']` | - | - |
26+
| `children` | `PropTypes.node` | ✅ (\*) | - | - | - |
27+
| `intlMessage` | `intl message` | ✅ (\*) | - | - | An intl message object that will be rendered with `FormattedMessage` |
28+
| `title` | `String` | - | - | - | Text to show in a tooltip on hover over the element |
29+
| `truncate` | `Bool` | - | - | `false` | Option for truncate content in case the screen has small width |
30+
31+
> `*`: `children` is required only if `intlMessage` is not provided
2932
3033
The component further forwards all `data-` attributes to the underlying component.
3134

@@ -50,10 +53,13 @@ Wraps the given text in the given HTML header `size`.
5053
| `elementType` | `String` || `['h4', 'h5']` | - |
5154
| `isBold` | `Boolean` | - | - | `false` |
5255
| `tone` | `String` | - | `['primary', 'secondary', 'information', 'positive', 'negative']` | - |
53-
| `children` | `PropTypes.node` || - | - |
56+
| `children` | `PropTypes.node` | ✅ (\*) | - | - |
57+
| `intlMessage` | `intl message` | ✅ (\*) | - | - | An intl message object that will be rendered with `FormattedMessage` |
5458
| `title` | `String` | - | - | - |
5559
| `truncate` | `Bool` | - | - | `false` |
5660

61+
> `*`: `children` is required only if `intlMessage` is not provided
62+
5763
The component further forwards all `data-` attributes to the underlying component.
5864

5965
#### Where to use
@@ -86,15 +92,18 @@ Wraps the given text in a `<p>` element, for normal content.
8692

8793
#### Properties
8894

89-
| Props | Type | Required | Values | Default |
90-
| ---------- | ---------------- | :------: | ----------------------------------------------------------------------------- | ------- |
91-
| `isBold` | `Boolean` | - | - | `false` |
92-
| `isItalic` | `Boolean` | - | - | `false` |
93-
| `tone` | `String` | - | `['primary', 'secondary', 'information', 'positive', 'negative', 'inverted']` | - |
94-
| `children` | `PropTypes.node` || - | - |
95-
| `title` | `String` | - | - | - |
96-
| `truncate` | `Bool` | - | - | `false` |
97-
| `isInline` | `Bool` | - | - | `false` |
95+
| Props | Type | Required | Values | Default |
96+
| ------------- | ---------------- | :------: | ----------------------------------------------------------------------------- | ------- |
97+
| `isBold` | `Boolean` | - | - | `false` |
98+
| `isItalic` | `Boolean` | - | - | `false` |
99+
| `tone` | `String` | - | `['primary', 'secondary', 'information', 'positive', 'negative', 'inverted']` | - |
100+
| `children` | `PropTypes.node` | ✅ (\*) | - | - |
101+
| `intlMessage` | `intl message` | ✅ (\*) | - | - | An intl message object that will be rendered with `FormattedMessage` |
102+
| `title` | `String` | - | - | - |
103+
| `truncate` | `Bool` | - | - | `false` |
104+
| `isInline` | `Bool` | - | - | `false` |
105+
106+
> `*`: `children` is required only if `intlMessage` is not provided
98107
99108
The component further forwards all `data-` attributes to the underlying component.
100109

@@ -116,15 +125,18 @@ properly style the text.
116125

117126
#### Properties
118127

119-
| Props | Type | Required | Values | Default |
120-
| ---------- | ---------------- | :------: | ----------------------------------------------------------------------------- | ------- |
121-
| `isBold` | `Boolean` | - | - | `false` |
122-
| `isItalic` | `Boolean` | - | - | `false` |
123-
| `tone` | `String` | - | `['primary', 'secondary', 'information', 'positive', 'negative', 'warning'']` | - |
124-
| `children` | `PropTypes.node` || - | - |
125-
| `title` | `String` | - | - | - |
126-
| `truncate` | `Bool` | - | - | `false` |
127-
| `isInline` | `Bool` | - | - | `false` |
128+
| Props | Type | Required | Values | Default |
129+
| ------------- | ---------------- | :------: | ----------------------------------------------------------------------------- | ------- |
130+
| `isBold` | `Boolean` | - | - | `false` |
131+
| `isItalic` | `Boolean` | - | - | `false` |
132+
| `tone` | `String` | - | `['primary', 'secondary', 'information', 'positive', 'negative', 'warning'']` | - |
133+
| `children` | `PropTypes.node` | ✅ (\*) | - | - |
134+
| `intlMessage` | `intl message` | ✅ (\*) | - | - | An intl message object that will be rendered with `FormattedMessage` |
135+
| `title` | `String` | - | - | - |
136+
| `truncate` | `Bool` | - | - | `false` |
137+
| `isInline` | `Bool` | - | - | `false` |
138+
139+
> `*`: `children` is required only if `intlMessage` is not provided
128140
129141
The component further forwards all `data-` attributes to the underlying component.
130142

src/components/typography/text/text.js

+48-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import React from 'react';
22
import PropTypes from 'prop-types';
3+
import { FormattedMessage } from 'react-intl';
4+
import requiredIf from 'react-required-if';
35
import filterDataAttributes from '../../../utils/filter-data-attributes';
46
import {
57
bodyStyles,
@@ -9,6 +11,12 @@ import {
911
wrapStyles,
1012
} from './text.styles';
1113

14+
const intlMessageShape = PropTypes.shape({
15+
id: PropTypes.string.isRequired,
16+
description: PropTypes.string,
17+
defaultMessage: PropTypes.string.isRequired,
18+
});
19+
1220
const nonEmptyString = (props, propName, componentName) => {
1321
const value = props[propName];
1422
if (typeof value === 'string' && !value)
@@ -26,17 +34,22 @@ const Headline = props => {
2634
title={props.title}
2735
{...filterDataAttributes(props)}
2836
>
29-
{props.children}
37+
{props.intlMessage ? (
38+
<FormattedMessage {...props.intlMessage} />
39+
) : (
40+
props.children
41+
)}
3042
</HeadlineElement>
3143
);
3244
};
3345

3446
Headline.displayName = 'TextHeadline';
3547
Headline.propTypes = {
3648
elementType: PropTypes.oneOf(['h1', 'h2', 'h3']).isRequired,
37-
children: PropTypes.node.isRequired,
3849
title: nonEmptyString,
3950
truncate: PropTypes.bool,
51+
intlMessage: requiredIf(intlMessageShape, props => !props.children),
52+
children: requiredIf(PropTypes.node, props => !props.intlMessage),
4053
};
4154

4255
const Subheadline = props => {
@@ -47,7 +60,11 @@ const Subheadline = props => {
4760
css={subheadlineStyles(props)}
4861
{...filterDataAttributes(props)}
4962
>
50-
{props.children}
63+
{props.intlMessage ? (
64+
<FormattedMessage {...props.intlMessage} />
65+
) : (
66+
props.children
67+
)}
5168
</SubheadlineElement>
5269
);
5370
};
@@ -63,21 +80,27 @@ Subheadline.propTypes = {
6380
'positive',
6481
'negative',
6582
]),
66-
children: PropTypes.node.isRequired,
6783
title: nonEmptyString,
6884
truncate: PropTypes.bool,
85+
intlMessage: requiredIf(intlMessageShape, props => !props.children),
86+
children: requiredIf(PropTypes.node, props => !props.intlMessage),
6987
};
7088

7189
const Wrap = props => (
7290
<div css={wrapStyles()} title={props.title} {...filterDataAttributes(props)}>
73-
{props.children}
91+
{props.intlMessage ? (
92+
<FormattedMessage {...props.intlMessage} />
93+
) : (
94+
props.children
95+
)}
7496
</div>
7597
);
7698

7799
Wrap.displayName = 'TextWrap';
78100
Wrap.propTypes = {
79-
children: PropTypes.node.isRequired,
80101
title: nonEmptyString,
102+
intlMessage: requiredIf(intlMessageShape, props => !props.children),
103+
children: requiredIf(PropTypes.node, props => !props.intlMessage),
81104
};
82105

83106
const Body = props =>
@@ -87,15 +110,23 @@ const Body = props =>
87110
title={props.title}
88111
{...filterDataAttributes(props)}
89112
>
90-
{props.children}
113+
{props.intlMessage ? (
114+
<FormattedMessage {...props.intlMessage} />
115+
) : (
116+
props.children
117+
)}
91118
</span>
92119
) : (
93120
<p
94121
css={bodyStyles(props)}
95122
title={props.title}
96123
{...filterDataAttributes(props)}
97124
>
98-
{props.children}
125+
{props.intlMessage ? (
126+
<FormattedMessage {...props.intlMessage} />
127+
) : (
128+
props.children
129+
)}
99130
</p>
100131
);
101132

@@ -112,9 +143,10 @@ Body.propTypes = {
112143
'negative',
113144
'inverted',
114145
]),
115-
children: PropTypes.node.isRequired,
116146
title: nonEmptyString,
117147
truncate: PropTypes.bool,
148+
intlMessage: requiredIf(intlMessageShape, props => !props.children),
149+
children: requiredIf(PropTypes.node, props => !props.intlMessage),
118150
};
119151

120152
const Detail = props => (
@@ -124,7 +156,11 @@ const Detail = props => (
124156
{...filterDataAttributes(props)}
125157
className={props.className}
126158
>
127-
{props.children}
159+
{props.intlMessage ? (
160+
<FormattedMessage {...props.intlMessage} />
161+
) : (
162+
props.children
163+
)}
128164
</small>
129165
);
130166

@@ -143,9 +179,10 @@ Detail.propTypes = {
143179
'inverted',
144180
]),
145181
className: PropTypes.string,
146-
children: PropTypes.node.isRequired,
147182
title: nonEmptyString,
148183
truncate: PropTypes.bool,
184+
intlMessage: requiredIf(intlMessageShape, props => !props.children),
185+
children: requiredIf(PropTypes.node, props => !props.intlMessage),
149186
};
150187

151188
export default {

src/components/typography/text/text.spec.js

+45-8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import React from 'react';
22
import { render } from '../../../test-utils';
33
import Text from './text';
44

5+
const intlMessage = { id: 'Title', defaultMessage: 'Hello' };
6+
57
describe('exports', () => {
68
it('should export 5 components', () => {
79
expect(Object.keys(Text)).toHaveLength(5);
@@ -43,6 +45,17 @@ describe('<Headline>', () => {
4345
expect(container).toHaveTextContent('Title');
4446
});
4547

48+
it('should render given text with react-intl', () => {
49+
const { container } = render(
50+
<Text.Headline
51+
elementType="h1"
52+
title="tooltip text"
53+
intlMessage={intlMessage}
54+
/>
55+
);
56+
expect(container).toHaveTextContent('Hello');
57+
});
58+
4659
it('should set `title` attribute', () => {
4760
const { queryByTitle } = render(
4861
<Text.Headline elementType="h1" title="tooltip text">
@@ -69,7 +82,6 @@ describe('<Subheadline>', () => {
6982
{'Title'}
7083
</Text.Subheadline>
7184
);
72-
7385
expect(container.querySelector('h4')).toBeInTheDocument();
7486
});
7587

@@ -79,10 +91,20 @@ describe('<Subheadline>', () => {
7991
{'Subtitle'}
8092
</Text.Subheadline>
8193
);
82-
8394
expect(container).toHaveTextContent('Subtitle');
8495
});
8596

97+
it('should render given text with react-intl', () => {
98+
const { container } = render(
99+
<Text.Subheadline
100+
elementType="h4"
101+
title="tooltip text"
102+
intlMessage={intlMessage}
103+
/>
104+
);
105+
expect(container).toHaveTextContent('Hello');
106+
});
107+
86108
it('should set `title` attribute', () => {
87109
const { queryByTitle } = render(
88110
<Text.Subheadline elementType="h4" title="tooltip text">
@@ -107,10 +129,16 @@ describe('<Wrap>', () => {
107129
const { container } = render(
108130
<Text.Wrap title="tooltip text">{'Text'}</Text.Wrap>
109131
);
110-
111132
expect(container).toHaveTextContent('Text');
112133
});
113134

135+
it('should render given text with react-intl', () => {
136+
const { container } = render(
137+
<Text.Wrap title="tooltip text" intlMessage={intlMessage} />
138+
);
139+
expect(container).toHaveTextContent('Hello');
140+
});
141+
114142
it('should set `title` attribute', () => {
115143
const { queryByTitle } = render(
116144
<Text.Wrap title="tooltip text">{'Title'}</Text.Wrap>
@@ -133,18 +161,23 @@ describe('<Body>', () => {
133161
const { container } = render(
134162
<Text.Body title="tooltip text">{'Body'}</Text.Body>
135163
);
136-
137164
expect(container.querySelector('p')).toBeInTheDocument();
138165
});
139166

140167
it('should render given text', () => {
141168
const { container } = render(
142169
<Text.Body title="tooltip text">{'Text'}</Text.Body>
143170
);
144-
145171
expect(container).toHaveTextContent('Text');
146172
});
147173

174+
it('should render given text with react-intl', () => {
175+
const { container } = render(
176+
<Text.Body title="tooltip text" intlMessage={intlMessage} />
177+
);
178+
expect(container).toHaveTextContent('Hello');
179+
});
180+
148181
it('should forward data attriutes', () => {
149182
const { getByTitle } = render(
150183
<Text.Body data-foo="bar" title="body">
@@ -161,7 +194,6 @@ describe('<Body>', () => {
161194
{'Body'}
162195
</Text.Body>
163196
);
164-
165197
expect(container.querySelector('span')).toBeInTheDocument();
166198
});
167199
});
@@ -172,18 +204,23 @@ describe('<Detail>', () => {
172204
const { container } = render(
173205
<Text.Detail title="tooltip text">{'Detail'}</Text.Detail>
174206
);
175-
176207
expect(container.querySelector('small')).toBeInTheDocument();
177208
});
178209

179210
it('should render given text', () => {
180211
const { container } = render(
181212
<Text.Detail title="tooltip text">{'Text'}</Text.Detail>
182213
);
183-
184214
expect(container).toHaveTextContent('Text');
185215
});
186216

217+
it('should render given text with react-intl', () => {
218+
const { container } = render(
219+
<Text.Detail title="tooltip text" intlMessage={intlMessage} />
220+
);
221+
expect(container).toHaveTextContent('Hello');
222+
});
223+
187224
it('should forward data attriutes', () => {
188225
const { getByTitle } = render(
189226
<Text.Detail data-foo="bar" title="detail">

0 commit comments

Comments
 (0)