React

by Abdul Ahmad

HTML

<div id="app"></div>

SCSS

body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}

.health-bar {
  width: 100px;
  height: 20px;
  position: relative;
  border: 1px solid darken(red, 5%);
  border-radius: 20px;
  overflow: hidden;


  .bar-fill {
    position: absolute;
    background: lighten(red, 30%);
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;

    &.animate {
      transition: all 1s ease 0.3s;
    }
    
    &.instant {
      background: red;
      z-index: 2;
    }
  }
  
  .health-bar-status {
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    z-index: 3;
    font-size: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  
  
    
  .damage-text {
    position: absolute;
    font-size: 14px;
    color: yellow;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding-right: 5px;
    box-sizing: border-box;
    z-index: 10;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    
    span {
      letter-spacing: 1px;

      text-shadow: 
        1px 0 0 black, 
        -1px 0 0 black, 
        0 1px 0 black, 
        0 -1px 0 black, 
        1px 1px black, 
        -1px -1px 0 black, 
        1px -1px 0 black, 
        -1px 1px 0 black;
    }
  }
}

.button {
  margin-top: 10px;
}

React

class TodoApp extends React.Component {
	healthBarTextTimeoutId;

	state = {
  	health: 100,
    healthBarText: '',
    lastHealthbarTextType: '',
  };
  
  applyDamage = () => {
  	clearTimeout(this.healthBarTextTimeoutId);
  	this.setState(s => {
      let newHealth = s.health - 30;
      if (newHealth < 0) newHealth = 0;
      
      const healthDiff = s.health - newHealth;
      let healthBarText = '';
      if (healthDiff > 0) healthBarText = '-' + healthDiff;

      return { 
        health: newHealth,
        healthBarText,
        lastHealthbarTextType: 'damage',
      };
    }, () => {
    	this.healthBarTextTimeoutId = setTimeout(() => {
      	this.setState({ healthBarText: '' });
      }, 1000);
    });
  };
  
  applyHeal = () => {
  	clearTimeout(this.healthBarTextTimeoutId);
  	this.setState(s => {
      let newHealth = s.health + 30;
      if (newHealth > 100) newHealth = 100;
      
      const healthDiff = newHealth - s.health;
      let healthBarText = '';
      if (healthDiff > 0) healthBarText = '+' + healthDiff;

      return { 
        health: newHealth,
        healthBarText,
        lastHealthbarTextType: 'heal',
      };
    }, () => {
    	this.healthBarTextTimeoutId = setTimeout(() => {
      	this.setState({ healthBarText: '' });
      }, 1000);
    });
  };
  
  render() {
  	const animClassTopFill = this.state.lastHealthbarTextType === 'heal' ? 'animate' : '';
    const animClassBotFill = this.state.lastHealthbarTextType === 'damage' ? 'animate' : '';
    return (
      <div>
        <div className='health-bar'>
          <div 
            className={'bar-fill ' + animClassBotFill}
            style={{
            	width: this.state.health + '%',
            }}
          />
          <div 
            className={'bar-fill instant ' + animClassTopFill}
            style={{
            	width: this.state.health + '%',
            }}
          />
          <div className='health-bar-status'>
           ...