<todo />

<script type="riot/tag">

  <entry>
    <form onsubmit={ create }>
      <input type="text" value={ name } placeholder="新規タスクを入力" onkeyup={ changeName }>
      <select onchange={ changePriority }>
        <option value="low" selected={ priority === 'low' }>優先度:低</option>
        <option value="mid" selected={ priority === 'mid' }>優先度:中</option>
        <option value="high" selected={ priority === 'high' }>優先度:高</option>
      </select>
      <button disabled={ name === '' }>追加</button>
    </form>

    var DEFAULT_NAME     = '';
    var DEFAULT_PRIORITY = 'mid';

    this.name     = DEFAULT_NAME;
    this.priority = DEFAULT_PRIORITY;

    changeName(e) {
      this.name = e.target.value;
    }

    changePriority(e) {
      this.priority = e.target.value;
    }

    create(e){
      e.preventDefault();
      opts.onCreate({
        name      : this.name,
        priority  : this.priority,
        isChecked : false
      });
      this.name     = DEFAULT_NAME;
      this.priority = DEFAULT_PRIORITY;
    }

    <style>
      form {
        padding : 10px;
      }
      input[type="text"],
      select,
      button {
        vertical-align : middle;
        border-radius  : .5rem;
      }
      input[type="text"],
      select {
        font-size : 1.6rem;
        border    : 1px solid #ccc;
      }
      input[type="text"] {
        padding : .4rem;
      }
      select {
        padding : .4rem 1rem;
      }
      button {
        font-size        : 1.4rem;
        padding          : .6rem 1rem;
        color            : #fff;
        background-color : #333;
        transition       : background-color .3s;
      }
      button:disabled {
        background-color : #ccc;
        cursor           : default;
        transition       : none;
      }
    </style>
  </entry>

  <task>
    <label class={ done: opts.props.isChecked }>
      <p><input type="checkbox" checked={ opts.props.isChecked } onchange={ toggleCheckbox }></p>
      <p>
        <span if={ opts.props.priority === 'low' } class="low">低</span>
        <span if={ opts.props.priority === 'mid' } class="mid">中</span>
        <span if={ opts.props.priority === 'high' } class="high">高</span>
      </p>
      <p>{ opts.props.name }</p>
    </label>

    toggleCheckbox(e) {
      opts.onUpdate(opts.index, e.target.checked);
    }

    <style>
      :scope {
        display : block;
      }
      label {
        display          : flex;
        align-items      : center;
        padding          : 5px 5px 5px 10px;
        border-radius    : .5rem;
        background-color : #fff;
        box-shadow       : 0 1px 0 rgba(0,0,0,.05);
        cursor           : pointer;
      }
      input[type="checkbox"] {
        vertical-align : .1em;
      }
      p:nth-child(1),
      p:nth-child(2) {
        flex-basis : auto;
      }
      p:nth-child(2) {
        padding : 0 10px;
      }
      p:nth-child(3) {
        flex-grow : 1;
      }
      .done p:nth-child(2),
      .done p:nth-child(3) {
        opacity: .3;
      }

      p:nth-child(2) > span {
        font-size      : 1rem;
        color          : #fff;
        padding        : 4px;
        border-radius  : 50%;
        vertical-align : middle;
      }
      p:nth-child(2) > span.low {
        background-color : #028EAF;
      }
      p:nth-child(2) > span.mid {
        background-color : #F88E21;
      }
      p:nth-child(2) > span.high {
        background-color : #C01617;
      }
    </style>
  </task>

  <todo>
    <h1>TODO List</h1>

    <entry on-create={ createTask } />

    <ul>
      <li each={ task, i in tasks }>
        <task index={ i } props={ task } on-update={ parent.updateTask } />
      </li>
    </ul>

    <p>
      <button disabled={ !hasCheckedTask } onclick={ removeCheckedTasks }>完了したタスクを削除</button>
    </p>

    this.tasks          = [];
    this.hasCheckedTask = false;

    createTask(data) {
      this.tasks.push(data);
      this.update();
    }

    updateTask(index, value) {
      this.tasks[index].isChecked = value;
      this.hasCheckedTask = this.tasks.some(function(task){
        return task.isChecked;
      });
      this.update();
    }

    removeCheckedTasks() {
      this.tasks = this.tasks.filter(function(task){
        return !task.isChecked;
      });
      this.hasCheckedTask = false;
      this.update();
    }

    <style>
      :scope {
        display          : block;
        background-color : #fff;
        font-size        : 1.6rem;
      }
      > h1 {
        font-size : 1.8rem;
        color     : #666;
        padding   : 10px 10px 0;
      }
      > ul {
        height           : 200px;
        padding          : 10px;
        overflow-y       : scroll;
        background-color : #eee;
        box-sizing       : border-box;
      }
      > ul > li:not(:first-child) {
        margin-top : 10px;
      }
      > ul > li.empty {
        color     : #ccc;
        font-size : 1.4rem;
        padding   : 5px;
      }
      > p {
        padding : 10px;
      }
      > p button {
        font-size        : 1.4rem;
        padding          : .6rem 1rem;
        border-radius    : .5rem;
        color            : #fff;
        background-color : #333;
        transition       : background-color .3s;
      }
      > p button:disabled {
        background-color : #ccc;
        cursor           : default;
        transition       : none;
      }
    </style>
  </todo>

</script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/riot/3.3.1/riot+compiler.min.js"></script>
<script>
  riot.mount('todo');
</script>
html {
  font-size : 62.5%;
}

body {
  font-family      : sans-serif;
  font-size        : 1.4rem;
  line-height      : 1.5;
  color            : #333;
  background-color : #fff;
}

input[type="text"], select, button {
  appearance  : none;
  font-family : inherit;
  font-size   : inherit;
  line-height : inherit;
}

input[type="checkbox"] {
  margin : 0;
}

button {
  border  : none;
  cursor  : pointer;
  outline : none;
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.