summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authoranderklander <anderklander@gmail.com>2018-02-06 13:06:42 +0100
committeranderklander <anderklander@gmail.com>2018-02-15 15:58:38 +0100
commit6efe0f6a44512c2a1ac51109ea498f1df7960ee5 (patch)
treeb182bdb0168ff3f833ba5a657bdef18452c13ccb
parentc6d4b3a2370fa6feeaaf33f0425127753e93039e (diff)
downloadmullvadvpn-6efe0f6a44512c2a1ac51109ea498f1df7960ee5.tar.xz
mullvadvpn-6efe0f6a44512c2a1ac51109ea498f1df7960ee5.zip
Common button component
-rw-r--r--app/components/Settings.js103
-rw-r--r--app/components/SettingsStyles.js27
-rw-r--r--app/components/styled/CellButton.js95
-rw-r--r--app/components/styled/index.js4
-rw-r--r--test/components/Settings.spec.js6
5 files changed, 155 insertions, 80 deletions
diff --git a/app/components/Settings.js b/app/components/Settings.js
index 4022054acd..7d27371ad4 100644
--- a/app/components/Settings.js
+++ b/app/components/Settings.js
@@ -2,7 +2,7 @@
import moment from 'moment';
import React from 'react';
import { Component, Text, View } from 'reactxp';
-import { Button } from './styled';
+import { Button, CellButton } from './styled';
import { Layout, Container, Header } from './Layout';
import CustomScrollbars from './CustomScrollbars';
import styles from './SettingsStyles';
@@ -81,40 +81,48 @@ export default class Settings extends Component {
return <View>
<View style={styles.settings_account} testName='settings__account'>
- <Button onPress={ this.props.onViewAccount } testName='settings__view_account'>
- <View style={styles.settings__cell}>
- <Text style={styles.settings__cell_label}>Account</Text>
- {isOutOfTime ? (
- <Text style={styles.settings__account_paid_until_label__error} testName='settings__account_paid_until_label'>OUT OF TIME</Text>
- ) : (
- <Text style={styles.settings__cell_subtext} testName='settings__account_paid_until_label'>{formattedExpiry}</Text>
- )}
- <Img style={styles.settings__cell_disclosure} source='icon-chevron' tintColor='currentColor'/>
- </View>
- </Button>
+ {isOutOfTime ? (
+ <CellButton onPress={ this.props.onViewAccount }
+ text='Account'
+ testName='settings__account_paid_until_label'
+ subtext='OUT OF TIME'
+ subtextStyle={ styles.settings__account_paid_until_label__error }
+ icon='icon-chevron'
+ iconStyle={styles.settings__icon_chevron}
+ tintColor='currentColor'/>
+ ) : (
+ <CellButton onPress={ this.props.onViewAccount }
+ text='Account'
+ testName='settings__account_paid_until_label'
+ subtext={ formattedExpiry }
+ subtextStyle={ styles.settings__account_paid_until_label }
+ icon='icon-chevron'
+ iconStyle={styles.settings__icon_chevron}
+ tintColor='currentColor'/>
+ )}
</View>
- <ButtonCell onPress={ this.props.onViewPreferences } testName='settings__preferences'>
- <Text style={styles.settings__cell_label}>Preferences</Text>
- <Img style={styles.settings__cell_disclosure} source='icon-chevron' tintColor='currentColor' />
- </ButtonCell>
-
- <ButtonCell onPress={ this.props.onViewAdvancedSettings } testName='settings__advanced'>
- <Text style={styles.settings__cell_label}>Advanced</Text>
- <Img style={styles.settings__cell_disclosure} source='icon-chevron' tintColor='currentColor'/>
- </ButtonCell>
+ <CellButton onPress={ this.props.onViewPreferences }
+ testName='settings__preferences'
+ text='Preferences'
+ icon='icon-chevron'
+ tintColor='currentColor'/>
+ <CellButton onPress={ this.props.onViewAdvancedSettings }
+ testName='settings__advanced'
+ text='Advanced'
+ icon='icon-chevron'
+ tintColor='currentColor'/>
</View>;
}
_renderMiddleButtons() {
- return <View>
- <ButtonCell onPress={ this.props.onExternalLink.bind(this, 'download') } testName='settings__version'>
- <Text style={styles.settings__cell_label}>App version</Text>
- <Text style={styles.settings__cell_subtext}>{this._formattedVersion()}</Text>
- <Img style={styles.settings__cell_icon} source='icon-extLink' tintColor='currentColor'/>
- </ButtonCell>
- </View>;
+ return <CellButton onPress={ this.props.onExternalLink.bind(this, 'download') }
+ testName='settings__version'
+ text='App version'
+ subtext={this._formattedVersion()}
+ icon='icon-extLink'
+ tintColor='currentColor'/>;
}
_formattedVersion() {
@@ -128,20 +136,24 @@ export default class Settings extends Component {
_renderBottomButtons() {
return <View>
- <ButtonCell onPress={ this.props.onExternalLink.bind(this, 'faq') } testName='settings__external_link'>
- <Text style={styles.settings__cell_label}>FAQs</Text>
- <Img style={styles.settings__cell_icon} source='icon-extLink' tintColor='currentColor'/>
- </ButtonCell>
+ <CellButton onPress={ this.props.onExternalLink.bind(this, 'faq') }
+ testName='settings__external_link'
+ text='FAQs'
+ icon='icon-extLink'
+ tintColor='currentColor'/>
- <ButtonCell onPress={ this.props.onExternalLink.bind(this, 'guides') } testName='settings__external_link'>
- <Text style={styles.settings__cell_label}>Guides</Text>
- <Img style={styles.settings__cell_icon} source='icon-extLink' tintColor='currentColor'/>
- </ButtonCell>
+ <CellButton onPress={ this.props.onExternalLink.bind(this, 'guides') }
+ testName='settings__external_link'
+ text='Guides'
+ icon='icon-extLink'
+ tintColor='currentColor'/>
- <ButtonCell onPress={ this.props.onViewSupport } testName='settings__view_support'>
- <Text style={styles.settings__cell_label}>Contact support</Text>
- <Img style={styles.settings__cell_disclosure} source='icon-chevron' tintColor='currentColor'/>
- </ButtonCell>
+ <CellButton onPress={ this.props.onViewSupport }
+ testName='settings__view_support'
+ text='Contact support'
+ icon='icon-chevron'
+ iconStyle={styles.settings__icon_chevron}
+ tintColor='currentColor'/>
</View>;
}
@@ -152,13 +164,4 @@ export default class Settings extends Component {
</Button>
</View>;
}
-}
-
-function ButtonCell(props) {
- const { children, ...rest } = props;
- return <Button { ...rest } >
- <View style={styles.settings__cell}>
- { children }
- </View>
- </Button>;
-}
+} \ No newline at end of file
diff --git a/app/components/SettingsStyles.js b/app/components/SettingsStyles.js
index d37703a8fe..734d73ad90 100644
--- a/app/components/SettingsStyles.js
+++ b/app/components/SettingsStyles.js
@@ -44,19 +44,7 @@ export default Object.assign(createViewStyles({
flex: 0,
opacity: 0.6,
},
- settings__cell:{
- backgroundColor: 'rgba(41,71,115,1)',
- paddingTop: 15,
- paddingBottom: 15,
- paddingLeft: 24,
- paddingRight: 24,
- marginBottom: 1,
- flex: 1,
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'space-between'
- },
- settings__cell_disclosure:{
+ settings__icon_chevron:{
marginLeft: 8,
color: 'rgba(255, 255, 255, 0.8)',
width: 7,
@@ -66,19 +54,6 @@ export default Object.assign(createViewStyles({
height: 24,
flex: 0
},
- settings__cell__active_hover:{
- backgroundColor: 'rgba(41,71,115,0.9)'
- },
- settings__cell_icon:{
- marginLeft: 8,
- width: 16,
- height: 16,
- flexGrow: 0,
- flexShrink: 0,
- flexBasis: 'auto',
- alignItems: 'flex-end',
- color: 'rgba(255, 255, 255, 0.8)',
- },
settings__footer_button:{
backgroundColor: 'rgba(208,2,27,1)',
paddingTop: 7,
diff --git a/app/components/styled/CellButton.js b/app/components/styled/CellButton.js
new file mode 100644
index 0000000000..b74f0cdfb0
--- /dev/null
+++ b/app/components/styled/CellButton.js
@@ -0,0 +1,95 @@
+// @flow
+import React from 'react';
+import { Text, Component } from 'reactxp';
+import { Button } from './Button';
+import Img from '../Img';
+
+import { createViewStyles, createTextStyles } from '../../lib/styles';
+
+const styles = {
+ ...createViewStyles({
+ cell:{
+ backgroundColor: 'rgba(41,71,115,1)',
+ paddingTop: 15,
+ paddingBottom: 15,
+ paddingLeft: 24,
+ paddingRight: 24,
+ marginBottom: 1,
+ flex: 1,
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'space-between'
+ },
+ hover:{
+ backgroundColor: 'rgba(41,71,115,0.9)'
+ },
+ icon:{
+ marginLeft: 8,
+ width: 16,
+ height: 16,
+ flexGrow: 0,
+ flexShrink: 0,
+ flexBasis: 'auto',
+ alignItems: 'flex-end',
+ color: 'rgba(255, 255, 255, 0.8)',
+ },
+ }),
+ ...createTextStyles({
+ label:{
+ fontFamily: 'DINPro',
+ fontSize: 20,
+ fontWeight: '900',
+ lineHeight: 26,
+ color: '#FFFFFF',
+ flexGrow: 1,
+ flexShrink: 0,
+ flexBasis: 'auto',
+ },
+ subtext:{
+ fontFamily: 'Open Sans',
+ fontSize: 13,
+ fontWeight: '800',
+ color: 'rgba(255, 255, 255, 0.8)',
+ flexGrow: 0,
+ textAlign: 'right',
+ },
+ })
+};
+
+export default class CellButton extends Component {
+ props: {
+ icon?: string,
+ iconStyle?: string,
+ hoverStyle?: string,
+ subtextStyle?: string,
+ text: string,
+ subtext?: string,
+ tintColor?: string,
+ onPress?: () => void,
+ style?: string
+ };
+
+ state = { hovered: false };
+
+ render() {
+ const { style, tintColor, hoverStyle, text, subtext, subtextStyle, icon, iconStyle, onPress, ...otherProps } = this.props;
+
+ return (
+ <Button style={[ styles.cell, style, this.state.hovered ? [styles.hover, hoverStyle] : null ]}
+ onPress={ onPress }
+ onHoverStart={() => this.setState({ hovered: true })}
+ onHoverEnd={() => this.setState({ hovered: false })}
+ {...otherProps}>
+
+ <Text style={ styles.label }>{ text }</Text>
+
+ { subtext ? <Text style={[ styles.subtext, subtextStyle ]}>{ subtext }</Text> : null }
+
+ <Img style={[ styles.icon, iconStyle ]}
+ source={ icon }
+ tintColor={ tintColor }/>
+
+ </Button>
+ );
+ }
+}
diff --git a/app/components/styled/index.js b/app/components/styled/index.js
index 6699594f18..0aeddca65e 100644
--- a/app/components/styled/index.js
+++ b/app/components/styled/index.js
@@ -1,7 +1,9 @@
// @flow
import { Button } from './Button';
+import CellButton from './CellButton';
export {
- Button
+ Button,
+ CellButton,
};
diff --git a/test/components/Settings.spec.js b/test/components/Settings.spec.js
index fc6b73f17c..d8d30ab4df 100644
--- a/test/components/Settings.spec.js
+++ b/test/components/Settings.spec.js
@@ -109,13 +109,13 @@ describe('components/Settings', () => {
it('should show out-of-time message for unpaid account', () => {
const props = makeProps(unpaidAccountState, settingsState);
const component = getComponent(render(props), 'settings__account_paid_until_label');
- expect(component.children().text()).to.equal('OUT OF TIME');
+ expect(component.prop('subtext')).to.equal('OUT OF TIME');
});
it('should hide out-of-time message for paid account', () => {
const props = makeProps(loggedInAccountState, settingsState);
const component = getComponent(render(props), 'settings__account_paid_until_label');
- expect(component.children().text()).not.to.equal('OUT OF TIME');
+ expect(component.prop('subtext')).not.to.equal('OUT OF TIME');
});
it('should call close callback', (done) => {
@@ -138,7 +138,7 @@ describe('components/Settings', () => {
const props = makeProps(loggedInAccountState, settingsState, {
onViewAccount: () => done()
});
- const component = getComponent(render(props), 'settings__view_account');
+ const component = getComponent(render(props), 'settings__account_paid_until_label');
click(component);
});