React accordion

a nice React accordion example.

Made with





$brown = #f0ebe1
$black = #372717
$gray = #756658

*, *:after, *:before
	box-sizing inherit

	display flex
	justify-content center
	padding 50px 0
	background-color #FCFCFC
	min-height 100vh
	font-size 16px
	line-height 1.4
	font-family 'Montserrat', sans-serif
	color $black
	box-sizing border-box
	overflow-y scroll
	width 100%
	max-width 470px
	background-color $brown
		position relative
		display block
		width 100%
		background none
		border none
		text-align left
		padding 25px 60px 25px 25px
		font-weight 500
		font-size 17px
		font-family inherit
		transition color .2s linear
		cursor pointer
			outline none
			content ''
			position absolute
			right 25px
			top 50%
			width 22px
			height 2px
			margin-top [email protected]
			background-color $black
			transform rotate(-90deg)
			transition transform .35s cubic-bezier(.65, .05, .36, 1)
		& ^[0]__content
			opacity 1

		& ^[0]__label
			color #957029
				transform rotate(0deg)
		overflow hidden
		will-change height
		transition height .4s cubic-bezier(.65, .05, .36, 1)
		margin 5px 25px 25px
		font-size 14px
		color $gray
		opacity 0
		transition opacity .3s linear .18s
		margin-bottom 3px


class Panel extends React.Component {
	constructor(props) {
		this.state = {
			height: 0

	componentDidMount() {
		window.setTimeout(() => {
			const el = ReactDOM.findDOMNode(this);
			const height = el.querySelector('.panel__inner').scrollHeight;
		}, 333);

	render () {
		const { label, content, activeTab, index, activateTab } = this.props;
		const { height } = this.state;
		const isActive = activeTab === index;
		const innerStyle = {
			height: isActive ? `${height}px` : '0px'

		return (
			<div className='panel'
				<button className='panel__label'
				<div className='panel__inner'
					<p className='panel__content'>

class Accordion extends React.Component {
	constructor(props) {
		this.state = {
			activeTab: 0
		this.activateTab = this.activateTab.bind(this);
	activateTab(index) {
		this.setState(prev => ({
			activeTab: prev.activeTab === index ? -1 : index
	render() {
		const { panels } = this.props;
		const { activeTab } = this.state;
		return (
			<div className='accordion' role='tablist'>
				{, index) =>
						activateTab={this.activateTab.bind(null, index)}

const panels = [
		label: 'Seriously, Don\'t Use Icon Fonts',
		content: 'Icons are everywhere. These "little miracle workers" (as John Hicks described them) help us reinforce meaning in the interfaces we design and build. Their popularity in web design has never been greater; the conciseness and versatility of pictograms in particular make them a lovely fit for displays large and small. But icons on the web have had their fair share of challenges.',
		label: 'Screen Readers Actually Read That Stuff',
		content: 'Most assistive devices will read aloud text inserted via CSS, and many of the Unicode characters icon fonts depend on are no exception. Best-case scenario, your "favorite" icon gets read aloud as "black favorite star." Worse-case scenario, it\'s read as "unpronounceable" or skipped entirely.',
		label: 'They Fail Poorly and Often',
		content: 'When your icon font fails, the browser treats it like any other font and replaces it with a fallback. Best-case scenario, you\'ve chosen your fallback characters carefully and something weird-looking but communicative still loads. Worse-case scenario (and far more often), the user sees something completely incongruous, usually the dreaded "missing character" glyph.',
		label: 'They\'re a Nightmare if You\'re Dyslexic',
		content: 'Many dyslexic people find it helpful to swap out a website\'s typeface for something like OpenDyslexic. But icon fonts get replaced as well, which makes for a frustratingly broken experience.',
		label: 'There\'s Already a Better Way',
		content: 'SVG is awesome for icons! It\'s a vector image format with optional support for CSS, JavaScript, reusability, accessibility and a bunch more. It was made for this sort of thing.'

const App = document.querySelector('#app');

ReactDOM.render(<Accordion panels={panels}/>, App);




See the Pen React accordion by DNLHC (@DNLHC) on CodePen.