diff --git a/app/assets/images/error_icon.png b/app/assets/images/error_icon.png
new file mode 100644
index 0000000..f15d38a
Binary files /dev/null and b/app/assets/images/error_icon.png differ
diff --git a/app/assets/images/green_check.png b/app/assets/images/green_check.png
new file mode 100644
index 0000000..51df71e
Binary files /dev/null and b/app/assets/images/green_check.png differ
diff --git a/app/assets/images/sync_icon.png b/app/assets/images/sync_icon.png
new file mode 100644
index 0000000..82c6359
Binary files /dev/null and b/app/assets/images/sync_icon.png differ
diff --git a/app/components/header.js b/app/components/header.js
index 4dd2d84..5c2a085 100644
--- a/app/components/header.js
+++ b/app/components/header.js
@@ -6,6 +6,8 @@ import styled from 'styled-components';
import { ZcashLogo } from './zcash-logo';
import { TextComponent } from './text';
import { Divider } from './divider';
+import { RowComponent } from './row';
+import { StatusPill } from './status-pill';
const Wrapper = styled.div`
height: ${props => props.theme.headerHeight};
@@ -38,6 +40,12 @@ const TitleWrapper = styled.div`
padding-right: ${props => props.theme.layoutPaddingRight};
`;
+const TitleRow = styled(RowComponent)`
+ align-items: center;
+ justify-content: space-between;
+ width: 100%;
+`;
+
const Title = styled(TextComponent)`
font-size: ${props => `${props.theme.fontSize.large}em`};
margin-top: 10px;
@@ -57,7 +65,10 @@ export const HeaderComponent = ({ title }: Props) => (
-
+
+
+
+
diff --git a/app/components/status-pill.js b/app/components/status-pill.js
new file mode 100644
index 0000000..d4c8e53
--- /dev/null
+++ b/app/components/status-pill.js
@@ -0,0 +1,112 @@
+// @flow
+import React, { Component } from 'react';
+import styled, { keyframes } from 'styled-components';
+import eres from 'eres';
+
+import { TextComponent } from './text';
+
+import rpc from '../../services/api';
+
+import readyIcon from '../assets/images/green_check.png';
+import syncIcon from '../assets/images/sync_icon.png';
+import errorIcon from '../assets/images/error_icon.png';
+
+const rotate = keyframes`
+ from {
+ transform: rotate(0deg);
+ }
+
+ to {
+ transform: rotate(360deg);
+ }
+`;
+
+const Wrapper = styled.div`
+ align-items: center;
+ display: flex;
+ background-color: #000;
+ border-radius: 27px;
+ padding: 7px 13px;
+`;
+
+const Icon = styled.img`
+ width: 12px;
+ height: 12px;
+ margin-right: 8px;
+ animation: 2s linear infinite;
+ animation-name: ${props => (props.animated ? rotate : 'none')};
+`;
+
+const StatusPillLabel = styled(TextComponent)`
+ color: ${props => props.theme.colors.statusPillLabel};
+ font-weight: ${props => props.theme.fontWeight.bold};
+ text-transform: uppercase;
+`;
+
+type Props = {};
+
+type State = {
+ type: string,
+ icon: string,
+ progress: number,
+ isSynching: boolean,
+};
+
+export class StatusPill extends Component {
+ timer: ?IntervalID = null;
+
+ state = {
+ type: 'synching',
+ icon: syncIcon,
+ progress: 0,
+ isSynching: true,
+ };
+
+ componentDidMount() {
+ this.timer = setInterval(() => {
+ this.getBlockchainStatus();
+ }, 2000);
+ }
+
+ componentWillUnmount() {
+ if (this.timer) {
+ clearInterval(this.timer);
+ this.timer = null;
+ }
+ }
+
+ getBlockchainStatus = async () => {
+ const [blockchainErr, blockchaininfo] = await eres(
+ rpc.getblockchaininfo(),
+ );
+
+ const newProgress = blockchaininfo.verificationprogress * 100;
+
+ this.setState({
+ progress: newProgress,
+ ...(newProgress > 99.99 ? {
+ type: 'ready',
+ icon: readyIcon,
+ isSynching: false,
+ } : {}),
+ });
+
+ if (blockchainErr) {
+ this.setState(() => ({ type: 'error', icon: errorIcon }));
+ }
+ }
+
+ render() {
+ const {
+ type, icon, progress, isSynching,
+ } = this.state;
+ const showPercent = isSynching ? `(${progress.toFixed(2)}%)` : '';
+
+ return (
+
+
+
+
+ );
+ }
+}
diff --git a/app/components/status-pill.mdx b/app/components/status-pill.mdx
new file mode 100644
index 0000000..d013575
--- /dev/null
+++ b/app/components/status-pill.mdx
@@ -0,0 +1,22 @@
+---
+name: StatusPill
+---
+
+import { Playground, PropsTable } from 'docz'
+
+import { StatusPill } from './status-pill.js'
+import { DoczWrapper } from '../theme.js'
+
+# StatusPill
+
+## Properties
+
+
+
+## Basic Usage
+
+
+
+ {() => }
+
+
diff --git a/app/theme.js b/app/theme.js
index 1bafe92..28ea0f0 100644
--- a/app/theme.js
+++ b/app/theme.js
@@ -24,6 +24,7 @@ const transactionReceived = '#6AEAC0';
const transactionsDate = '#777777';
const transactionsItemHovered = '#222222';
const selectButtonShadow = 'rgba(238,201,76,0.65)';
+const statusPillLabel = '#727272';
const transactionsDetailsLabel = transactionsDate;
const appTheme = {
@@ -68,6 +69,7 @@ const appTheme = {
inputBackground: brandOne,
selectButtonShadow,
transactionsDetailsLabel,
+ statusPillLabel,
},
sidebarWidth: '180px',
headerHeight: '60px',