diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2018-02-16 11:19:36 +0100 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2018-02-16 11:19:36 +0100 |
| commit | 5f15a7bec3e2a50162e54488c5a3f519b9553586 (patch) | |
| tree | 9d61e6b951139dfb061c1898b7eb0aab4c5e3e73 /app/components | |
| parent | c6d4b3a2370fa6feeaaf33f0425127753e93039e (diff) | |
| parent | 89eeb129f065d92a82393db2deca58c0c0f2ff38 (diff) | |
| download | mullvadvpn-5f15a7bec3e2a50162e54488c5a3f519b9553586.tar.xz mullvadvpn-5f15a7bec3e2a50162e54488c5a3f519b9553586.zip | |
Merge branch 'buttons'
Diffstat (limited to 'app/components')
| -rw-r--r-- | app/components/Account.css | 98 | ||||
| -rw-r--r-- | app/components/Account.js | 84 | ||||
| -rw-r--r-- | app/components/AccountStyles.js | 109 | ||||
| -rw-r--r-- | app/components/HeaderBarStyles.js | 11 | ||||
| -rw-r--r-- | app/components/Img.android.js | 17 | ||||
| -rw-r--r-- | app/components/Img.js | 3 | ||||
| -rw-r--r-- | app/components/PreferencesStyles.js | 16 | ||||
| -rw-r--r-- | app/components/Settings.js | 111 | ||||
| -rw-r--r-- | app/components/SettingsStyles.js | 98 | ||||
| -rw-r--r-- | app/components/Support.js | 61 | ||||
| -rw-r--r-- | app/components/SupportStyles.js | 132 | ||||
| -rw-r--r-- | app/components/styled/AppButton.js | 136 | ||||
| -rw-r--r-- | app/components/styled/CellButton.js | 116 | ||||
| -rw-r--r-- | app/components/styled/index.js | 11 |
14 files changed, 581 insertions, 422 deletions
diff --git a/app/components/Account.css b/app/components/Account.css deleted file mode 100644 index 2f450e3828..0000000000 --- a/app/components/Account.css +++ /dev/null @@ -1,98 +0,0 @@ -.account { - background: #192E45; - height: 100%; -} - -.account__container { - display: flex; - flex-direction: column; - height: 100%; -} - -.account__header { - flex: 0 0 auto; - padding: 40px 24px 24px; - position: relative; /* anchor for close button */ -} - -.account__close { - position: absolute; - display: flex; - align-items: center; - border: 0; - padding: 0; - margin: 0; - top: 24px; - left: 12px; - z-index: 1; /* part of .account__container covers the button */ -} - -.account__close-icon { - opacity: 0.6; - margin-right: 8px; -} - -.account__close-title { - font-family: "Open Sans"; - font-size: 13px; - font-weight: 600; - color: rgba(255, 255, 255, 0.6); -} - -.account__title { - font-family: DINPro; - font-size: 32px; - font-weight: 900; - line-height: 40px; - color: #FFFFFF; -} - -.account__content { - flex: 1 1 auto; - display: flex; - flex-direction: column; - justify-content: space-between; -} - -.account__main { - margin-bottom: 24px; -} - -.account__footer { - padding: 24px; -} - -.account__row { - padding: 0 24px; -} - -.account__row + .account__row { - margin-top: 24px; -} - -.account__row-label { - font-family: "Open Sans"; - font-size: 13px; - font-weight: 600; - color: rgba(255, 255, 255, 0.8); - margin-bottom: 8px; -} - -.account__row-value { - font-family: "Open Sans"; - font-size: 16px; - font-weight: 800; - color: rgba(255, 255, 255, 0.8); -} - -.account__row-value--error { - color: #d0021b; -} - -.account__footer .button + .button { - margin-top: 24px; -} - -.account__id { - user-select: text; -} diff --git a/app/components/Account.js b/app/components/Account.js index 47c11a622c..afa36fe31a 100644 --- a/app/components/Account.js +++ b/app/components/Account.js @@ -1,9 +1,12 @@ // @flow import moment from 'moment'; -import React, { Component } from 'react'; -import { Layout, Container, Header } from './Layout'; +import React from 'react'; +import { Component, Text, View } from 'reactxp'; +import { Button, RedButton, GreenButton, Label } from './styled'; +import { Layout, Container } from './Layout'; +import styles from './AccountStyles'; +import Img from './Img'; import { formatAccount } from '../lib/formatters'; -import ExternalLinkSVG from '../assets/images/icon-extLink.svg'; import type { AccountReduxState } from '../redux/account/reducers'; @@ -17,7 +20,7 @@ export type AccountProps = { export default class Account extends Component { props: AccountProps; - render(): React.Element<*> { + render() { const expiry = moment(this.props.account.expiry); const formattedAccountToken = formatAccount(this.props.account.accountToken || ''); const formattedExpiry = expiry.format('hA, D MMMM YYYY').toUpperCase(); @@ -25,48 +28,57 @@ export default class Account extends Component { return ( <Layout> - <Header hidden={ true } style={ 'defaultDark' } /> <Container> - <div className="account"> - <div className="account__close" onClick={ this.props.onClose }> - <img className="account__close-icon" src="./assets/images/icon-back.svg" /> - <span className="account__close-title">Settings</span> - </div> - <div className="account__container"> + <View style={styles.account}> + <Button style={styles.account__close} + onPress={ this.props.onClose } + testName='account__close'> + <Img style={styles.account__close_icon} source="icon-back" /> + <Text style={styles.account__close_title}>Settings</Text> + </Button> + <View style={styles.account__container}> - <div className="account__header"> - <h2 className="account__title">Account</h2> - </div> + <View style={styles.account__header}> + <Text style={styles.account__title}>Account</Text> + </View> - <div className="account__content"> - <div className="account__main"> + <View style={styles.account__content}> + <View style={styles.account__main}> - <div className="account__row"> - <div className="account__row-label">Account ID</div> - <div className="account__row-value account__id">{ formattedAccountToken }</div> - </div> + <View style={styles.account__row}> + <Text style={styles.account__row_label}>Account ID</Text> + <Text style={styles.account__row_value}>{ formattedAccountToken }</Text> + </View> - <div className="account__row"> - <div className="account__row-label">Paid until</div> + <View style={styles.account__row}> + <Text style={styles.account__row_label}>Paid until</Text> { isOutOfTime ? - <div className="account__out-of-time account__row-value account__row-value--error">OUT OF TIME</div> + <Text style={styles.account__out_of_time} testName='account__out_of_time'>OUT OF TIME</Text> : - <div className="account__row-value">{ formattedExpiry }</div> + <Text style={styles.account__row_value}>{ formattedExpiry }</Text> } - </div> + </View> - <div className="account__footer"> - <button className="account__buymore button button--positive" onClick={ this.props.onBuyMore }> - <span className="button-label">Buy more time</span> - <ExternalLinkSVG className="button-icon button-icon--16" /> - </button> - <button className="account__logout button button--negative" onClick={ this.props.onLogout }>Logout</button> - </div> + <View style={styles.account__footer}> + <GreenButton + onPress={ this.props.onBuyMore } + text='Buy more credit' + icon='icon-extLink' + testName='account__buymore'> + <Label>Buy more credit</Label> + <Img source='icon-extLink' height='16' width='16' /> + </GreenButton> + <RedButton + onPress={ this.props.onLogout } + testName='account__logout'> + Log out + </RedButton> + </View> - </div> - </div> - </div> - </div> + </View> + </View> + </View> + </View> </Container> </Layout> ); diff --git a/app/components/AccountStyles.js b/app/components/AccountStyles.js new file mode 100644 index 0000000000..406215cd4f --- /dev/null +++ b/app/components/AccountStyles.js @@ -0,0 +1,109 @@ +// @flow + +import { createViewStyles, createTextStyles } from '../lib/styles'; +import { colors } from '../config'; + +export default { + ...createViewStyles({ + account: { + backgroundColor: colors.darkBlue, + height: '100%', + }, + account__container: { + flexDirection: 'column', + height: '100%', + paddingBottom: 48, + }, + account__header: { + flexGrow: 0, + flexShrink: 0, + flexBasis: 'auto', + paddingTop: 16, + paddingRight: 24, + paddingLeft: 24, + paddingBottom: 12, + }, + account__close: { + flexDirection: 'row', + alignItems: 'center', + alignSelf: 'flex-start', + marginLeft: 12, + marginTop: 24, + cursor: 'default', + }, + account__close_icon: { + width: 24, + height: 24, + opacity: 0.6, + marginRight: 8, + }, + account__scrollview: { + flexGrow: 1, + flexShrink: 1, + flexBasis: '100%', + }, + account__content: { + flexDirection: 'column', + flexGrow: 1, + flexShrink: 0, + flexBasis: 'auto', + }, + account__main: { + marginBottom: 24, + }, + account__row: { + paddingTop: 0, + paddingBottom: 0, + paddingLeft: 24, + paddingRight: 24, + marginTop: 24, + }, + account__footer: { + marginTop: 12, + }, + }), + ...createTextStyles({ + account__close_title: { + fontFamily: 'Open Sans', + fontSize: 13, + fontWeight: '600', + color: colors.white60, + }, + account__title: { + fontFamily: 'DINPro', + fontSize: 32, + fontWeight: '900', + lineHeight: 40, + color: colors.white, + }, + account__row_label: { + fontFamily: 'Open Sans', + fontSize: 13, + fontWeight: '600', + lineHeight: 20, + letterSpacing: -0.2, + color: colors.white60, + marginBottom: 9, + }, + account__row_value: { + fontFamily: 'Open Sans', + fontSize: 16, + fontWeight: '800', + color: colors.white, + }, + account__out_of_time: { + fontFamily: 'Open Sans', + fontSize: 16, + fontWeight: '800', + color: colors.red, + }, + account__footer_label: { + fontFamily: 'Open Sans', + fontSize: 13, + fontWeight: '600', + lineHeight: 20, + letterSpacing: -0.2, + color: colors.white80, + } + }) +};
\ No newline at end of file diff --git a/app/components/HeaderBarStyles.js b/app/components/HeaderBarStyles.js index c2d53a2036..a8569f2f81 100644 --- a/app/components/HeaderBarStyles.js +++ b/app/components/HeaderBarStyles.js @@ -1,5 +1,6 @@ // @flow import { createTextStyles, createViewStyles } from '../lib/styles'; +import { colors } from '../config'; export default { ...createViewStyles({ @@ -8,7 +9,7 @@ export default { paddingBottom: 12, paddingLeft: 12, paddingRight: 12, - backgroundColor: '#294D73', + backgroundColor: colors.blue, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', @@ -23,13 +24,13 @@ export default { paddingTop: 24, }, headerbar__style_defaultDark: { - backgroundColor: '#192E45', + backgroundColor: colors.darkBlue, }, headerbar__style_error: { - backgroundColor: '#D0021B', + backgroundColor: colors.red, }, headerbar__style_success: { - backgroundColor: '#44AD4D', + backgroundColor: colors.green, }, headerbar__container: { display: 'flex', @@ -55,7 +56,7 @@ export default { fontWeight: '900', lineHeight: 30, letterSpacing: -0.5, - color: 'rgba(255,255,255,0.6)', + color: colors.white60, marginLeft: 8, } }) diff --git a/app/components/Img.android.js b/app/components/Img.android.js index 436f805ccb..ced9d3f461 100644 --- a/app/components/Img.android.js +++ b/app/components/Img.android.js @@ -7,20 +7,25 @@ export default class Img extends Component { props: { source: string, style: Object, - tintColor?: string + tintColor?: string, + height?: number, + width?:number, }; render(){ - const { source, tintColor, style } = this.props; + const width = this.props.width || 7; + const height = this.props.height || 12; + const source = this.props.source || 'icon-chevron'; + const tintColor = this.props.tintColor || 'currentColor'; - if (tintColor === 'currentColor' && style) { - const { color: tint, ...otherStyles } = StyleSheet.flatten(style); + if (tintColor === 'currentColor' && this.props.style) { + const { color: tint, ...otherStyles } = StyleSheet.flatten(this.props.style); return( - <Image style={[ otherStyles, { tintColor: tint } ]} source={ source }/> + <Image style={[ otherStyles, { tintColor: tint, height: height, width: width } ]} source={ source }/> ); } else { return( - <Image style={ style } source={ source }/> + <Image style={[ this.props.style, { height: height, width: width } ]} source={ source }/> ); } } diff --git a/app/components/Img.js b/app/components/Img.js index 8c8244fc38..c4fb7637d5 100644 --- a/app/components/Img.js +++ b/app/components/Img.js @@ -9,7 +9,8 @@ export default class Img extends Component { }; render() { - const { source, tintColor, ...otherProps } = this.props; + const { source, ...otherProps } = this.props; + const tintColor = this.props.tintColor; const url = './assets/images/' + source + '.svg'; let image; diff --git a/app/components/PreferencesStyles.js b/app/components/PreferencesStyles.js index 24d0884605..7c1693e300 100644 --- a/app/components/PreferencesStyles.js +++ b/app/components/PreferencesStyles.js @@ -1,17 +1,17 @@ // @flow - import { createViewStyles, createTextStyles } from '../lib/styles'; +import { colors } from '../config'; export default { ...createViewStyles({ preferences: { - backgroundColor: '#192E45', + backgroundColor: colors.darkBlue, height: '100%', }, preferences__container: { display: 'flex', flexDirection: 'column', - height: '100%', + flex: 1, }, preferences__header: { flexGrow: 0, @@ -47,7 +47,7 @@ export default { flexBasis: 'auto', }, preferences__cell: { - backgroundColor: 'rgba(41,71,115,1)', + backgroundColor: colors.blue, flexDirection: 'row', alignItems: 'center', }, @@ -73,14 +73,14 @@ export default { fontFamily: 'Open Sans', fontSize: 13, fontWeight: '600', - color: 'rgba(255, 255, 255, 0.6)', + color: colors.white60, }, preferences__title: { fontFamily: 'DINPro', fontSize: 32, fontWeight: '900', lineHeight: 40, - color: '#fff', + color: colors.white }, preferences__cell_label: { fontFamily: 'DINPro', @@ -88,7 +88,7 @@ export default { fontWeight: '900', lineHeight: 26, letterSpacing: -0.2, - color: '#fff', + color: colors.white, }, preferences__cell_footer_label: { fontFamily: 'Open Sans', @@ -96,7 +96,7 @@ export default { fontWeight: '600', lineHeight: 20, letterSpacing: -0.2, - color: 'rgba(255,255,255,0.8)' + color: colors.white80 } }) };
\ No newline at end of file diff --git a/app/components/Settings.js b/app/components/Settings.js index 4022054acd..cae2503127 100644 --- a/app/components/Settings.js +++ b/app/components/Settings.js @@ -2,8 +2,8 @@ import moment from 'moment'; import React from 'react'; import { Component, Text, View } from 'reactxp'; -import { Button } from './styled'; -import { Layout, Container, Header } from './Layout'; +import { Button, CellButton, RedButton, Label, SubText} from './styled'; +import { Layout, Container } from './Layout'; import CustomScrollbars from './CustomScrollbars'; import styles from './SettingsStyles'; import Img from './Img'; @@ -31,7 +31,6 @@ export default class Settings extends Component { render() { return ( <Layout> - <Header hidden={ true } style={ 'defaultDark' } /> <Container> <View style={styles.settings}> <Button style={styles.settings__close} onPress={ this.props.onClose } testName='settings__close'> @@ -48,9 +47,7 @@ export default class Settings extends Component { <View style={styles.settings__content}> <View> { this._renderTopButtons() } - <View style={styles.settings__cell_spacer}/> { this._renderMiddleButtons() } - <View style={styles.settings__cell_spacer}/> { this._renderBottomButtons() } </View> { this._renderQuitButton() } @@ -81,39 +78,47 @@ 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 } + testName='settings__account_paid_until_button'> + <Label>Account</Label> + <SubText testName='settings__account_paid_until_subtext' style={styles.settings__account_paid_until_Label__error}>OUT OF TIME</SubText> + <Img height='12' width='7' source='icon-chevron' /> + </CellButton> + ) : ( + <CellButton onPress={ this.props.onViewAccount } + testName='settings__account_paid_until_button'> + <Label>Account</Label> + <SubText testName='settings__account_paid_until_subtext'>{ formattedExpiry }</SubText> + <Img height='12' width='7' source='icon-chevron' /> + </CellButton> + )} </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'> + <Label>Preferences</Label> + <Img height='12' width='7' source='icon-chevron' /> + </CellButton> + <CellButton onPress={ this.props.onViewAdvancedSettings } + testName='settings__advanced'> + <Label>Advanced</Label> + <Img height='12' width='7' source='icon-chevron' /> + </CellButton> + <View style={styles.settings__cell_spacer}/> </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> + <CellButton onPress={ this.props.onExternalLink.bind(this, 'download') } + testName='settings__version'> + <Label>App version</Label> + <SubText>{this._formattedVersion()}</SubText> + <Img height='16' width='16' source='icon-extLink' /> + </CellButton> + <View style={styles.settings__cell_spacer}/> </View>; } @@ -128,37 +133,33 @@ 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'> + <Label>FAQs</Label> + <Img height='16' width='16' source='icon-extLink' /> + </CellButton> - <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'> + <Label>Guides</Label> + <Img height='16' width='16' source='icon-extLink' /> + </CellButton> - <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'> + <Label>Contact support</Label> + <Img height='12' width='7' source='icon-chevron' /> + </CellButton> </View>; } _renderQuitButton() { return <View style={styles.settings__footer}> - <Button style={styles.settings__footer_button} onPress={this.props.onQuit} testName='settings__quit'> - <Text style={styles.settings__footer_button_label}>Quit app</Text> - </Button> + <RedButton + onPress={this.props.onQuit} + testName='settings__quit'> + <Label>Quit app</Label> + </RedButton> </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..81d72277a3 100644 --- a/app/components/SettingsStyles.js +++ b/app/components/SettingsStyles.js @@ -1,22 +1,23 @@ import { createViewStyles, createTextStyles } from '../lib/styles'; +import { colors } from '../config'; export default Object.assign(createViewStyles({ settings: { - backgroundColor: '#192E45', + backgroundColor: colors.darkBlue, height: '100%' }, settings__container:{ flexDirection: 'column', - height: '100%' + flex: 1 }, settings__header:{ flexGrow: 0, flexShrink: 0, flexBasis: 'auto', - paddingTop: 40, + paddingTop: 16, paddingRight: 24, paddingLeft: 24, - paddingBottom: 24, + paddingBottom: 16, }, settings__content: { flexDirection: 'column', @@ -29,13 +30,8 @@ export default Object.assign(createViewStyles({ flexBasis: '100%', }, settings__close: { - position: 'absolute', - top: 0, - left: 12, - borderWidth: 0, - padding: 0, - margin: 0, - zIndex: 1, /* part of .settings__close covers the button */ + marginLeft: 12, + marginTop: 24, cursor: 'default', }, settings__close_icon:{ @@ -44,55 +40,13 @@ 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:{ - marginLeft: 8, - color: 'rgba(255, 255, 255, 0.8)', - width: 7, - height: 12, - }, settings__cell_spacer:{ 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, - paddingLeft: 12, - paddingRight: 12, - paddingBottom: 9, - borderRadius: 4, - alignItems: 'center', - }, settings__footer: { - paddingTop: 24, - paddingLeft: 24, - paddingRight: 24, - paddingBottom: 24, + paddingTop: 16, + paddingBottom: 16, }, }), createTextStyles({ settings__title:{ @@ -100,39 +54,9 @@ export default Object.assign(createViewStyles({ fontSize: 32, fontWeight: '900', lineHeight: 40, - color: '#FFFFFF' - }, - settings__cell_label:{ - fontFamily: 'DINPro', - fontSize: 20, - fontWeight: '900', - lineHeight: 26, - color: '#FFFFFF', - flexGrow: 1, - flexShrink: 0, - flexBasis: 'auto', - }, - settings__footer_button_label:{ - fontFamily: 'DINPro', - fontSize: 20, - fontWeight: '900', - lineHeight: 26, - color: 'rgba(255,255,255,0.8)' - }, - settings__cell_subtext:{ - fontFamily: 'Open Sans', - fontSize: 13, - fontWeight: '800', - color: 'rgba(255, 255, 255, 0.8)', - flexGrow: 0, - textAlign: 'right', + color: colors.white }, settings__account_paid_until_label__error:{ - fontFamily: 'Open Sans', - fontSize: 13, - fontWeight: '800', - flexGrow: 0, - textAlign: 'right', - color: '#d0021b', + color: colors.red, }, })); diff --git a/app/components/Support.js b/app/components/Support.js index dc646bdb0e..80116bcc1b 100644 --- a/app/components/Support.js +++ b/app/components/Support.js @@ -1,7 +1,8 @@ // @flow import React from 'react'; -import { Component, Text, Button, View, TextInput } from 'reactxp'; -import { Layout, Container, Header } from './Layout'; +import { Component, Text, View, TextInput } from 'reactxp'; +import { Button, BlueButton, GreenButton, Label } from './styled'; +import { Layout, Container } from './Layout'; import styles from './SupportStyles'; import Img from './Img'; @@ -117,14 +118,11 @@ export default class Support extends Component { return ( <Layout> - <Header hidden={ true } style={ 'defaultDark' } /> <Container> <View style={styles.support}> <Button style={styles.support__close} onPress={ this.props.onClose } testName="support__close"> - <View style={styles.support__close}> - <Img style={styles.support__close_icon} source="icon-back" /> - <Text style={styles.support__close_title}>Settings</Text> - </View> + <Img style={styles.support__close_icon} source="icon-back" /> + <Text style={styles.support__close_title}>Settings</Text> </Button> <View style={styles.support__container}> @@ -193,24 +191,29 @@ export default class Support extends Component { <Text style={styles.support__no_email_warning}> You are about to send the problem report without a way for us to get back to you. If you want an answer to your report you will have to enter an email address. </Text> - <Button style={styles.support__form_send} disabled={ !this.validate() } onPress={ this.onSend } testName='support__send_logs'> - <Text style={styles.support__button_label}>Send anyway</Text> - </Button> + <GreenButton + disabled={ !this.validate() } + onPress={ this.onSend } + testName='support__send_logs'> + Send anyway + </GreenButton> </View>; } _renderActionButtons() { return [ - <Button key={1} onPress={ this.onViewLog } style={{'flex':1}} testName='support__view_logs'> - <View style={styles.support__form_view_logs}> - <View style={styles.support__open_icon}></View> - <Text style={styles.support__button_label}>View app logs</Text> - <Img source="icon-extLink" style={styles.support__open_icon} tintColor='currentColor'/> - </View> - </Button>, - <Button key={2} style={styles.support__form_send} disabled={ !this.validate() } onPress={ this.onSend } testName='support__send_logs'> - <Text style={styles.support__button_label}>Send</Text> - </Button> + <BlueButton key={1} + onPress={ this.onViewLog } + testName='support__view_logs'> + <Label>View app logs</Label> + <Img source='icon-extLink' height='16' width='16' /> + </BlueButton>, + <GreenButton key={2} + disabled={ !this.validate() } + onPress={ this.onSend } + testName='support__send_logs'> + Send + </GreenButton> ]; } @@ -275,16 +278,14 @@ export default class Support extends Component { </View> </View> <View style={styles.support__footer}> - <Button onPress={ () => this.setState({ sendState: 'INITIAL' }) }> - <View style={styles.support__form_edit_logs}> - <Text style={styles.support__button_label}>Edit message</Text> - </View> - </Button> - <Button onPress={ this.onSend }> - <View style={styles.support__form_send}> - <Text style={styles.support__button_label}>Try again</Text> - </View> - </Button> + <BlueButton onPress={ () => this.setState({ sendState: 'INITIAL' }) }> + Edit message + </BlueButton> + <GreenButton + onPress={ this.onSend } + testName='support__send_logs'> + Try again + </GreenButton> </View> </View>; } diff --git a/app/components/SupportStyles.js b/app/components/SupportStyles.js index f0b0df5c18..85eb693fee 100644 --- a/app/components/SupportStyles.js +++ b/app/components/SupportStyles.js @@ -1,14 +1,15 @@ import { createViewStyles, createTextStyles } from '../lib/styles'; +import { colors } from '../config'; export default Object.assign(createViewStyles({ support:{ - backgroundColor: '#192E45', + backgroundColor: colors.darkBlue, height: '100%', }, support__container:{ display: 'flex', flexDirection: 'column', - height: '100%', + flex: 1 }, support__header:{ flex: 0, @@ -16,10 +17,10 @@ export default Object.assign(createViewStyles({ paddingBottom: 12, paddingLeft: 24, paddingRight: 24, - overflow: 'visible', - position: 'relative' /* anchor for close button */ }, support__close:{ + paddingLeft: 12, + paddingTop: 24, flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-start', @@ -37,7 +38,6 @@ export default Object.assign(createViewStyles({ display: 'flex', flexDirection: 'column', justifyContent: 'space-between', - paddingBottom: 24, }, support__form:{ display: 'flex', @@ -46,17 +46,16 @@ export default Object.assign(createViewStyles({ }, support__form_row:{ paddingTop: 0, - paddingBottom: 0, - paddingLeft: 24, - paddingRight: 24, + paddingBottom: 8, + paddingLeft: 22, + paddingRight: 22, }, support__form_row_message:{ flex: 1, paddingTop: 0, - paddingBottom: 0, - paddingLeft: 24, - paddingRight: 24, - marginTop: 8, + paddingBottom: 8, + paddingLeft: 22, + paddingRight: 22, }, support__form_message_scroll_wrap:{ flex: 1, @@ -65,81 +64,29 @@ export default Object.assign(createViewStyles({ overflow: 'hidden', }, support__footer:{ - paddingTop: 1, - paddingRight: 24, - paddingLeft: 24, - paddingBottom: 24, - marginTop: 12, + paddingTop: 0, + paddingBottom: 16, display: 'flex', flexDirection: 'column', flex: 0, }, - support__form_view_logs:{ - backgroundColor: 'rgba(41,71,115,1)', - color: 'rgba(255,255,255,0.8)', - paddingTop: 7, - paddingLeft: 12, - paddingRight: 12, - paddingBottom: 9, - borderRadius: 4, - justifyContent: 'space-between', - alignItems: 'center', - flexDirection: 'row', - flex: 1, - }, - support__form_edit_logs:{ - backgroundColor: 'rgba(41,71,115,1)', - color: 'rgba(255,255,255,0.8)', - paddingTop: 7, - paddingLeft: 12, - paddingRight: 12, - paddingBottom: 9, - borderRadius: 4, - justifyContent: 'center', - alignItems: 'center', - flexDirection: 'row', - flex: 1, - }, - support__form_send:{ - backgroundColor: 'rgba(63,173,77,1)', - color: 'rgba(255,255,255,0.8)', - paddingTop: 7, - paddingLeft: 12, - paddingRight: 12, - paddingBottom: 9, - borderRadius: 4, - marginTop: 16, - justifyContent: 'space-between', - alignItems: 'center', - flex: 1, - }, support__status_icon:{ textAlign: 'center', marginBottom: 32, }, - support__open_icon:{ - color: 'rgba(255,255,255,0.8)', - marginLeft: 8, - width: 16, - height: 16, - flexGrow: 0, - flexShrink: 0, - flexBasis: 'auto', - alignItems: 'flex-end', - }, }), createTextStyles({ support__close_title:{ fontFamily: 'Open Sans', fontSize: 13, fontWeight: '600', - color: 'rgba(255, 255, 255, 0.6)', + color: colors.white60, }, support__title:{ fontFamily: 'DINPro', fontSize: 32, fontWeight: '900', lineHeight: 40, - color: '#FFFFFF', + color: colors.white, marginBottom: 16, }, support__subtitle:{ @@ -147,40 +94,40 @@ export default Object.assign(createViewStyles({ fontSize: 13, fontWeight: '600', overflow: 'visible', - color: 'rgba(255,255,255,0.8)', + color: colors.white80, lineHeight: 20, letterSpacing: -0.2, }, support__form_email:{ - width: '100%', + flex: 1, borderRadius: 4, overflow: 'hidden', - paddingTop: 10, - paddingLeft: 12, - paddingRight: 12, - paddingBottom: 12, + paddingTop: 14, + paddingLeft: 14, + paddingRight: 14, + paddingBottom: 14, fontFamily: 'Open Sans', fontSize: 13, fontWeight: '600', lineHeight: 26, - color: '#294D73', - backgroundColor: '#fff', + color: colors.blue, + backgroundColor: colors.white, }, support__form_message:{ - paddingTop: 10, - paddingLeft: 12, - paddingRight: 12, - paddingBottom: 10, + paddingTop: 14, + paddingLeft: 14, + paddingRight: 14, + paddingBottom: 14, fontFamily: 'Open Sans', fontSize: 13, fontWeight: '600', - color: '#294D73', - backgroundColor: '#fff', + color: colors.blue, + backgroundColor: colors.white, flex: 1, }, support__sent_email:{ fontWeight: '900', - color: 'white', + color: colors.white, }, support__status_security__secure:{ fontFamily: 'Open Sans', @@ -188,7 +135,7 @@ export default Object.assign(createViewStyles({ fontWeight: '800', lineHeight: 22, marginBottom: 4, - color: '#44AD4D', + color: colors.green, }, support__send_status:{ fontFamily: 'DINPro', @@ -197,22 +144,17 @@ export default Object.assign(createViewStyles({ maxHeight: 'calc(1.16em * 2)', overflow: 'visible', letterSpacing: -0.9, - color: '#FFFFFF', + color: colors.white, marginBottom: 4, }, - support__button_label:{ - fontFamily: 'DINPro', - fontSize: 20, - fontWeight: '900', - lineHeight: 26, - justifyContent: 'center', - alignItems: 'center', - }, support__no_email_warning: { fontFamily: 'Open Sans', fontSize: 13, lineHeight: 16, - - color: 'rgba(255,255,255,0.8)', + color: colors.white80, + paddingTop: 8, + paddingLeft: 24, + paddingRight: 24, + paddingBottom: 8, }, })); diff --git a/app/components/styled/AppButton.js b/app/components/styled/AppButton.js new file mode 100644 index 0000000000..60da8edb3c --- /dev/null +++ b/app/components/styled/AppButton.js @@ -0,0 +1,136 @@ +// @flow +import React from 'react'; +import { Text, Component } from 'reactxp'; +import { Button } from './Button'; +import { colors } from '../../config'; + +import { createViewStyles, createTextStyles } from '../../lib/styles'; + +const styles = { + ...createViewStyles({ + red:{ + backgroundColor: colors.red95, + }, + redHover: { + backgroundColor: colors.red, + }, + green:{ + backgroundColor: colors.green, + }, + greenHover:{ + backgroundColor: colors.green90, + }, + blue:{ + backgroundColor: colors.blue80, + }, + blueHover:{ + backgroundColor: colors.blue60, + }, + transparent:{ + backgroundColor: colors.white20, + }, + transparentHover:{ + backgroundColor: colors.white40, + }, + white80:{ + color: colors.white80, + }, + white: { + color: colors.white, + }, + icon:{ + position: 'absolute', + alignSelf: 'flex-end', + right: 8, + marginLeft: 8, + }, + common:{ + paddingTop: 9, + paddingLeft: 9, + paddingRight: 9, + paddingBottom: 9, + marginTop: 8, + marginBottom: 8, + marginLeft: 24, + marginRight: 24, + borderRadius: 4, + flex: 1, + flexDirection: 'column', + alignContent: 'center', + justifyContent: 'center', + }, + }), + ...createTextStyles({ + label:{ + alignSelf: 'center', + fontFamily: 'DINPro', + fontSize: 20, + fontWeight: '900', + lineHeight: 26, + flex: 1, + }, + }), +}; + +export class Label extends Text {} + +export default class BaseButton extends Component { + props: { + children: Array<React.Element<*>> | React.Element<*>, + disabled: boolean, + }; + + state = { hovered: false }; + + textStyle = () => this.state.hovered ? styles.white80 : styles.white; + iconStyle = () => this.state.hovered ? styles.white80 : styles.white; + backgroundStyle = () => this.state.hovered ? styles.white80 : styles.white; + + onHoverStart = () => !this.props.disabled ? this.setState({ hovered: true }) : null; + onHoverEnd = () => !this.props.disabled ? this.setState({ hovered: false }) : null; + render() { + const { children, ...otherProps } = this.props; + return ( + <Button style={[ styles.common, this.backgroundStyle() ]} + onHoverStart={this.onHoverStart} + onHoverEnd={this.onHoverEnd} + {...otherProps}> + { + React.Children.map(children, (node) => { + if (React.isValidElement(node)){ + let updatedProps = {}; + + if(node.type.name === 'Label') { + updatedProps = { style: [styles.label, this.textStyle()]}; + } + + if(node.type.name === 'Img') { + updatedProps = { tintColor:'currentColor', style: [styles.icon, this.iconStyle()]}; + } + + return React.cloneElement(node, updatedProps); + } else { + return <Label style={[styles.label, this.textStyle()]}>{children}</Label>; + } + }) + } + </Button> + ); + } +} + +export class RedButton extends BaseButton{ + backgroundStyle = () => this.state.hovered ? styles.redHover : styles.red; +} + +export class GreenButton extends BaseButton{ + backgroundStyle = () => this.state.hovered ? styles.greenHover : styles.green; +} + +export class BlueButton extends BaseButton{ + backgroundStyle = () => this.state.hovered ? styles.blueHover : styles.blue; +} + +export class TransparentButton extends BaseButton{ + backgroundStyle = () => this.state.hovered ? styles.transparentHover : styles.transparent; +}
\ No newline at end of file diff --git a/app/components/styled/CellButton.js b/app/components/styled/CellButton.js new file mode 100644 index 0000000000..7309180241 --- /dev/null +++ b/app/components/styled/CellButton.js @@ -0,0 +1,116 @@ +// @flow +import React from 'react'; +import { Text, Component } from 'reactxp'; +import { Button } from './Button'; +import { colors } from '../../config'; + +import { createViewStyles, createTextStyles } from '../../lib/styles'; + +const styles = { + ...createViewStyles({ + cell:{ + paddingTop: 14, + paddingBottom: 14, + paddingLeft: 16, + paddingRight: 16, + marginBottom: 1, + flex: 1, + flexDirection: 'row', + alignItems: 'center', + alignContent: 'center', + }, + blue:{ + backgroundColor: colors.blue80, + }, + blueHover:{ + backgroundColor: colors.blue60, + }, + white40:{ + color: colors.white40, + }, + white60:{ + color: colors.white60, + }, + white80:{ + color: colors.white80, + }, + white: { + color: colors.white, + }, + icon: { + marginLeft: 8, + }, + }), + ...createTextStyles({ + label:{ + alignSelf: 'center', + fontFamily: 'DINPro', + fontSize: 20, + fontWeight: '900', + lineHeight: 26, + flex: 1, + marginLeft: 8, + }, + subtext:{ + fontFamily: 'Open Sans', + fontSize: 13, + fontWeight: '800', + flex: 0, + textAlign: 'right', + }, + }), +}; + +export class SubText extends Text {} +export class Label extends Text {} + +export default class CellButton extends Component { + props: { + children: Array<React.Element<*>> | React.Element<*>, + disabled: boolean, + }; + + state = { hovered: false }; + + textStyle = () => this.state.hovered ? styles.white80 : styles.white; + iconStyle = () => this.state.hovered ? styles.white40 : styles.white60; + subtextStyle = () => this.state.hovered ? styles.white40 : styles.white60; + backgroundStyle = () => this.state.hovered ? styles.blueHover : styles.blue; + + onHoverStart = () => !this.props.disabled ? this.setState({ hovered: true }) : null; + onHoverEnd = () => !this.props.disabled ? this.setState({ hovered: false }) : null; + + render() { + const { children, ...otherProps } = this.props; + return ( + <Button style={[ styles.cell, this.backgroundStyle() ]} + onHoverStart={this.onHoverStart} + onHoverEnd={this.onHoverEnd} + {...otherProps}> + { + React.Children.map(children, (node) => { + if (React.isValidElement(node)){ + let updatedProps = {}; + + if(node.type.name === 'Label') { + updatedProps = { style: [styles.label, this.textStyle(), node.props.style]}; + } + + if(node.type.name === 'Img') { + updatedProps = { tintColor:'currentColor', style: [styles.icon, this.iconStyle(), node.props.style]}; + } + + if(node.type.name === 'SubText') { + updatedProps = { style: [styles.subtext, this.subtextStyle(), node.props.style]}; + } + + return React.cloneElement(node, updatedProps); + } else { + return <Label style={[styles.label, this.textStyle()]}>{children}</Label>; + } + }) + } + </Button> + ); + } +} diff --git a/app/components/styled/index.js b/app/components/styled/index.js index 6699594f18..de18529cac 100644 --- a/app/components/styled/index.js +++ b/app/components/styled/index.js @@ -1,7 +1,16 @@ // @flow import { Button } from './Button'; +import CellButton, { Label, SubText } from './CellButton'; +import { RedButton, GreenButton, BlueButton, TransparentButton } from './AppButton'; export { - Button + Button, + CellButton, + RedButton, + GreenButton, + BlueButton, + TransparentButton, + Label, + SubText, }; |
