diff --git a/components/chart/chart-legend.js b/components/chart/chart-legend.js
new file mode 100644
index 0000000000000000000000000000000000000000..df6f8a60f77f36e6fb648ed2369cad9af5d0ebfa
--- /dev/null
+++ b/components/chart/chart-legend.js
@@ -0,0 +1,27 @@
+import React from 'react'
+import { View } from 'react-native'
+
+import AppText from '../app-text'
+import DripHomeIcon from '../../assets/drip-home-icons'
+
+import styles from './styles'
+import { cycleDayColor } from '../../styles'
+
+import { shared as labels } from '../../i18n/en/labels'
+
+const ChartLegend = () => {
+  return (
+    <View style={[styles.yAxis, styles.chartLegend]}>
+      <DripHomeIcon
+        name="circle"
+        size={styles.yAxis.width - 7}
+        color={cycleDayColor}
+      />
+      <AppText style={styles.yAxisLabels.dateLabel}>
+        {labels.date.toLowerCase()}
+      </AppText>
+    </View>
+  )
+}
+
+export default ChartLegend
diff --git a/components/chart/chart.js b/components/chart/chart.js
index 4106938772caff868af0cfe819e23e630ccf8a7c..8f8a3f5d37018b81edc4ccfa9d9c0c1b58f06ce0 100644
--- a/components/chart/chart.js
+++ b/components/chart/chart.js
@@ -1,31 +1,20 @@
 import React, { Component } from 'react'
 import { View, FlatList, ActivityIndicator } from 'react-native'
 import { LocalDate } from 'js-joda'
-import { makeYAxisLabels, makeHorizontalGrid } from './y-axis'
+
+import YAxis from './y-axis'
 import nfpLines from './nfp-lines'
 import DayColumn from './day-column'
+import HorizontalGrid from './horizontal-grid'
+
 import { getCycleDaysSortedByDate, getAmountOfCycleDays } from '../../db'
 import styles from './styles'
-import { cycleDayColor } from '../../styles'
 import { scaleObservable } from '../../local-storage'
 import config from '../../config'
-import AppText from '../app-text'
+
 import AppLoadingView from '../app-loading'
-import { shared as labels } from '../../i18n/en/labels'
-import DripIcon from '../../assets/drip-icons'
-import DripHomeIcon from '../../assets/drip-home-icons'
-import nothingChanged from '../../db/db-unchanged'
 
