Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement highlightedtext component #1864

Merged
merged 8 commits into from
Oct 5, 2020
70 changes: 15 additions & 55 deletions src/components/HighlightedText/__test__/HighlightedText.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,81 +21,41 @@ describe('<HighlightedText />', () => {
it('should return 3 <span> with theirs respective values because the default wrapper is a span', () => {
const component = mount(<HighlightedText parts={parts} />);
const container = component.find('span');
expect(
container
.at(0)
.html()
.includes('Apples'),
).toBe(true);
expect(
container
.at(1)
.html()
.includes('varieties'),
).toBe(true);
expect(
container
.at(2)
.html()
.includes('Honeycrisp'),
).toBe(true);
expect(container.length).toBe(3);
parts.forEach(({ value }, index) => {
expect(
container
.at(index)
.html()
.includes(value),
).toBe(true);
});
});
it('should return 3 custom <span> with theirs respective values because the custom wrapper is a span', () => {
const TextContainer = styled.span`
color: grey;
`;

const HitContainer = styled.span`
color: #fff;
`;

const component = mount(
<HighlightedText
parts={parts}
textComponent={TextContainer}
hitComponent={HitContainer}
/>,
);
const container = component.find('span');
expect(
container
.at(0)
.html()
.includes('Apples'),
).toBe(true);
expect(
container
.at(1)
.html()
.includes('varieties'),
).toBe(true);
expect(
container
.at(2)
.html()
.includes('Honeycrisp'),
).toBe(true);
it('it should not return a <p> container', () => {
const component = mount(<HighlightedText parts={parts} isInline />);
expect(component.html().includes('<p>')).toBe(false);
});

it('should return a custom <span> with id="hitText" in the container at(1) which corresponds to the text that has a type hit', () => {
const TextContainer = styled.span`
color: grey;
color: #808080;
`;

const HitContainer = styled.span`
color: #fff;
`;

// eslint-disable-next-line react/prop-types
const hitComponent = ({ children }) => {
const HitComponent = ({ children }) => {
return <HitContainer id="hitText">{children}</HitContainer>;
};

const component = mount(
<HighlightedText
parts={parts}
textComponent={TextContainer}
hitComponent={hitComponent}
hitComponent={HitComponent}
/>,
);
const container = component.find('span');
Expand Down
31 changes: 31 additions & 0 deletions src/components/HighlightedText/highlighContainer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';
import PropTypes, { bool, node } from 'prop-types';

export default function HighlighContainer({ children, isInline, className, style }) {
if (isInline) {
return (
<span className={className} style={style}>
{children}
</span>
);
}
return (
<p className={className} style={style}>
{children}
</p>
);
}

HighlighContainer.propTypes = {
className: PropTypes.string,
style: PropTypes.object,
children: node,
isInline: bool,
};

HighlighContainer.defaultProps = {
className: undefined,
style: undefined,
children: undefined,
isInline: false,
};
3 changes: 2 additions & 1 deletion src/components/HighlightedText/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ interface Part {
export interface HighlightedText extends BaseProps {
hitComponent?: ComponentType<{ children?: string }>;
textComponent?: ComponentType<{ children?: string }>;
part?: Part[];
parts?: Part[];
isInline: boolean;
LeandroTorresSicilia marked this conversation as resolved.
Show resolved Hide resolved
}

export default function(props: HighlightedText): JSX.Element | null;
18 changes: 10 additions & 8 deletions src/components/HighlightedText/index.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,31 @@
import React from 'react';
import PropTypes from 'prop-types';
import PropTypes, { bool } from 'prop-types';
LeandroTorresSicilia marked this conversation as resolved.
Show resolved Hide resolved
import HitText from './hitText';
import HighlighContainer from './highlighContainer';
import { DefaultHitContainer, DefaultTextContainer } from './styled/index';

LeandroTorresSicilia marked this conversation as resolved.
Show resolved Hide resolved
/**
* HighlightedText is a component that highlights a part of a text.
*/

function HighlightedText(props) {
const { style, className, parts, hitComponent, textComponent } = props;
export default function HighlightedText(props) {
const { style, className, parts, hitComponent, textComponent, isInline } = props;
const finalHitContainer = hitComponent || DefaultHitContainer;
const finalTextContainer = textComponent || DefaultTextContainer;

return (
<p className={className} style={style}>
<HighlighContainer className={className} style={style} isInline={isInline}>
<HitText
parts={parts}
hitComponent={finalHitContainer}
textComponent={finalTextContainer}
/>
</p>
</HighlighContainer>
);
}

export default HighlightedText;

HighlightedText.propTypes = {
/** The class of the component. */
/** A CSS class for the outer element, in addition to the component's base classes. */
className: PropTypes.string,
/** An object with the custom styles of the container. */
style: PropTypes.object,
Expand All @@ -47,6 +46,8 @@ HighlightedText.propTypes = {
* the text not highlighted
*/
textComponent: PropTypes.elementType,
LeandroTorresSicilia marked this conversation as resolved.
Show resolved Hide resolved
/** A boolean that when it is true wraps the text in a span tag, and when it is false wraps it in a p tag, this lets you display the text block or inline */
LeandroTorresSicilia marked this conversation as resolved.
Show resolved Hide resolved
isInline: bool,
};

HighlightedText.defaultProps = {
Expand All @@ -55,4 +56,5 @@ HighlightedText.defaultProps = {
parts: undefined,
hitComponent: undefined,
textComponent: undefined,
isInline: false,
};
79 changes: 41 additions & 38 deletions src/components/HighlightedText/readme.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
# HighlightedText base
##### This example shows the style that is applied by default to the component.
```js
import React, { useState } from 'react';
import { HighlightedText } from 'react-rainbow-components';
import React from 'react';
import { HighlightedText } from 'react-rainbow-components';

const style = {
maxWidth:"700px",
textAlign:"center",
padding:"20px",
margin:"auto",
maxWidth: '700px',
textAlign: 'center',
padding: '20px',
margin: 'auto',
};

const parts = [
{
"value" : "Apples come in several ",
"type" : "text"
},
{
"value" : "varieties",
"type" : "hit"
},
{
"value" : ", including Fuji, Granny Smith, and Honeycrisp.",
"type" : "text"
}
{
value: 'Apples come in several ',
type: 'text',
},
{
value: 'varieties',
type: 'hit',
},
{
value: ', including Fuji, Granny Smith, and Honeycrisp.',
type: 'text',
},
];

<HighlightedText parts={parts} style={style} />
<HighlightedText parts={parts} style={style} />;

```

# HighlightedText with custom styles
##### This example shows the component when custom styles are applied to it.

```js
import React, { useState } from 'react';
import React from 'react';
import styled from 'styled-components';
import { HighlightedText } from 'react-rainbow-components';
import { HighlightedText } from 'react-rainbow-components';

const style = {
maxWidth: '700px',
Expand All @@ -46,32 +46,35 @@ const style = {
};

const parts = [
{
"value" : "Apples come in several ",
"type" : "text"
},
{
"value" : "varieties",
"type" : "hit"
},
{
"value" : ", including Fuji, Granny Smith, and Honeycrisp.",
"type" : "text"
}
{
value: 'Apples come in several ',
type: 'text',
},
{
value: 'varieties',
type: 'hit',
},
{
value: ', including Fuji, Granny Smith, and Honeycrisp.',
type: 'text',
},
];

const TextContainer = styled.span`
color: gray;
color: ${(props) => props.theme.rainbow.palette.text.title};
font-size: 1rem;
`;

const HitContainer = styled.span`
background-color: #00a3dc;
color: #fff;
const HitContainer = styled.span.attrs(props => {
return props.theme.rainbow.palette;
})
`
background-color: ${(props) => props.brand.main};
color: ${props => props.getContrastText(props.text.main)};
font-size: 1rem;
`;

<HighlightedText parts={parts} style={style} textComponent={TextContainer} hitComponent={HitContainer}/>
<HighlightedText parts={parts} style={style} textComponent={TextContainer} hitComponent={HitContainer} />;

```