Skip to content

Instantly share code, notes, and snippets.

@cfenzo
Last active March 16, 2017 12:19
Show Gist options
  • Save cfenzo/10b2705b1d4903ae012b7b03791af246 to your computer and use it in GitHub Desktop.
Save cfenzo/10b2705b1d4903ae012b7b03791af246 to your computer and use it in GitHub Desktop.
<ShowMore> component
import React from 'react';
class ShowMore extends React.Component {
contentHeight = 0
state = {
contentHeight: 0,
expanded: false
}
componentDidMount() {
this.updateHeight();
}
componentDidUpdate() {
this.updateHeight();
}
updateHeight() {
if(this.contentHeight !== this.state.contentHeight){
this.setState(state => ({
contentHeight: this.contentHeight
}));
}
}
toggleExpanded = () => {
this.setState(state => ({
expanded:!state.expanded
}));
}
render() {
let {
children,
className,
height,
more,
less,
useGradient,
gradientHeight,
gradientColor,
buttonClassName
} = this.props;
let {expanded, contentHeight} = this.state;
let truncated = height < contentHeight;
let gradientStyle = {
position: 'absolute',
bottom: 0,
left:0,
width: '100%',
height: gradientHeight,
/* no support for multiple background styles in react style={} ..
background: `-moz-linear-gradient(top, transparent 0%, ${gradientColor} 80%)`,
background: `-webkit-linear-gradient(top, transparent 0%, ${gradientColor} 80%)`,
background: `-ms-linear-gradient(top, transparent 0%, ${gradientColor} 80%)`,
// TODO add filter for broader IE support?
*/
background: `linear-gradient(to bottom, transparent 0%, ${gradientColor} 80%)`
};
return (
<div className={className}>
{/* Measure the height of the content (children) */}
<div style={{position: 'relative', height:0, width:'100%', overflow:'hidden', padding:0, margin:0}}>
<div
style={{position: 'absolute', width: '100%', top: '0', left: '-100%', padding:0, margin:0}}
ref={ ref => {
{/* set this.contentHeight if ref !== null */}
if(ref !== null) this.contentHeight = ref.offsetHeight;
}}
>
{children}
</div>
</div>
{/* render content (children) */}
<div style={{
position: 'relative',
maxHeight: expanded ? 'none' : height+'px',
overflow: expanded ? 'auto' : 'hidden'
}}>
{children}
{/* gradient overlay for smoooooth transition */}
{useGradient && truncated && !expanded && <div style={gradientStyle}></div>}
</div>
{/* toggle button */}
{truncated && <button onClick={this.toggleExpanded} className={buttonClassName}>{expanded?more:less}</button>}
</div>);
}
}
ShowMore.PropTypes = {
children: React.PropTypes.any,
className: React.PropTypes.string,
height: React.PropTypes.number,
more: React.PropTypes.string,
less: React.PropTypes.string,
useGradient: React.PropTypes.bool,
gradientHeight: React.PropTypes.string,
gradientColor: React.PropTypes.string,
buttonClassName: React.PropTypes.string
};
ShowMore.defaultProps = {
height: 100,
more: 'Show more',
less: 'Show less',
useGradient: true,
gradientHeight: '3em',
gradientColor: '#fff'
};
export default ShowMore;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment