See Styled TodoItem Component

Story: As a user, I want my TodoItem component to be styled.

TodoItem

In order to apply the desired TodoItem styling we'll need change the structure of the markup. Let's replace checkboxes with .svg images and delete button with a div.

diff --git a/src/todomvc/components/TodoItem.js b/src/todomvc/components/TodoItem.js
index 65c5d42..2b4eb51 100644
--- a/src/todomvc/components/TodoItem.js
+++ b/src/todomvc/components/TodoItem.js
@@ -2,6 +2,7 @@

 import React, {Component} from 'react'
 import PropTypes from 'prop-types'
+
 import TodoTextInput from './TodoTextInput'

 export default class TodoItem extends Component {
@@ -28,30 +29,48 @@ export default class TodoItem extends Component {
     this.setState({editing: false})
   }

+  renderButtonUnchecked() {
+    const {todo, toggleCompleteOneTodo} = this.props;
+
+    return (
+      <svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"
+           onClick={() => toggleCompleteOneTodo(todo.get('id'))}>
+        <circle cx="50" cy="50" r="50" fill="none" stroke="#ededed" strokeWidth="3"/>
+      </svg>
+    )
+  }
+
+  renderButtonChecked() {
+    const {todo, toggleCompleteOneTodo} = this.props;
+    return (
+      <svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"
+           onClick={() => toggleCompleteOneTodo(todo.get('id'))}>
+        <circle cx="50" cy="50" r="50" fill="none" stroke="#bddad5" strokeWidth="3"/>
+        <path fill="#5dc2af" d="M72 25L42 71 27 56l-4 4 20 20 34-52z"/>
+      </svg>
+    )
+  }
+
   renderTodoListItem() {
-    const {todo, deleteTodo, toggleCompleteOneTodo} = this.props;
+    const {todo, deleteTodo} = this.props;

     return (
       <li>
+        {todo.get('completed') ? this.renderButtonChecked() : this.renderButtonUnchecked()}
         <label onDoubleClick={this.handleDoubleClick.bind(this)}>
           {todo.get('description')}
         </label>
-        <input type="checkbox" name="completed" checked={todo.get('completed')}
-               onChange={ () => toggleCompleteOneTodo(todo.get('id')) }/>completed
-        <button onClick={() => deleteTodo(todo.get('id'))}>delete todo</button>
+        <div onClick={() => deleteTodo(todo.get('id'))}>x</div>
       </li>
     )
   }

   renderTodoTextInput() {
-    const {todo, deleteTodo, toggleCompleteOneTodo} = this.props;
+    const {todo} = this.props;

     return (
       <li>
         <TodoTextInput text={todo.get('description')} onSave={(text) => this.handleSave(todo.get('id'), text)}/>
-        <input type="checkbox" name="completed" checked={todo.get('completed')}
-               onChange={ () => toggleCompleteOneTodo(todo.get('id')) }/>completed
-        <button onClick={() => deleteTodo(todo.get('id'))}>delete todo</button>
       </li>
     )
   }
(END)

Check how this effected our existing tests.

Four tests have failed! Let's update our tests to reflect the changed markup.

Run tests and watch them pass.

Commit changes.

Now let's address our styling process.

Should be styled correctly

It should have li styling applied in accordance with the design specs

In order to test the styling of the last todo in the list, we'll have to create a MainSection component with several TodoItem elements in our test case. Write the test.

Run the test and watch it fail.

Write the code to make the test pass. First, we'll have to pass the information whether the todo is the last in the list. This requires a change to MainSection component:

Then, we need to change the TodoItem component too. Unlike with previous components we will apply the styling directly on the tag. This is one of the difficulties of styling pseudo-selectors (:last-child in this case) in Radium library. Also, pay attention to :hover pseudo selector... Even though we don't have any special style on the li hover event, we need to add empty :hover style here to tell Radium to track this element's state.

Run the test and watch it pass.

Commit changes.

It should have ButtonChecked styling applied in accordance with the design specs

Change the way your setup() works and write the test.

Run the test and watch it fail.

Write the code to make the test pass.

Run the test and watch it pass.

Commit changes.

It should have ButtonUnchecked styling applied in accordance with the design specs

Write the test.

Run the test and watch it fail.

Write the code to make the test pass.

Run the test and watch it pass.

Commit changes.

It should have label not completed styling applied in accordance with the design specs

Write the test.

Run the test and watch it fail.

Write the code to make the test pass.

Run the test and watch it pass.

Commit changes.

It should have label completed styling applied in accordance with the design specs

Write the test.

Run the test and watch it fail.

Write the code to make the test pass.

Run the test and watch it pass.

Commit changes.

It should have delete div styling applied in accordance with the design specs

Write the test.

Run the test and watch it fail.

Write the code to make the test pass.

Run the test and watch it pass.

Commit changes.

It should not display delete div initially

Create this test as a separate one because it will help the next behavior test. Write the test.

Run the test and watch it fail.

Write the code to make the test pass.

Run the test and watch it pass.

Commit changes.

Should behave correctly

It should display delete div only when hovering over a todo

Write the test.

Run the test and watch it fail.

Write the code to make the test pass.

Run the test and watch it pass.

Commit changes.

Last updated

Was this helpful?