mirror of
https://github.com/trezor/trezor-wallet
synced 2024-11-28 03:08:30 +00:00
Pin modal refactored
This commit is contained in:
parent
8f9a26caaa
commit
ec1b25d760
@ -4,7 +4,7 @@ import colors from 'config/colors';
|
|||||||
const baseStyles = css`
|
const baseStyles = css`
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
color: ${colors.BLACK};
|
color: ${colors.TEXT_PRIMARY};
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ const Wrapper = styled.p`
|
|||||||
font-size: ${FONT_SIZE.BASE};
|
font-size: ${FONT_SIZE.BASE};
|
||||||
line-height: ${LINE_HEIGHT.BASE};
|
line-height: ${LINE_HEIGHT.BASE};
|
||||||
color: ${colors.TEXT_SECONDARY};
|
color: ${colors.TEXT_SECONDARY};
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
${props => props.isSmaller && css`
|
${props => props.isSmaller && css`
|
||||||
font-size: ${FONT_SIZE.SMALLER};
|
font-size: ${FONT_SIZE.SMALLER};
|
||||||
|
52
src/components/buttons/PinButton/index.js
Normal file
52
src/components/buttons/PinButton/index.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import colors from 'config/colors';
|
||||||
|
|
||||||
|
const Wrapper = styled.button`
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
margin-top: 15px;
|
||||||
|
margin-left: 10px;
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: ${colors.TEXT_PRIMARY};
|
||||||
|
border: 1px solid ${colors.DIVIDER};
|
||||||
|
background: ${colors.WHITE};
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin-left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: ${colors.TEXT_PRIMARY};
|
||||||
|
background-color: ${colors.WHITE};
|
||||||
|
border-color: ${colors.TEXT_SECONDARY};
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
color: ${colors.TEXT_PRIMARY};
|
||||||
|
background: ${colors.DIVIDER};
|
||||||
|
border-color: ${colors.DIVIDER};
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const PinButton = ({
|
||||||
|
children, className, onClick,
|
||||||
|
}) => (
|
||||||
|
<Wrapper
|
||||||
|
className={className}
|
||||||
|
onClick={onClick}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Wrapper>
|
||||||
|
);
|
||||||
|
|
||||||
|
PinButton.propTypes = {
|
||||||
|
className: PropTypes.string,
|
||||||
|
children: PropTypes.string.isRequired,
|
||||||
|
onClick: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PinButton;
|
53
src/components/inputs/PinInput/index.js
Normal file
53
src/components/inputs/PinInput/index.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import styled, { css } from 'styled-components';
|
||||||
|
import colors from 'config/colors';
|
||||||
|
import Icon from 'components/Icon';
|
||||||
|
import { FONT_SIZE, FONT_WEIGHT } from 'config/variables';
|
||||||
|
import icons from 'config/icons';
|
||||||
|
|
||||||
|
const Wrapper = styled.div`
|
||||||
|
position: relative;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledInput = styled.input`
|
||||||
|
letter-spacing: 7px;
|
||||||
|
font-weight: ${FONT_WEIGHT.BIGGER};
|
||||||
|
font-size: ${FONT_SIZE.BIGGER};
|
||||||
|
padding: 5px 31px 10px 20px;
|
||||||
|
color: ${colors.TEXT_PRIMARY};
|
||||||
|
background: transparent;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledIcon = styled(Icon)`
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Input = ({
|
||||||
|
onChange,
|
||||||
|
onDeleteClick,
|
||||||
|
value,
|
||||||
|
}) => (
|
||||||
|
<Wrapper>
|
||||||
|
<StyledInput
|
||||||
|
disabled
|
||||||
|
type="password"
|
||||||
|
maxLength="9"
|
||||||
|
autoComplete="off"
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
|
<StyledIcon onClick={() => onDeleteClick()} color={colors.TEXT_PRIMARY} icon={icons.BACK} />
|
||||||
|
</Wrapper>
|
||||||
|
);
|
||||||
|
|
||||||
|
Input.propTypes = {
|
||||||
|
onDeleteClick: PropTypes.func.isRequired,
|
||||||
|
value: PropTypes.string.isRequired,
|
||||||
|
onChange: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Input;
|
@ -4,7 +4,7 @@ import styled from 'styled-components';
|
|||||||
import { H3 } from 'components/Heading';
|
import { H3 } from 'components/Heading';
|
||||||
import P from 'components/Paragraph';
|
import P from 'components/Paragraph';
|
||||||
import Button from 'components/buttons/Button';
|
import Button from 'components/buttons/Button';
|
||||||
import Input from 'components/Input';
|
import Input from 'components/inputs/Input';
|
||||||
import { getDuplicateInstanceNumber } from 'reducers/utils';
|
import { getDuplicateInstanceNumber } from 'reducers/utils';
|
||||||
import { FONT_SIZE } from 'config/variables';
|
import { FONT_SIZE } from 'config/variables';
|
||||||
import Icon from 'components/Icon';
|
import Icon from 'components/Icon';
|
||||||
|
@ -1,19 +1,44 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
|
import P from 'components/Paragraph';
|
||||||
|
import { H2 } from 'components/Heading';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import styled from 'styled-components';
|
import Link from 'components/Link';
|
||||||
import colors from 'config/colors';
|
import colors from 'config/colors';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import PinInput from 'components/inputs/PinInput';
|
||||||
|
import PinButton from 'components/buttons/PinButton';
|
||||||
|
import Button from 'components/buttons/Button';
|
||||||
import type { Props } from './index';
|
import type { Props } from './index';
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
pin: string;
|
pin: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Wrapper = styled.div``;
|
const Wrapper = styled.div`
|
||||||
const InputRow = styled.div``;
|
padding: 24px 48px;
|
||||||
|
`;
|
||||||
|
|
||||||
export default class Pin extends Component<Props, State> {
|
const InputRow = styled.div`
|
||||||
|
margin-top: 24px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const PinRow = styled.div``;
|
||||||
|
|
||||||
|
const StyledP = styled(P)`
|
||||||
|
padding-top: 5px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledLink = styled(Link)`
|
||||||
|
padding-left: 5px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Footer = styled.div`
|
||||||
|
margin: 20px 0 10px 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
`;
|
||||||
|
|
||||||
|
class Pin extends Component<Props, State> {
|
||||||
keyboardHandler: (event: KeyboardEvent) => void;
|
keyboardHandler: (event: KeyboardEvent) => void;
|
||||||
|
|
||||||
state: State;
|
state: State;
|
||||||
@ -109,41 +134,45 @@ export default class Pin extends Component<Props, State> {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (!this.props.modal.opened) return null;
|
if (!this.props.modal.opened) return null;
|
||||||
|
|
||||||
const { onPinSubmit } = this.props.modalActions;
|
const { onPinSubmit } = this.props.modalActions;
|
||||||
const { device } = this.props.modal;
|
const { device } = this.props.modal;
|
||||||
const { pin } = this.state;
|
const { pin } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper className="pin">
|
<Wrapper className="pin">
|
||||||
{/* <button className="close-modal transparent"></button> */}
|
<H2>Enter { device.label } PIN</H2>
|
||||||
<h3>Enter { device.label } PIN</h3>
|
<P>The PIN layout is displayed on your TREZOR.</P>
|
||||||
<p>The PIN layout is displayed on your TREZOR.</p>
|
<InputRow>
|
||||||
|
<PinInput value={pin} onDeleteClick={() => this.onPinBackspace()} />
|
||||||
<div className="pin-input-row">
|
</InputRow>
|
||||||
<input type="password" autoComplete="off" maxLength="9" disabled value={pin} />
|
<PinRow>
|
||||||
<button type="button" className="pin-backspace transparent" onClick={event => this.onPinBackspace()} />
|
<PinButton type="button" data-value="7" onClick={() => this.onPinAdd(7)}>• </PinButton>
|
||||||
</div>
|
<PinButton type="button" data-value="8" onClick={() => this.onPinAdd(8)}>•</PinButton>
|
||||||
|
<PinButton type="button" data-value="9" onClick={() => this.onPinAdd(9)}>•</PinButton>
|
||||||
<div className="pin-row">
|
</PinRow>
|
||||||
<button type="button" data-value="7" onClick={event => this.onPinAdd(7)}>•</button>
|
<PinRow>
|
||||||
<button type="button" data-value="8" onClick={event => this.onPinAdd(8)}>•</button>
|
<PinButton type="button" data-value="4" onClick={() => this.onPinAdd(4)}>• </PinButton>
|
||||||
<button type="button" data-value="9" onClick={event => this.onPinAdd(9)}>•</button>
|
<PinButton type="button" data-value="5" onClick={() => this.onPinAdd(5)}>•</PinButton>
|
||||||
</div>
|
<PinButton type="button" data-value="6" onClick={() => this.onPinAdd(6)}>•</PinButton>
|
||||||
<div className="pin-row">
|
</PinRow>
|
||||||
<button type="button" data-value="4" onClick={event => this.onPinAdd(4)}>•</button>
|
<PinRow>
|
||||||
<button type="button" data-value="5" onClick={event => this.onPinAdd(5)}>•</button>
|
<PinButton type="button" data-value="1" onClick={() => this.onPinAdd(1)}>• </PinButton>
|
||||||
<button type="button" data-value="6" onClick={event => this.onPinAdd(6)}>•</button>
|
<PinButton type="button" data-value="2" onClick={() => this.onPinAdd(2)}>•</PinButton>
|
||||||
</div>
|
<PinButton type="button" data-value="3" onClick={() => this.onPinAdd(3)}>•</PinButton>
|
||||||
<div className="pin-row">
|
</PinRow>
|
||||||
<button type="button" data-value="1" onClick={event => this.onPinAdd(1)}>•</button>
|
<Footer>
|
||||||
<button type="button" data-value="2" onClick={event => this.onPinAdd(2)}>•</button>
|
<Button type="button" onClick={() => onPinSubmit(pin)}>Enter PIN</Button>
|
||||||
<button type="button" data-value="3" onClick={event => this.onPinAdd(3)}>•</button>
|
<StyledP>Not sure how PIN works?
|
||||||
</div>
|
<StyledLink
|
||||||
|
href="http://doc.satoshilabs.com/trezor-user/enteringyourpin.html"
|
||||||
<div><button className="submit" type="button" onClick={event => onPinSubmit(pin)}>Enter PIN</button></div>
|
target="_blank"
|
||||||
<p>Not sure how PIN works? <a className="green" href="http://doc.satoshilabs.com/trezor-user/enteringyourpin.html" target="_blank" rel="noreferrer noopener">Learn more</a></p>
|
rel="noreferrer noopener"
|
||||||
|
>Learn more
|
||||||
|
</StyledLink>
|
||||||
|
</StyledP>
|
||||||
|
</Footer>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default Pin;
|
@ -1,4 +1,7 @@
|
|||||||
export default {
|
export default {
|
||||||
|
BACK: [
|
||||||
|
'M656.224 402.304l-66.848 66.176-66.848-66.176-50.144 49.6 66.912 66.176-66.912 66.176 50.176 49.632 66.848-66.176 66.848 66.176 50.112-49.632-66.816-66.176 66.816-66.176-50.144-49.6zM337.824 256h540.928c27.2 0 49.248 21.824 49.248 48.768v414.464c0 26.944-22.048 48.768-49.248 48.768h-540.608c-13.856 0-27.072-5.792-36.416-15.936l-192.896-209.664c-17.248-18.752-17.088-47.488 0.352-66.048l192.576-204.8c9.344-9.92 22.4-15.552 36.064-15.552z',
|
||||||
|
],
|
||||||
HELP: [
|
HELP: [
|
||||||
'M693.024 330.944c-99.968-99.936-262.080-99.936-362.048 0s-99.968 262.112 0 362.080c99.968 100 262.144 99.936 362.048 0 99.968-99.904 99.968-262.176 0-362.080zM501.216 717.952c-27.808 0-50.496-22.464-50.496-50.048 0-28.32 22.176-50.528 50.496-50.528 27.616 0 50.048 22.656 50.048 50.528 0.032 27.168-22.88 50.048-50.048 50.048zM536.416 542.464v27.744c0 13.504-5.28 18.784-18.784 18.784h-36.224c-13.504 0-18.72-5.28-18.72-18.784v-61.984c0-15.68 16.064-20.352 30.208-24.48 3.456-1.056 7.040-2.080 10.496-3.264 18.336-6.592 29.696-14.816 29.696-35.296 0-6.656 0-26.816-32.832-26.816-20.224 0-38.624 7.776-49.6 12.416-6.208 2.624-9.28 3.904-12.384 3.904-6.336 0-12.32-5.088-13.248-10.304l-12.608-32.96c-1.824-3.776-1.824-6.784-1.824-9.216 0-24.288 75.552-37.664 100.608-37.664 63.104 0 105.504 40.672 105.504 101.152 0.032 65.44-49.12 85.952-80.288 96.768z',
|
'M693.024 330.944c-99.968-99.936-262.080-99.936-362.048 0s-99.968 262.112 0 362.080c99.968 100 262.144 99.936 362.048 0 99.968-99.904 99.968-262.176 0-362.080zM501.216 717.952c-27.808 0-50.496-22.464-50.496-50.048 0-28.32 22.176-50.528 50.496-50.528 27.616 0 50.048 22.656 50.048 50.528 0.032 27.168-22.88 50.048-50.048 50.048zM536.416 542.464v27.744c0 13.504-5.28 18.784-18.784 18.784h-36.224c-13.504 0-18.72-5.28-18.72-18.784v-61.984c0-15.68 16.064-20.352 30.208-24.48 3.456-1.056 7.040-2.080 10.496-3.264 18.336-6.592 29.696-14.816 29.696-35.296 0-6.656 0-26.816-32.832-26.816-20.224 0-38.624 7.776-49.6 12.416-6.208 2.624-9.28 3.904-12.384 3.904-6.336 0-12.32-5.088-13.248-10.304l-12.608-32.96c-1.824-3.776-1.824-6.784-1.824-9.216 0-24.288 75.552-37.664 100.608-37.664 63.104 0 105.504 40.672 105.504 101.152 0.032 65.44-49.12 85.952-80.288 96.768z',
|
||||||
],
|
],
|
||||||
|
@ -3,6 +3,7 @@ export const FONT_SIZE = {
|
|||||||
SMALLER: '12px',
|
SMALLER: '12px',
|
||||||
SMALL: '14px',
|
SMALL: '14px',
|
||||||
BASE: '16px',
|
BASE: '16px',
|
||||||
|
BIGGER: '32px',
|
||||||
BIGGEST: '36px',
|
BIGGEST: '36px',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -13,11 +13,6 @@ input, textarea {
|
|||||||
&:focus {
|
&:focus {
|
||||||
box-shadow: 0 1px 2px 0 rgba(169, 169, 169, 0.25);
|
box-shadow: 0 1px 2px 0 rgba(169, 169, 169, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:disabled {
|
|
||||||
background: @color_gray_light;
|
|
||||||
color: @color_text_secondary;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
margin-top: 14px;
|
margin-top: 14px;
|
||||||
}
|
}
|
||||||
p {
|
p {
|
||||||
margin: 5px 0px;
|
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
color: @color_text_secondary;
|
color: @color_text_secondary;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@ -56,51 +55,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.pin {
|
.pin {
|
||||||
padding: 24px 48px;
|
|
||||||
.pin-row {
|
|
||||||
button {
|
|
||||||
width: 80px;
|
|
||||||
height: 80px;
|
|
||||||
margin-top: 15px;
|
|
||||||
margin-left: 10px;
|
|
||||||
font-size: 22px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: @color_text_primary;
|
|
||||||
border: 1px solid @color_divider;
|
|
||||||
background: @color_white;
|
|
||||||
transition: all 0.3s;
|
|
||||||
&:first-child {
|
|
||||||
margin-left: 0px;
|
|
||||||
}
|
|
||||||
&:hover {
|
|
||||||
color: @color_text_primary;
|
|
||||||
border-color: @color_text_secondary;
|
|
||||||
}
|
|
||||||
&:active {
|
|
||||||
color: @color_text_primary;
|
|
||||||
background: @color_divider;
|
|
||||||
border-color: @color_divider;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.pin-input-row {
|
|
||||||
margin-top: 24px;
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
|
||||||
letter-spacing: 6px;
|
|
||||||
line-height: 48px;
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 32px;
|
|
||||||
height: auto;
|
|
||||||
padding: 0px 31px;
|
|
||||||
color: @color_text_primary;
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pin-backspace {
|
.pin-backspace {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
Loading…
Reference in New Issue
Block a user