-const symptomIcons = {
-  bleeding: <DripIcon size={16} name='drip-icon-bleeding' color={styles.iconShades.bleeding[3]}/>,
-  mucus: <DripIcon size={16} name='drip-icon-mucus' color={styles.iconShades.mucus[4]}/>,
-  cervix: <DripIcon size={16} name='drip-icon-cervix' color={styles.iconShades.cervix[3]}/>,
-  desire: <DripIcon size={16} name='drip-icon-desire' color={styles.iconShades.desire[2]}/>,
-  sex: <DripIcon size={16} name='drip-icon-sex' color={styles.iconShades.sex[2]}/>,
-  pain: <DripIcon size={16} name='drip-icon-pain' color={styles.iconShades.pain[0]}/>,
-  mood: <DripIcon size={16} name='drip-icon-mood' color={styles.iconShades.mood[0]}/>,
-  note: <DripIcon size={16} name='drip-icon-note' color={styles.iconShades.note[0]}/>
-}
+import nothingChanged from '../../db/db-unchanged'
 
 export default class CycleChart extends Component {
   constructor(props) {
@@ -129,49 +118,30 @@ export default class CycleChart extends Component {
   }
 
   render() {
+    const { chartHeight, chartLoaded } = this.state
     return (
       <View
         onLayout={this.onLayout}
         style={{ flexDirection: 'row', flex: 1 }}
       >
-        {!this.state.chartLoaded && <AppLoadingView />}
-
-        {this.state.chartHeight && this.state.chartLoaded &&
-          <View>
-            <View style={[styles.yAxis, {height: this.symptomRowHeight}]}>
-              {this.symptomRowSymptoms.map(symptomName => {
-                return <View
-                  style={{ alignItems: 'center', justifyContent: 'center' }}
-                  key={symptomName}
-                  width={styles.yAxis.width}
-                  height={this.symptomRowHeight /
-                    this.symptomRowSymptoms.length}
-                >
-                  {symptomIcons[symptomName]}
-                </View>
-              })}
-            </View>
-            <View style={[styles.yAxis, {height: this.columnHeight}]}>
-              {makeYAxisLabels(this.columnHeight)}
-            </View>
-            <View style={[styles.yAxis, { alignItems: 'center', justifyContent: 'center' }]}>
-              <DripHomeIcon
-                name="circle"
-                size={styles.yAxis.width - 7}
-                color={cycleDayColor}
-              />
-              <AppText style={[styles.yAxisLabels.dateLabel]}>
-                {labels.date.toLowerCase()}
-              </AppText>
-            </View>
-          </View>}
-
-
-        {this.state.chartHeight && this.state.chartLoaded &&
-          makeHorizontalGrid(this.columnHeight, this.symptomRowHeight)
+        {!chartLoaded && <AppLoadingView />}
+
+        {chartHeight && chartLoaded && (
+          <YAxis
+            height={this.columnHeight}
+            symptomsToDisplay={this.symptomRowSymptoms}
+            symptomsSectionHeight={this.symptomRowHeight}
+          />
+        )}
+
+        {chartHeight && chartLoaded && (
+          <HorizontalGrid
+            height={this.columnHeight}
+            startPosition={this.symptomRowHeight}
+          />)
         }
 
-        {this.state.chartHeight &&
+        {chartHeight &&
           <FlatList
             horizontal={true}
             inverted={true}
diff --git a/components/chart/day-column.js b/components/chart/day-column.js
index c49f9dbf8bac752c999477c71ccba832f8e0e69c..1597697fc14e5d042f0a2dfb9ea27b4199907277 100644
--- a/components/chart/day-column.js
+++ b/components/chart/day-column.js
@@ -18,8 +18,11 @@ import styles from './styles'
 import config from '../../config'
 import cycleModule from '../../lib/cycle'
 import { getCycleDay } from '../../db'
+
 import DotAndLine from './dot-and-line'
-import { normalizeToScale } from './y-axis'
+import SymptomCell from './symptom-cell'
+
+import { normalizeToScale } from '../helpers/chart'
 
 const label = styles.column.label
 
@@ -139,41 +142,6 @@ class DayColumn extends Component {
     return false
   }
 
-  drawSymptom = (symptom) => {
-
-    const { symptomHeight } = this.props
-    const shouldDrawSymptom = this.data.hasOwnProperty(symptom)
-    const styleParent = [styles.symptomRow, {height: symptomHeight}]
-
-    if (shouldDrawSymptom) {
-      const styleSymptom = styles.iconShades[symptom]
-      const symptomData = this.data[symptom]
-
-      const dataIsComplete = this.isSymptomDataComplete(symptom)
-      const isMucusOrCervix = (symptom === 'mucus') || (symptom === 'cervix')
-
-      const backgroundColor = (isMucusOrCervix && !dataIsComplete) ?
-        'white' : styleSymptom[symptomData]
-      const borderWidth = (isMucusOrCervix && !dataIsComplete) ? 2 : 0
-      const borderColor = styleSymptom[0]
-      const styleChild = [styles.symptomIcon, {
-        backgroundColor,
-        borderColor,
-        borderWidth
-      }]
-
-      return (
-        <View style={styleParent} key={symptom}>
-          <View style={styleChild} />
-        </View>
-      )
-    } else {
-      return (
-        <View style={styleParent} key={symptom} />
-      )
-    }
-  }
-
   render() {
     const columnElements = []
     const { dateString,
@@ -263,9 +231,21 @@ class DayColumn extends Component {
         onPress={() => this.onDaySelect(dateString)}
         activeOpacity={1}
       >
-        <View>
-          {symptomRowSymptoms.map(symptom => this.drawSymptom(symptom))}
-        </View>
+
+        { symptomRowSymptoms.map(symptom => {
+          const hasSymptomData = this.data.hasOwnProperty(symptom)
+          return (
+            <SymptomCell
+              key={symptom}
+              symptom={symptom}
+              symptomValue={hasSymptomData && this.data[symptom]}
+              isSymptomDataComplete={
+                hasSymptomData && this.isSymptomDataComplete(symptom)
+              }
+              height={this.props.symptomHeight}
+            />)
+        }
+        )}
 
         <Surface width={config.columnWidth} height={columnHeight}>
           {column}
diff --git a/components/chart/horizontal-grid.js b/components/chart/horizontal-grid.js
new file mode 100644
index 0000000000000000000000000000000000000000..e7cf7cc1b7fe7ee6f6d1cd72f60d998028121a35
--- /dev/null
+++ b/components/chart/horizontal-grid.js
@@ -0,0 +1,26 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { View } from 'react-native'
+
+import { getTickPositions } from '../helpers/chart'
+
+import styles from './styles'
+
+const HorizontalGrid = ({ height, startPosition }) => {
+  return getTickPositions(height).map(tick => {
+    return (
+      <View
+        top={startPosition + tick}
+        {...styles.horizontalGrid}
+        key={tick}
+      />
+    )
+  })
+}
+
+HorizontalGrid.propTypes = {
+  height: PropTypes.number,
+  startPosition: PropTypes.number,
+}
+
+export default HorizontalGrid
diff --git a/components/chart/nfp-lines.js b/components/chart/nfp-lines.js
index cf73c52234c75521369ce6a7dda7cd2fcf778231..853dde54f634dc27c330be9d05a3fbf31b88a977 100644
--- a/components/chart/nfp-lines.js
+++ b/components/chart/nfp-lines.js
@@ -1,5 +1,5 @@
 import { getCycleStatusForDay } from '../../lib/sympto-adapter'
-import { normalizeToScale } from './y-axis'
+import { normalizeToScale } from '../helpers/chart'
 
 export default function () {
   const cycle = {
diff --git a/components/chart/styles.js b/components/chart/styles.js
index d2a95d70367f227c0d1257a9caa30de3d0fec054..dc3a69be97429e7cdf93b590ca0c01a28003e234 100644
--- a/components/chart/styles.js
+++ b/components/chart/styles.js
@@ -11,6 +11,19 @@ const gridLineWidthVertical = 0.6
 const gridLineWidthHorizontal = 0.3
 const numberLabelFontSize = 13
 
+const redColor = '#c3000d'
+const violetColor = '#7689a9'
+const shadesOfViolet = ['#e3e7ed', '#c8cfdc', '#acb8cb', '#91a0ba', violetColor] // light to dark
+const yellowColor = '#dbb40c'
+const shadesOfYellow = ['#f0e19d', '#e9d26d', '#e2c33c', yellowColor] // light to dark
+const magentaColor = '#6f2565'
+const shadesOfMagenta = ['#a87ca2', '#8b5083', magentaColor] // light to dark
+const pinkColor = '#9e346c'
+const shadesOfPink = ['#c485a6', '#b15c89', pinkColor] // light to dark
+const lightGreenColor = '#bccd67'
+const orangeColor = '#bc6642'
+const mintColor = '#6ca299'
+
 const styles = {
   curve: {
     stroke: colorTemperature,
@@ -48,39 +61,44 @@ const styles = {
       width: gridLineWidthVertical,
     }
   },
-  symptomIcon: {
+  symptomDot: {
     width: 12,
     height: 12,
     borderRadius: 50,
   },
-  iconShades: {
-    'bleeding': shadesOfRed,
-    'mucus': [
-      '#e3e7ed',
-      '#c8cfdc',
-      '#acb8cb',
-      '#91a0ba',
-      '#7689a9'
-    ],
-    'cervix': [
-      '#f0e19d',
-      '#e9d26d',
-      '#e2c33c',
-      '#dbb40c',
-    ],
-    'sex': [
-      '#a87ca2',
-      '#8b5083',
-      '#6f2565',
-    ],
-    'desire': [
-      '#c485a6',
-      '#b15c89',
-      '#9e346c',
-    ],
-    'pain': ['#bccd67'],
-    'mood': ['#bc6642'],
-    'note': ['#6ca299']
+  iconColors: {
+    'bleeding': {
+      color: redColor,
+      shades: shadesOfRed,
+    },
+    'mucus': {
+      color: violetColor,
+      shades: shadesOfViolet,
+    },
+    'cervix': {
+      color: yellowColor,
+      shades: shadesOfYellow,
+    },
+    'sex': {
+      color: magentaColor,
+      shades: shadesOfMagenta,
+    },
+    'desire': {
+      color: pinkColor,
+      shades: shadesOfPink,
+    },
+    'pain': {
+      color: lightGreenColor,
+      shades: [lightGreenColor],
+    },
+    'mood': {
+      color: orangeColor,
+      shades: [orangeColor],
+    },
+    'note': {
+      color: mintColor,
+      shades: [mintColor],
+    },
   },
   yAxis: {
     width: 27,
@@ -109,6 +127,18 @@ const styles = {
       fontWeight: '100',
     }
   },
+  symptomIcon: {
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+  chartLegend: {
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+  boldTick: {
+    fontWeight: 'bold',
+    fontSize: 11,
+  },
   horizontalGrid: {
     position:'absolute',
     borderStyle: 'solid',
diff --git a/components/chart/symptom-cell.js b/components/chart/symptom-cell.js
new file mode 100644
index 0000000000000000000000000000000000000000..fa760422235383ed9a1ed753d549f5482f470a36
--- /dev/null
+++ b/components/chart/symptom-cell.js
@@ -0,0 +1,52 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { View } from 'react-native'
+
+import styles from './styles'
+
+const SymptomCell = ({
+  height,
+  symptom,
+  symptomValue,
+  isSymptomDataComplete
+}) => {
+
+  const shouldDrawDot = symptomValue !== false
+  const styleParent = [styles.symptomRow, { height }]
+  let styleChild
+
+  if (shouldDrawDot) {
+    const styleSymptom = styles.iconColors[symptom]
+    const symptomColor = styleSymptom.shades[symptomValue]
+
+    const isMucusOrCervix = (symptom === 'mucus') || (symptom === 'cervix')
+
+    const backgroundColor = (isMucusOrCervix && !isSymptomDataComplete) ?
+      'white' : symptomColor
+    const borderWidth = (isMucusOrCervix && !isSymptomDataComplete) ? 2 : 0
+    const borderColor = symptomColor
+    styleChild = [styles.symptomDot, {
+      backgroundColor,
+      borderColor,
+      borderWidth
+    }]
+  }
+
+  return (
+    <View style={styleParent} key={symptom}>
+      {shouldDrawDot && <View style={styleChild} />}
+    </View>
+  )
+}
+
+SymptomCell.propTypes = {
+  height: PropTypes.number,
+  symptom: PropTypes.string,
+  symptomValue: PropTypes.oneOfType([
+    PropTypes.bool,
+    PropTypes.number,
+  ]),
+  isSymptomDataComplete: PropTypes.bool,
+}
+
+export default SymptomCell
diff --git a/components/chart/symptom-icon.js b/components/chart/symptom-icon.js
new file mode 100644
index 0000000000000000000000000000000000000000..3236c3b044009c998bff77c8f065beb769aa20e2
--- /dev/null
+++ b/components/chart/symptom-icon.js
@@ -0,0 +1,26 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { View } from 'react-native'
+
+import DripIcon from '../../assets/drip-icons'
+
+import styles from './styles'
+
+const SymptomIcon = ({ symptom, height }) => {
+  return (
+    <View style={styles.symptomIcon} width={styles.yAxis.width} height={height}>
+      <DripIcon
+        size={16}
+        name={`drip-icon-${symptom}`}
+        color={styles.iconColors[symptom].color}
+      />
+    </View>
+  )
+}
+
+SymptomIcon.propTypes = {
+  height: PropTypes.number,
+  symptom: PropTypes.string,
+}
+
+export default SymptomIcon
diff --git a/components/chart/tick-list.js b/components/chart/tick-list.js
new file mode 100644
index 0000000000000000000000000000000000000000..16fba0af4065148a95ae0d743748d25e15e42cf7
--- /dev/null
+++ b/components/chart/tick-list.js
@@ -0,0 +1,34 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { View } from 'react-native'
+
+import Tick from './tick'
+
+import { getTickList } from '../helpers/chart'
+
+import styles from './styles'
+
+const TickList = ({ height }) => {
+  return (
+    <View style={[styles.yAxis, { height }]}>{
+      getTickList(height)
+        .map(({ label, position, isBold, shouldShowLabel}) => {
+          return (
+            <Tick
+              key={label}
+              yPosition={position}
+              isBold={isBold}
+              shouldShowLabel={shouldShowLabel}
+              label={label}
+            />
+          )
+        })
+    }</View>
+  )
+}
+
+TickList.propTypes = {
+  height: PropTypes.number,
+}
+
+export default TickList
diff --git a/components/chart/tick.js b/components/chart/tick.js
new file mode 100644
index 0000000000000000000000000000000000000000..173cfbe6036f47a1005b3fe6f9fa8f88cd3f6a40
--- /dev/null
+++ b/components/chart/tick.js
@@ -0,0 +1,29 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+
+import AppText from '../app-text'
+
+import styles from './styles'
+
+const Tick = ({ yPosition, isBold, shouldShowLabel, label }) => {
+  // this eyeballing is sadly necessary because RN does not
+  // support percentage values for transforms, which we'd need
+  // to reliably place the label vertically centered to the grid
+  const topPosition = yPosition - 8
+  const style = [
+    styles.yAxisLabels.tempScale,
+    {top: topPosition},
+    isBold && styles.boldTick
+  ]
+
+  return <AppText style={style}>{shouldShowLabel && label}</AppText>
+}
+
+Tick.propTypes = {
+  yPosition: PropTypes.number,
+  isBold: PropTypes.bool,
+  shouldShowLabel: PropTypes.bool,
+  label: PropTypes.string,
+}
+
+export default Tick
diff --git a/components/chart/y-axis.js b/components/chart/y-axis.js
index 1f337368db7253856d74a2bdd44b529000070650..acd3ccf75e8b3594cf096997ae54cc918bd69742 100644
--- a/components/chart/y-axis.js
+++ b/components/chart/y-axis.js
@@ -1,75 +1,37 @@
 import React from 'react'
+import PropTypes from 'prop-types'
 import { View } from 'react-native'
-import config from '../../config'
-import styles from './styles'
-import { scaleObservable, unitObservable } from '../../local-storage'
-import AppText from '../app-text'
-
-export function makeYAxisLabels(columnHeight) {
-  const units = unitObservable.value
-  const scaleMax = scaleObservable.value.max
-  const style = styles.yAxisLabels.tempScale
 
-  return getTickPositions(columnHeight).map((y, i) => {
-    const tick = scaleMax - i * units
-    const tickLabel = tick * 10 % 10 ? tick.toString() : tick.toString() + '.0'
-    let showTick
-    let tickBold
-    if (units === 0.1) {
-      showTick =  (tick * 10 % 2) ? false : true
-      tickBold = tick * 10 % 5 ? {} : {fontWeight: 'bold', fontSize: 11}
-    } else {
-      showTick =  (tick * 10 % 5) ? false : true
-      tickBold = tick * 10 % 10 ? {} : {fontWeight: 'bold', fontSize: 11}
-    }
-    // this eyeballing is sadly necessary because RN does not
-    // support percentage values for transforms, which we'd need
-    // to reliably place the label vertically centered to the grid
-    return (
-      <AppText
-        style={[style, {top: y - 8}, tickBold]}
-        key={i}>
-        {showTick && tickLabel}
-      </AppText>
-    )
-  })
-}
+import SymptomIcon from './symptom-icon'
+import TickList from './tick-list'
+import ChartLegend from './chart-legend'
 
-export function makeHorizontalGrid(columnHeight, symptomRowHeight) {
-  return getTickPositions(columnHeight).map(tick => {
-    return (
-      <View
-        top={tick + symptomRowHeight}
-        {...styles.horizontalGrid}
-        key={tick}
-      />
-    )
-  })
-}
+import styles from './styles'
 
-function getTickPositions(columnHeight) {
-  const units = unitObservable.value
-  const scaleMin = scaleObservable.value.min
-  const scaleMax = scaleObservable.value.max
-  const numberOfTicks = (scaleMax - scaleMin) * (1 / units) + 1
-  const tickDistance = 1 / (numberOfTicks - 1)
-  const tickPositions = []
-  for (let i = 0; i < numberOfTicks; i++) {
-    const position = getAbsoluteValue(tickDistance * i, columnHeight)
-    tickPositions.push(position)
-  }
-  return tickPositions
+const YAxis = ({ height, symptomsToDisplay, symptomsSectionHeight }) => {
+  const symptomIconHeight = symptomsSectionHeight / symptomsToDisplay.length
+  return (
+    <View>
+      <View style={[styles.yAxis, {height: symptomsSectionHeight}]}>
+        {symptomsToDisplay.map(symptom => (
+          <SymptomIcon
+            key={symptom}
+            symptom={symptom}
+            height={symptomIconHeight}
+          />
+        )
+        )}
+      </View>
+      <TickList height={height} />
+      <ChartLegend />
+    </View>
+  )
 }
 
-export function normalizeToScale(temp, columnHeight) {
-  const scale = scaleObservable.value
-  const valueRelativeToScale = (scale.max - temp) / (scale.max - scale.min)
-  return getAbsoluteValue(valueRelativeToScale, columnHeight)
+YAxis.propTypes = {
+  height: PropTypes.number,
+  symptomsToDisplay: PropTypes.array,
+  symptomsSectionHeight: PropTypes.number,
 }
 
-function getAbsoluteValue(relative, columnHeight) {
-  // we add some height to have some breathing room
-  const verticalPadding = columnHeight * config.temperatureScale.verticalPadding
-  const scaleHeight = columnHeight - 2 * verticalPadding
-  return scaleHeight * relative + verticalPadding
-}
\ No newline at end of file
+export default YAxis
diff --git a/components/helpers/chart.js b/components/helpers/chart.js
new file mode 100644
index 0000000000000000000000000000000000000000..24a563cb1ab291bd0606a9b1ff813293f2d12fde
--- /dev/null
+++ b/components/helpers/chart.js
@@ -0,0 +1,67 @@
+import { scaleObservable, unitObservable } from '../../local-storage'
+import config from '../../config'
+
+export function normalizeToScale(temp, columnHeight) {
+  const scale = scaleObservable.value
+  const valueRelativeToScale = (scale.max - temp) / (scale.max - scale.min)
+  return getAbsoluteValue(valueRelativeToScale, columnHeight)
+}
+
+function getAbsoluteValue(relative, columnHeight) {
+  // we add some height to have some breathing room
+  const verticalPadding = columnHeight * config.temperatureScale.verticalPadding
+  const scaleHeight = columnHeight - 2 * verticalPadding
+  return scaleHeight * relative + verticalPadding
+}
+
+export function getTickPositions(columnHeight) {
+  const units = unitObservable.value
+  const scaleMin = scaleObservable.value.min
+  const scaleMax = scaleObservable.value.max
+  const numberOfTicks = (scaleMax - scaleMin) * (1 / units) + 1
+  const tickDistance = 1 / (numberOfTicks - 1)
+  const tickPositions = []
+  for (let i = 0; i < numberOfTicks; i++) {
+    const position = getAbsoluteValue(tickDistance * i, columnHeight)
+    tickPositions.push(position)
+  }
+  return tickPositions
+}
+
+export function getTickList(columnHeight) {
+
+  const units = unitObservable.value
+  const scaleMax = scaleObservable.value.max
+
+  return getTickPositions(columnHeight).map((tickPosition, i) => {
+
+    const tick = scaleMax - i * units
+    let isBold, label, shouldShowLabel
+
+    if (Number.isInteger(tick)) {
+      isBold = true
+      label = tick.toString() + '.0'
+    } else {
+      isBold = false
+      label = tick.toString()
+    }
+
+    // when temp range <= 3, units === 0.1 we show temp values with step 0.2
+    // when temp range > 3, units === 0.5 we show temp values with step 0.5
+
+    if (units === 0.1) {
+      // show label with step 0.2
+      shouldShowLabel = !(tick * 10 % 2)
+    } else {
+      // show label with step 0.5
+      shouldShowLabel = !(tick * 10 % 5)
+    }
+
+    return {
+      position: tickPosition,
+      label,
+      isBold,
+      shouldShowLabel,
+    }
+  })
+}