JSFiddle - React, Tailwind, and code Playground

by Tyler Brown

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.2.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>

SCSS

* {
  transition: all 200ms;
}

.ex {
  display: flex;
  flex: 1;
  flex-direction: row;
  align-items: center;
  border: 1px solid #CCC;
  border-bottom: 0;
  font-family: 'Avenir', 'Helvetica', Arial;
  
  &.active .ex-name {
    color: black;
    font-weight: bold;
  }
  
  &.inactive .ex-name {
    color: #CCC;
  }

  &-name {
    width: 300px;
    /* border: 1px solid black; */
    padding: 0 12px;
  }
  
  &-weeks {
    flex: 1;
    border-left: 1px solid #CCC;
    display: flex;
    flex-direction: row;
    
    &-week {
      border-right: 1px solid #CCC;
      width: 30px;
      height: 30px;
      
      &.date {
        text-align: center;
        font-size: 11px;
      }
      
      &.phase-1 { background-color: #FDD; }
      &.phase-2 { background-color: #FFD; }
      &.phase-3 { background-color: #DFD; }
      &.phase-4 { background-color: #DFF; }
      &.phase-5 { background-color: #DDF; }
      &.phase-1.active { background-color: #F88; }
      &.phase-2.active { background-color: #FF8; }
      &.phase-3.active { background-color: #8F8; }
      &.phase-4.active { background-color: #8FF; }
      &.phase-5.active { background-color: #88F; }
      
      .dot {
        width: 24px;
        height: 24px;
        /* background-color: #CCC; */
        border-radius: 100px;
        margin: 3px;
      }
      
      &.on .dot {
        background-color: #CCC;
      }
      &.on.active .dot {
        background-color: #333;
      }
    }
  }
}

Babel + JSX

const weeks = [...Array(12).keys()].map(n => n + 1);
const weekPhaseMap = {
	1: 1,
	2: 1,
	3: 1,
	4: 2,
	5: 2,
	6: 2,
	7: 3,
	8: 3,
	9: 4,
	10: 4,
	11: 4,
	12: 5,
};
const weekDateMap = {
	1: '1/25',
	2: '2/1',
	3: '2/8',
	4: '2/15',
	5: '2/22',
	6: '3/1',
	7: '3/8',
	8: '3/15',
	9: '3/22',
	10: '3/29',
	11: '4/5',
	12: '4/12',
};

class App extends React.Component {

  constructor(props) {
  	super(props);
    this.state = {
    	activeWeek: 1,
    };
  }

  onWeekMouseEnter(week) {
  	this.setState({activeWeek: week});
  }

  render() {
    return (
      <div>
        {this.state.activeWeek || 'none'}
        <div className="exercise ex">
          <div className="ex-name"></div>
          <div className="ex-weeks">
            {weeks.map((week) => {
              const date = weekDateMap[week];
              return (
                <div className="ex-weeks-week date">{date}</div>
              );
            })}
          </div>
        </div>
        {exercises.map((exercise) => {
          const isActive = this.state.activeWeek >= exercise.startWeek &&  this.state.activeWeek <= exercise.endWeek;
	        return (
            <div className={`exercise ex ${isActive ? 'active' : 'inactive'}`}>
              <div className="ex-name">{exercise.name}</div>
              <div className="ex-weeks">
                {weeks.map((week) => {
                  const isOn = week >= exercise.startWeek && week <= exercise.endWeek;
                  const isActiveWeek = this.state.activeWeek == week;
                  const phase = weekPhaseMap[week];
                  return (
                    <div className={`ex-weeks-week ${isOn ? 'on' : 'off'} ${isActiveWeek ? 'active' : 'inactive'} phase-${phase}`} onMouseEnter={this.onWeekMouseEnter.bind(this, week)}><div className="dot" /></div>
                  );
                })}
              </div>
            </div>
          );
        })}
      </div>
    );
  }
};

const exercises = [
	{name: "standing abduction w/o...