Small css class adjustments (#342)

* Small css class adjustments

* Additional

* Adjustments

* Update packages/extension-ui/src/partials/AddAccount.tsx

* Additional css movements

* Minor adjustments
This commit is contained in:
Jaco Greeff
2020-05-31 12:18:54 +02:00
committed by GitHub
parent 5767777ab7
commit ba3b0d3c77
31 changed files with 481 additions and 463 deletions
@@ -150,7 +150,7 @@ describe('Derive', () => {
it('selects internal root accounts as other options', async () => {
const { wrapper } = await mountComponent();
const options = wrapper.find('[data-parent-option] [data-field="name"] div').map((el) => el.text());
const options = wrapper.find('[data-parent-option] [data-field="name"]').map((el) => el.text());
expect(options).toEqual(['A', 'B', 'D']);
});
+1 -1
View File
@@ -36,7 +36,7 @@ function Forget ({ match: { params: { address } } }: Props): React.ReactElement<
/>
<div>
<Address address={address}>
<MovedWarning danger>
<MovedWarning isDanger>
You are about to remove the account. This means that you will not be able to access it via this extension anymore. If you wish to recover it, you would need to use the seed.
</MovedWarning>
<ActionArea>
@@ -54,8 +54,10 @@ export default function Upload (): React.ReactElement {
);
const _onChangeFile = useCallback(
async (file: Uint8Array): Promise<void> => {
setJson(await parseFile(file));
(file: Uint8Array): void => {
parseFile(file)
.then(setJson)
.catch(console.error);
}, []
);
@@ -27,23 +27,23 @@ function ActionText ({ className, icon, onClick, text }: Props): React.ReactElem
);
}
export default styled(ActionText)`
export default styled(ActionText)(({ theme }: ThemeProps) => `
cursor: pointer;
span {
font-size: ${({ theme }: ThemeProps): string => theme.labelFontSize};
line-height: ${({ theme }: ThemeProps): string => theme.labelLineHeight};
color: ${theme.labelColor}
font-size: ${theme.labelFontSize};
line-height: ${theme.labelLineHeight};
text-decoration-line: underline;
color: ${({ theme }: ThemeProps): string => theme.labelColor}
}
${Svg} {
background: ${({ theme }: ThemeProps): string => theme.iconNeutralColor};
background: ${theme.iconNeutralColor};
display: inline-block;
height: 14px;
margin-right: 6px;
position: relative;
top: 2px;
width: 14px;
height: 14px;
margin-right: 6px;
}
`;
`);
+145 -134
View File
@@ -107,105 +107,81 @@ function Address ({ actions, address, children, className, genesisHash, name, pa
return (
<div className={className}>
<div>
<AccountInfoRow>
<Identicon
iconTheme={theme}
onCopy={_onCopy}
prefix={prefix}
value={formatted || address}
/>
<Info>
{parentName ? (
<div className='infoRow'>
<Identicon
className='identityIcon'
iconTheme={theme}
onCopy={_onCopy}
prefix={prefix}
value={formatted || address}
/>
<div className='info'>
{parentName
? (
<>
<Banner>
<div className='banner'>
<ArrowLabel/>
<ParentName data-field='parent'>{parentName}{suri || ''}</ParentName>
</Banner>
<DisplacedName>{displayedName}</DisplacedName>
<div
className='parentName'
data-field='parent'
>
{parentName}{suri || ''}
</div>
</div>
<div className='name displaced'>{displayedName}</div>
</>
) : (
<Name data-field='name'>{displayedName}</Name>
)
: (
<div
className='name'
data-field='name'
>
{displayedName}
</div>
)
}
<div className='copyAddress'>
<FullAddress data-field='address'>{formatted || '<unknown>'}</FullAddress>
{chain?.genesisHash && (
<div
className='banner chain'
data-field='chain'
>
{chain.name}
</div>
)}
<CopyAddress>
<FullAddress data-field='address'>{formatted || '<unknown>'}</FullAddress>
{chain?.genesisHash && <ChainBanner data-field='chain'>{chain.name}</ChainBanner>}
<CopyToClipboard text={(formatted && formatted) || ''} >
<Svg
onClick={_onCopy}
src={copy}
/>
</CopyToClipboard>
</CopyAddress>
</Info>
{actions && (
<>
<Settings onClick={_onClick}>
{showActionsMenu
? <ActiveActionsIcon />
: <ActionsIcon />
}
</Settings>
{showActionsMenu && (
<MovableMenu
isMoved={moveMenuUp}
reference={actionsRef}
>
{actions}
</MovableMenu>
)}
</>
)}
</AccountInfoRow>
{children}
<CopyToClipboard text={(formatted && formatted) || ''} >
<Svg
onClick={_onCopy}
src={copy}
/>
</CopyToClipboard>
</div>
</div>
{actions && (
<>
<Settings onClick={_onClick}>
{showActionsMenu
? <ActiveActionsIcon />
: <ActionsIcon />
}
</Settings>
{showActionsMenu && (
<MovableMenu
isMoved={moveMenuUp}
reference={actionsRef}
>
{actions}
</MovableMenu>
)}
</>
)}
</div>
{children}
</div>
);
}
const CopyAddress = styled.div`
display: flex;
justify-content: space-between;
& ${Svg} {
width: 14px;
height: 14px;
margin-right: 10px;
background: ${({ theme }: ThemeProps): string => theme.accountDotsIconColor};
&:hover {
background: ${({ theme }: ThemeProps): string => theme.labelColor};
cursor: pointer;
}
}
`;
const AccountInfoRow = styled.div`
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
height: 72px;
border-radius: 4px;
`;
const Info = styled.div`
width: 100%;
`;
const Name = styled.div`
overflow: hidden;
text-overflow: ellipsis;
width: 300px;
margin: 2px 0;
font-weight: 600;
font-size: 16px;
line-height: 22px;
`;
const DisplacedName = styled(Name)`
padding-top: 10px;
`;
const FullAddress = styled.div`
width: 270px;
overflow: hidden;
@@ -248,47 +224,15 @@ const Settings = styled.div`
Settings.displayName = 'Details';
const ActionsIcon = styled(Svg).attrs(() => ({
src: details
}))`
const ActionsIcon = styled(Svg).attrs(() => ({ src: details }))`
background: ${({ theme }: ThemeProps): string => theme.accountDotsIconColor};
`;
const ActiveActionsIcon = styled(Svg).attrs(() => ({
src: details
}))`
const ActiveActionsIcon = styled(Svg).attrs(() => ({ src: details }))`
background: ${({ theme }: ThemeProps): string => theme.primaryColor};
`;
const Banner = styled.div`
border-radius: 0 0 8px 8px;
color: white;
font-size: 12px;
line-height: 16px;
position: absolute;
top: 0;
`;
const ChainBanner = styled(Banner)`
padding: 0.1rem 0.5rem;
right: 40px;
background: ${({ theme }: ThemeProps): string => theme.primaryColor};
`;
const ParentName = styled.div`
padding: 0.25rem 0 0 0.8rem;
font-weight: 600;
font-size: 10px;
line-height: 14px;
color: ${({ theme }: ThemeProps): string => theme.labelColor};
text-overflow: ellipsis;
overflow: hidden;
width: 270px;
`;
const ArrowLabel = styled(Svg).attrs(() => ({
src: parentArrow
}))`
const ArrowLabel = styled(Svg).attrs(() => ({ src: parentArrow }))`
position: absolute;
top: 5px;
width: 9px;
@@ -296,22 +240,51 @@ const ArrowLabel = styled(Svg).attrs(() => ({
background: ${({ theme }: ThemeProps): string => theme.labelColor};
`;
const MovableMenu = styled(Menu) <{ isMoved: boolean }>`
const MovableMenu = styled(Menu)<{ isMoved: boolean }>`
${({ isMoved }): string => isMoved ? 'bottom: 50px' : ''};
`;
export default styled(Address)`
export default styled(Address)(({ theme }: ThemeProps) => `
position: relative;
margin-bottom: 8px;
& > div {
background: ${({ theme }: ThemeProps): string => theme.accountBackground};
border: 1px solid ${({ theme }: ThemeProps): string => theme.boxBorderColor};
box-sizing: border-box;
border-radius: 4px;
background: ${theme.accountBackground};
border: 1px solid ${theme.boxBorderColor};
box-sizing: border-box;
border-radius: 4px;
.banner {
border-radius: 0 0 8px 8px;
color: white;
font-size: 12px;
line-height: 16px;
position: absolute;
top: 0;
&.chain {
background: ${theme.primaryColor};
padding: 0.1rem 0.5rem;
right: 40px;
}
}
& ${Identicon} {
.copyAddress {
display: flex;
justify-content: space-between;
& ${Svg} {
width: 14px;
height: 14px;
margin-right: 10px;
background: ${theme.accountDotsIconColor};
&:hover {
background: ${theme.labelColor};
cursor: pointer;
}
}
}
.identityIcon {
margin-left: 25px;
margin-right: 10px;
@@ -320,4 +293,42 @@ export default styled(Address)`
height: 50px;
}
}
`;
.info {
width: 100%;
}
.infoRow {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
height: 72px;
border-radius: 4px;
}
.name {
font-size: 16px;
font-weight: 600;
line-height: 22px;
margin: 2px 0;
overflow: hidden;
text-overflow: ellipsis;
width: 300px;
&.displaced {
padding-top: 10px;
}
}
.parentName {
color: ${theme.labelColor};
font-size: 10px;
font-weight: 600;
line-height: 14px;
overflow: hidden;
padding: 0.25rem 0 0 0.8rem;
text-overflow: ellipsis;
width: 270px;
}
`);
@@ -29,9 +29,7 @@ const SmallButton = styled(Button)`
background: ${({ theme }: ThemeProps): string => theme.backButtonBackground};
`;
const ArrowLeft = styled(Svg).attrs(() => ({
src: arrowLeft
}))`
const ArrowLeft = styled(Svg).attrs(() => ({ src: arrowLeft }))`
width: 12px;
height: 12px;
display: block;
+10 -10
View File
@@ -22,20 +22,20 @@ function Box ({ banner, children, className }: Props): React.ReactElement<Props>
);
}
export default styled(Box)`
background: ${({ theme }: ThemeProps): string => theme.readonlyInputBackground};
export default styled(Box)(({ theme }: ThemeProps) => `
background: ${theme.readonlyInputBackground};
border: none;
border-radius: ${({ theme }: ThemeProps): string => theme.borderRadius};
color: ${({ theme }: ThemeProps): string => theme.textColor};
font-family: ${({ theme }: ThemeProps): string => theme.fontFamily};
font-size: ${({ theme }: ThemeProps): string => theme.fontSize};
margin: ${({ theme }: ThemeProps): string => theme.boxMargin};
padding: ${({ theme }: ThemeProps): string => theme.boxPadding};
border-radius: ${theme.borderRadius};
color: ${theme.textColor};
font-family: ${theme.fontFamily};
font-size: ${theme.fontSize};
margin: ${theme.boxMargin};
padding: ${theme.boxPadding};
position: relative;
.banner {
background: darkorange;
border-radius: 0 ${({ theme }: ThemeProps): string => theme.borderRadius} 0 ${({ theme }: ThemeProps): string => theme.borderRadius};
border-radius: 0 ${theme.borderRadius} 0 ${theme.borderRadius};
color: white;
font-size: 0.75rem;
padding: 0.25rem 0.5rem;
@@ -43,4 +43,4 @@ export default styled(Box)`
right: 0;
top: 0;
}
`;
`);
@@ -40,20 +40,20 @@ function Button ({ children, className, isDisabled, onClick, to }: Props): React
);
}
export default styled(Button)`
export default styled(Button)(({ isDanger, theme }: Props) => `
display: block;
width: 100%;
height: ${({ isDanger }: Props): string => isDanger ? '40px' : '48px'};
height: ${isDanger ? '40px' : '48px'};
box-sizing: border-box;
border: none;
border-radius: ${({ theme }: Props): string => theme.borderRadius};
color: ${({ theme }: Props): string => theme.buttonTextColor};
border-radius: ${theme.borderRadius};
color: ${theme.buttonTextColor};
font-size: 15px;
font-weight: 800;
line-height: 20px;
padding: 0 1rem;
text-align: center;
background: ${({ isDanger, theme }: Props): string => isDanger ? theme.buttonBackgroundDanger : theme.buttonBackground};
background: ${isDanger ? theme.buttonBackgroundDanger : theme.buttonBackground};
cursor: pointer;
&:disabled {
@@ -62,6 +62,6 @@ export default styled(Button)`
}
&:not(:disabled):hover {
background: ${({ isDanger, theme }: Props): string => isDanger ? theme.buttonBackgroundDangerHover : theme.buttonBackgroundHover};
background: ${isDanger ? theme.buttonBackgroundDangerHover : theme.buttonBackgroundHover};
}
`;
`);
@@ -7,11 +7,11 @@ import { ThemeProps } from '../types';
import styled from 'styled-components';
import Button from './Button';
export default styled.div`
export default styled.div(({ theme }: ThemeProps) => `
display: flex;
flex-direction: row;
background: ${({ theme }: ThemeProps): string => theme.highlightedAreaBackground};
border-top: 1px solid ${({ theme }: ThemeProps): string => theme.inputBorderColor};
background: ${theme.highlightedAreaBackground};
border-top: 1px solid ${theme.inputBorderColor};
padding: 12px 24px;
&&& {
@@ -22,4 +22,4 @@ export default styled.div`
& > ${Button}:not(:last-of-type) {
margin-right: 8px;
}
`;
`);
@@ -31,8 +31,8 @@ function Checkbox ({ checked, className, label, onChange }: Props): React.ReactE
);
}
export default styled(Checkbox)`
margin: ${({ theme }: ThemeProps): string => theme.boxMargin};
export default styled(Checkbox)(({ theme }: ThemeProps) => `
margin: ${theme.boxMargin};
label {
display: block;
@@ -41,9 +41,9 @@ export default styled(Checkbox)`
user-select: none;
padding-left: 24px;
padding-top: 1px;
color: ${({ theme }: ThemeProps): string => theme.subTextColor};
font-size: ${({ theme }: ThemeProps): string => theme.fontSize};
line-height: ${({ theme }: ThemeProps): string => theme.lineHeight};
color: ${theme.subTextColor};
font-size: ${theme.fontSize};
line-height: ${theme.lineHeight};
& input {
position: absolute;
@@ -59,10 +59,10 @@ export default styled(Checkbox)`
left: 0;
height: 16px;
width: 16px;
border-radius: ${({ theme }: ThemeProps): string => theme.borderRadius};
background-color: ${({ theme }: ThemeProps): string => theme.readonlyInputBackground};
border: 1px solid ${({ theme }: ThemeProps): string => theme.inputBorderColor};
border: 1px solid ${({ theme }: ThemeProps): string => theme.inputBorderColor};
border-radius: ${theme.borderRadius};
background-color: ${theme.readonlyInputBackground};
border: 1px solid ${theme.inputBorderColor};
border: 1px solid ${theme.inputBorderColor};
&:after {
content: '';
display: none;
@@ -73,16 +73,16 @@ export default styled(Checkbox)`
top: 2px;
mask: url(${Checkmark});
mask-size: cover;
background: ${({ theme }: ThemeProps): string => theme.primaryColor};
background: ${theme.primaryColor};
}
}
&:hover input ~ span {
background-color: ${({ theme }: ThemeProps): string => theme.inputBackground};
background-color: ${theme.inputBackground};
}
input:checked ~ span:after {
display: block;
}
}
`;
`);
@@ -59,23 +59,23 @@ function Dropdown ({ className, defaultValue, isFocussed, label, onBlur, onChang
);
}
export default styled(Dropdown)`
export default React.memo(styled(Dropdown)(({ isError, theme }: Props) => `
position: relative;
select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background: ${({ theme }: Props): string => theme.readonlyInputBackground};
border-color: ${({ isError, theme }: Props): string => isError ? theme.errorBorderColor : theme.inputBorderColor};
border-radius: ${({ theme }: ThemeProps): string => theme.borderRadius};
background: ${theme.readonlyInputBackground};
border-color: ${isError ? theme.errorBorderColor : theme.inputBorderColor};
border-radius: ${theme.borderRadius};
border-style: solid;
border-width: 1px;
box-sizing: border-box;
color: ${({ isError, theme }: Props): string => isError ? theme.errorBorderColor : theme.textColor};
color: ${isError ? theme.errorBorderColor : theme.textColor};
display: block;
font-family: ${({ theme }: Props): string => theme.fontFamily};
font-size: ${({ theme }: Props): string => theme.fontSize};
font-family: ${theme.fontFamily};
font-size: ${theme.fontSize};
font-weight: 600;
padding: 0.5rem 0.75rem;
width: 100%;
@@ -98,4 +98,4 @@ export default styled(Dropdown)`
background: url(${arrow}) center no-repeat;
pointer-events: none;
}
`;
`));
@@ -22,13 +22,10 @@ function Icon ({ className = '', icon, onClick }: Props): React.ReactElement<Pro
);
}
export default styled(Icon)`
export default styled(Icon)(({ onClick }: Props) => `
background: white;
border-radius: 50%;
box-sizing: border-box;
cursor: ${({ onClick }): string =>
onClick
? 'pointer'
: 'inherit'};
cursor: ${onClick ? 'pointer' : 'inherit'};
text-align: center;
`;
`);
@@ -31,13 +31,13 @@ function Identicon ({ className, iconTheme, onCopy, prefix, value }: Props): Rea
);
}
export default styled(Identicon)`
export default styled(Identicon)(({ theme }: ThemeProps) => `
display: flex;
justify-content: center;
.container:before {
box-shadow: none;
background: ${({ theme }: ThemeProps): string => theme.identiconBackground};
background: ${theme.identiconBackground};
}
svg {
@@ -45,4 +45,4 @@ export default styled(Identicon)`
display: none;
}
}
`;
`);
@@ -22,8 +22,8 @@ function Label ({ children, className, label }: Props): React.ReactElement<Props
);
}
export default styled(Label)`
color: ${({ theme }: ThemeProps): string => theme.textColor};
export default styled(Label)(({ theme }: ThemeProps) => `
color: ${theme.textColor};
label {
font-size: 10px;
@@ -34,4 +34,4 @@ export default styled(Label)`
margin-bottom: 12px;
text-transform: uppercase;
}
`;
`);
@@ -6,7 +6,7 @@ import { ThemeProps } from '../types';
import styled from 'styled-components';
export default styled.ul`
export default styled.ul(({ theme }: ThemeProps) => `
list-style: none;
padding-inline-start: 10px;
padding-inline-end: 10px;
@@ -19,10 +19,10 @@ export default styled.ul`
li::before {
content: '\\2022';
color: ${({ theme }: ThemeProps): string => theme.primaryColor};
color: ${theme.primaryColor};
font-size: 30px;
font-weight: bold;
margin-right: 10px;
vertical-align: -20%;
}
`;
`);
@@ -24,15 +24,15 @@ function Menu ({ children, className, reference }: Props): React.ReactElement<Pr
);
}
export default styled(Menu)`
export default styled(Menu)(({ theme }: ThemeProps) => `
position: absolute;
right: 0;
margin-top: 90px;
padding: 16px 0;
background: ${({ theme }: ThemeProps): string => theme.popupBackground};
background: ${theme.popupBackground};
border-radius: 4px;
border: 1px solid ${({ theme }: ThemeProps): string => theme.boxBorderColor};
border: 1px solid ${theme.boxBorderColor};
box-sizing: border-box;
box-shadow: 0 0 32px ${({ theme }: ThemeProps): string => theme.boxShadow};
box-shadow: 0 0 32px ${theme.boxShadow};
z-index: 1;
`;
`);
@@ -20,14 +20,14 @@ function MnemonicSeed ({ className, onCopy, seed }: Props): React.ReactElement<P
return (
<div className={className}>
<MnemonicText value={seed} />
<ButtonsRow>
<div className='buttonsRow'>
<ActionText
data-seed-action='copy'
icon={copy}
onClick={onCopy}
text='Copy to clipboard'
/>
</ButtonsRow>
</div>
</div>
);
}
@@ -47,15 +47,15 @@ const MnemonicText = styled(TextAreaWithLabel).attrs(() => ({
}
`;
const ButtonsRow = styled.div`
display: flex;
flex-direction: row;
${ActionText} {
margin-right: 32px;
}
`;
export default styled(MnemonicSeed)`
margin-top: 21px;
.buttonsRow {
display: flex;
flex-direction: row;
${ActionText} {
margin-right: 32px;
}
}
`;
@@ -22,9 +22,7 @@ export default function NextStepButton ({ children, ...props }: Props): React.Re
);
}
const ArrowRight = styled(Svg).attrs(() => ({
src: arrowLeft
}))`
const ArrowRight = styled(Svg).attrs(() => ({ src: arrowLeft }))`
float: right;
width: 12px;
height: 12px;
+41 -41
View File
@@ -25,55 +25,20 @@ function Switch ({ checked, checkedLabel, className, onChange, uncheckedLabel }:
<div className={className}>
<span>{uncheckedLabel}</span>
<label>
<Checkbox
<input
checked={checked}
className='checkbox'
onChange={_onChange}
type='checkbox'
/>
<Slider />
<span className='slider' />
</label>
<span>{checkedLabel}</span>
</div>
);
}
const Slider = styled.span`
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: ${({ theme }: ThemeProps): string => theme.readonlyInputBackground};
transition: 0.2s;
border-radius: 100px;
border: 1px solid ${({ theme }: ThemeProps): string => theme.inputBorderColor};
&:before {
position: absolute;
content: '';
height: 16px;
width: 16px;
left: 4px;
bottom: 3px;
background-color: ${({ theme }: ThemeProps): string => theme.primaryColor};
transition: 0.4s;
border-radius: 50%;
}
`;
const Checkbox = styled.input.attrs(() => ({
type: 'checkbox'
}))`
opacity: 0;
width: 0;
height: 0;
&:checked + ${Slider}:before {
transform: translateX(24px);
}
`;
export default styled(Switch)`
export default styled(Switch)(({ theme }: ThemeProps) => `
label {
position: relative;
display: inline-block;
@@ -85,4 +50,39 @@ export default styled(Switch)`
span {
font-weight: 600;
}
`;
.checkbox {
opacity: 0;
width: 0;
height: 0;
&:checked + .slider:before {
transform: translateX(24px);
}
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: ${theme.readonlyInputBackground};
transition: 0.2s;
border-radius: 100px;
border: 1px solid ${theme.inputBorderColor};
&:before {
position: absolute;
content: '';
height: 16px;
width: 16px;
left: 4px;
bottom: 3px;
background-color: ${theme.primaryColor};
transition: 0.4s;
border-radius: 50%;
}
}
`);
@@ -23,11 +23,11 @@ function Table ({ children, className = '', isFull }: Props): React.ReactElement
);
}
export default React.memo(styled(Table)`
export default React.memo(styled(Table)(({ theme }: ThemeProps) => `
border: 0;
display: block;
font-size: ${({ theme }: ThemeProps): string => theme.labelFontSize};
line-height: ${({ theme }: ThemeProps): string => theme.labelLineHeight};
font-size: ${theme.labelFontSize};
line-height: ${theme.labelLineHeight};
margin-bottom: 1rem;
&.isFull {
@@ -73,4 +73,4 @@ export default React.memo(styled(Table)`
white-space: normal;
}
}
`);
`));
@@ -6,7 +6,7 @@ import { ThemeProps } from '../types';
import styled from 'styled-components';
export default styled.div`
export default styled.div(({ theme }: ThemeProps) => `
width: 100%;
margin-bottom: 8px;
margin-top: 18px;
@@ -15,6 +15,6 @@ export default styled.div`
line-height: 14px;
letter-spacing: 0.04em;
text-transform: uppercase;
color: ${({ theme }: ThemeProps): string => theme.textColor};
color: ${theme.textColor};
opacity: 0.65;
`;
`);
@@ -12,8 +12,8 @@ import Svg from './Svg';
interface Props extends ThemeProps {
children: React.ReactNode;
danger?: boolean;
className?: string;
isDanger?: boolean;
}
function Warning ({ children, className }: Props): React.ReactElement<Props> {
@@ -30,18 +30,18 @@ function Warning ({ children, className }: Props): React.ReactElement<Props> {
);
}
export default React.memo(styled(Warning)`
export default React.memo(styled(Warning)(({ isDanger, theme }: Props) => `
display: flex;
flex-direction: row;
padding-left: ${({ danger }): string => danger ? '18px' : ''};
color: ${({ theme }: Props): string => theme.subTextColor};
padding-left: ${isDanger ? '18px' : ''};
color: ${theme.subTextColor};
margin-right: 20px;
border-left: ${({ danger, theme }: Props): string => danger ? `0.25rem solid ${theme.buttonBackgroundDanger}` : ''};
border-left: ${isDanger ? `0.25rem solid ${theme.buttonBackgroundDanger}` : ''};
.warningImage {
width: 16px;
height: 14px;
margin: 5px 10px 5px 0;
background: ${({ danger, theme }: Props): string => danger ? theme.iconDangerColor : theme.iconWarningColor};
background: ${isDanger ? theme.iconDangerColor : theme.iconWarningColor};
}
`);
`));
@@ -10,11 +10,7 @@ import { AvailableThemes } from '.';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const noop = (): void => undefined;
const AccountContext = React.createContext<AccountsContext>({
accounts: [],
hierarchy: [],
master: undefined
});
const AccountContext = React.createContext<AccountsContext>({ accounts: [], hierarchy: [], master: undefined });
const ActionContext = React.createContext<(to?: string) => void>(noop);
const AuthorizeReqContext = React.createContext<AuthorizeRequest[]>([]);
const MediaContext = React.createContext<boolean>(false);
@@ -11,7 +11,7 @@ import { ActionContext } from '../components';
import AddAccountImage from './AddAccountImage';
import Header from './Header';
interface Props {
interface Props extends ThemeProps {
className?: string;
}
@@ -26,43 +26,43 @@ function AddAccount ({ className }: Props): React.ReactElement<Props> {
<>
<Header
showSettings
text={'Add Account'}
text='Add Account'
/>
<div className={className}>
<Image>
<div className='image'>
<AddAccountImage onClick={_onClick}/>
</Image>
<div>
<TipText>You currently don&apos;t have any accounts. Either create a new account or if you have an existing account you wish to use, import it with the seed phrase.</TipText>
</div>
<div className='no-accounts'>
<p>You currently don&apos;t have any accounts. Either create a new account or if you have an existing account you wish to use, import it with the seed phrase.</p>
</div>
</div>
</>
);
}
const TipText = styled.p`
text-align: center;
font-size: 16px;
line-height: 26px;
margin: 0 30px;
color: ${({ theme }: ThemeProps): string => theme.subTextColor};
`;
const Image = styled.div`
display: flex;
justify-content: center;
`;
export default styled(AddAccount)`
color: ${({ theme }: ThemeProps): string => theme.textColor};
export default React.memo(styled(AddAccount)(({ theme }: Props) => `
color: ${theme.textColor};
height: 100%;
h3 {
color: ${({ theme }: ThemeProps): string => theme.textColor};
color: ${theme.textColor};
margin-top: 0;
font-weight: normal;
font-size: 24px;
line-height: 33px;
text-align: center;
}
`;
> .image {
display: flex;
justify-content: center;
}
> .no-accounts p {
text-align: center;
font-size: 16px;
line-height: 26px;
margin: 0 30px;
color: ${theme.subTextColor};
}
`));
@@ -69,17 +69,17 @@ function AddAccountImage ({ className, onClick }: Props): React.ReactElement<Pro
);
}
export default styled(AddAccountImage)`
export default React.memo(styled(AddAccountImage)(({ theme }: Props) => `
circle, path {
cursor: pointer;
}
path {
fill: ${({ theme }: Props): string => theme.textColor};
fill: ${theme.textColor};
}
& > g > circle {
stroke: ${({ theme }: Props): string => theme.inputBorderColor};
fill: ${({ theme }: Props): string => theme.addAccountImageBackground};
stroke: ${theme.inputBorderColor};
fill: ${theme.addAccountImageBackground};
}
`;
`));
+5 -5
View File
@@ -10,7 +10,7 @@ import styled from 'styled-components';
import ArrowLeftImage from '../assets/arrowLeft.svg';
import { Link, Svg } from '../components';
interface Props {
interface Props extends ThemeProps {
className?: string;
to?: string;
}
@@ -43,9 +43,9 @@ const BackLink = styled(Link)`
}
`;
export default styled(Back)`
export default React.memo(styled(Back)(({ theme }: Props) => `
margin: 0;
line-height: 52px;
border-bottom: 1px solid ${({ theme }: ThemeProps): string => theme.inputBorderColor};
font-size: ${({ theme }: ThemeProps): string => theme.labelFontSize};
`;
border-bottom: 1px solid ${theme.inputBorderColor};
font-size: ${theme.labelFontSize};
`));
@@ -44,7 +44,7 @@ function DerivationPath ({ className, defaultPath, onChange, parentAddress, pare
return (
<div className={className}>
<PathField>
<div className='container'>
<PathInput isUnlocked={isDisabled}>
<ValidatedInput
component={InputWithLabel}
@@ -65,16 +65,11 @@ function DerivationPath ({ className, defaultPath, onChange, parentAddress, pare
<LockButton onClick={_onExpand}>
{!isDisabled ? <LockIcon/> : <UnlockIcon/>}
</LockButton>
</PathField>
</div>
</div>
);
}
const PathField = styled.div`
display: flex;
flex-direction: row;
`;
interface UnlockableComponentProps {
isUnlocked: boolean;
}
@@ -87,37 +82,41 @@ const PathInput = styled.div<UnlockableComponentProps>`
}
`;
const LockIcon = styled(Svg).attrs(() => ({
src: lockIcon
}))`
const LockIcon = styled(Svg).attrs(() => ({ src: lockIcon }))`
width: 11px;
height: 14px;
background: ${({ theme }: ThemeProps) => theme.iconNeutralColor};
`;
const UnlockIcon = styled(Svg).attrs(() => ({
src: unlockIcon
}))`
const UnlockIcon = styled(Svg).attrs(() => ({ src: unlockIcon }))`
width: 11px;
height: 14px;
background: ${({ theme }: ThemeProps) => theme.iconNeutralColor};
`;
const LockButton = styled(Button)`
width: 11px;
height: 14px;
padding: 3px;
margin: 36px 2px 0 10px;
background: none;
height: 14px;
margin: 36px 2px 0 10px;
padding: 3px;
width: 11px;
&:not(:disabled):hover {
background: none;
}
&:active, &:focus {
outline: none;
}
&::-moz-focus-inner {
border: 0;
}
`;
export default DerivationPath;
export default React.memo(styled(DerivationPath)`
> .container {
display: flex;
flex-direction: row;
}
`);
@@ -37,7 +37,7 @@ describe('Header component', () => {
it('highlights gear icon when settings are toggled', () => {
wrapper = mountHeader({ showSettings: true });
wrapper.find('SettingsToggle').simulate('click');
wrapper.find('div.settingsToggle').simulate('click');
expect(wrapper.find(Settings).length).toBe(1);
expect(wrapper.find('Gear').prop('isSelected')).toBe(true);
+58 -51
View File
@@ -14,7 +14,7 @@ import { Link, Svg } from '../components';
import useOutsideClick from '../hooks/useOutsideClick';
import Settings from './Settings';
interface Props {
interface Props extends ThemeProps {
children?: React.ReactNode;
className?: string;
showSettings?: boolean;
@@ -35,28 +35,36 @@ function Header ({ children, className, showBackArrow, showSettings, text }: Pro
return (
<div className={className}>
<Container>
<Branding>
<div className='container'>
<div className='branding'>
{showBackArrow
? (
<BackLink to='/'>
<ArrowLeft/>
</BackLink>
)
: <Logo src={logo}/>
: (
<img
className='logo'
src={logo}
/>
)
}
<LogoText>{text || 'polkadot{.js}'}</LogoText>
</Branding>
<span className='logoText'>{text || 'polkadot{.js}'}</span>
</div>
{showSettings && (
<SettingsToggle onClick={_toggleSettings}>
<div
className='settingsToggle'
onClick={_toggleSettings}
>
<Gear isSelected={showActionsMenu} />
</SettingsToggle>
</div>
)}
{showActionsMenu && (
<Settings reference={actionsRef}/>
)}
{children}
</Container>
</div>
</div>
);
}
@@ -79,30 +87,6 @@ const ArrowLeft = styled(Svg).attrs(() => ({ src: ArrowLeftImage }))`
background: ${({ theme }: ThemeProps) => theme.labelColor};
`;
const Container = styled.div`
display: flex;
justify-content: space-between;
width: 100%;
border-bottom: 1px solid ${({ theme }: ThemeProps) => theme.inputBorderColor};
min-height: 70px;
`;
const Branding = styled.div`
display: flex;
justify-content: center;
align-items: center;
color: ${({ theme }: ThemeProps) => theme.labelColor};
font-family: ${({ theme }: ThemeProps) => theme.fontFamily};
text-align: center;
margin-left: 24px;
`;
const Logo = styled.img`
height: 28px;
width: 28px;
margin: 8px 12px 12px 0;
`;
interface GearProps {
isSelected: boolean;
}
@@ -117,23 +101,7 @@ const Gear = styled(Svg).attrs(() => ({ src: gear }))<GearProps>`
Gear.displayName = 'Gear';
const LogoText = styled.span`
color: ${({ theme }: ThemeProps) => theme.textColor};
font-family: ${({ theme }: ThemeProps) => theme.fontFamily};
font-size: 20px;
line-height: 27px;
`;
const SettingsToggle = styled.div`
align-self: center;
&:hover {
cursor: pointer;
}
`;
SettingsToggle.displayName = 'SettingsToggle';
export default styled(Header)`
export default React.memo(styled(Header)(({ theme }: Props) => `
max-width: 100%;
box-sizing: border-box;
font-weight: normal;
@@ -144,4 +112,43 @@ export default styled(Header)`
&& {
padding: 0 0 0;
}
`;
> .container {
display: flex;
justify-content: space-between;
width: 100%;
border-bottom: 1px solid ${theme.inputBorderColor};
min-height: 70px;
.branding {
display: flex;
justify-content: center;
align-items: center;
color: ${theme.labelColor};
font-family: ${theme.fontFamily};
text-align: center;
margin-left: 24px;
.logo {
height: 28px;
width: 28px;
margin: 8px 12px 12px 0;
}
.logoText {
color: ${theme.textColor};
font-family: ${theme.fontFamily};
font-size: 20px;
line-height: 27px;
}
}
.settingsToggle {
align-self: center;
&:hover {
cursor: pointer;
}
}
}
`));
@@ -10,12 +10,13 @@ import styled from 'styled-components';
import { ActionContext, ActionText } from '../components';
import Header from './Header';
interface Props {
interface Props extends ThemeProps {
className?: string;
step: number;
text: string;
}
export default function HeaderWithSteps ({ step, text }: Props): React.ReactElement<Props> {
function HeaderWithSteps ({ className, step, text }: Props): React.ReactElement<Props> {
const onAction = useContext(ActionContext);
const _onCancel = useCallback(() => {
@@ -23,40 +24,45 @@ export default function HeaderWithSteps ({ step, text }: Props): React.ReactElem
}, [onAction]);
return (
<Header text={text}>
<CreationSteps>
<Header
className={className}
text={text}
>
<div className='steps'>
<div>
<CurrentStep>{step}</CurrentStep>
<TotalSteps>/2</TotalSteps>
<span className='current'>{step}</span>
<span className='total'>/2</span>
</div>
<ActionText
onClick={_onCancel}
text='Cancel'
/>
</CreationSteps>
</div>
</Header>
);
}
const CreationSteps = styled.div`
align-items: center;
display: flex;
justify-content: space-between;
flex-grow: 1;
padding-right: 24px;
margin-top: 3px;
`;
export default React.memo(styled(HeaderWithSteps)(({ theme }: Props) => `
.current {
font-size: ${theme.labelFontSize};
line-height: ${theme.labelLineHeight};
color: ${theme.primaryColor};
font-weight: 600;
}
const CurrentStep = styled.span`
font-size: ${({ theme }: ThemeProps) => theme.labelFontSize};
line-height: ${({ theme }: ThemeProps) => theme.labelLineHeight};
color: ${({ theme }: ThemeProps) => theme.primaryColor};
font-weight: 600;
`;
.steps {
align-items: center;
display: flex;
justify-content: space-between;
flex-grow: 1;
padding-right: 24px;
margin-top: 3px;
}
const TotalSteps = styled.span`
font-size: ${({ theme }: ThemeProps) => theme.labelFontSize};
line-height: ${({ theme }: ThemeProps) => theme.labelLineHeight};
color: ${({ theme }: ThemeProps) => theme.textColor};
font-weight: 600;
`;
.total {
font-size: ${theme.labelFontSize};
line-height: ${theme.labelLineHeight};
color: ${theme.textColor};
font-weight: 600;
}
`));
+53 -49
View File
@@ -65,7 +65,7 @@ function Settings ({ className, reference }: Props): React.ReactElement<Props> {
reference={reference}
>
<div className='setting'>
<SettingTitle>Theme</SettingTitle>
<Title className='title'>Theme</Title>
<Switch
checked={themeContext.id === themes.dark.id}
checkedLabel='Dark'
@@ -74,16 +74,18 @@ function Settings ({ className, reference }: Props): React.ReactElement<Props> {
/>
</div>
<div className='setting'>
<SettingTitle>External QR accounts and Access</SettingTitle>
<CheckboxSetting
<Title className='title'>External QR accounts and Access</Title>
<Checkbox
checked={camera}
className='checkbox'
label='Allow Camera Access'
onChange={setCamera}
/>
</div>
<div className='setting'>
<SettingTitle>Display address format For:</SettingTitle>
<DropdownSetting
<Title className='title'>Display address format For:</Title>
<Dropdown
className='dropdown'
label=''
onChange={_onChangePrefix}
options={prefixOptions}
@@ -92,7 +94,8 @@ function Settings ({ className, reference }: Props): React.ReactElement<Props> {
</div>
{isPopup && (
<div className='setting'>
<OpenInNewWindowButton
<ActionText
className='openWindow'
icon={FullScreenIcon}
onClick={windowOpen}
text='Open extension in new window'
@@ -103,57 +106,58 @@ function Settings ({ className, reference }: Props): React.ReactElement<Props> {
);
}
const CheckboxSetting = styled(Checkbox)`
font-size: 15px;
font-weight: 600;
line-height: 20px;
color: ${({ theme }: ThemeProps) => theme.textColor};
label {
color: ${({ theme }: ThemeProps) => theme.textColor};
}
`;
const DropdownSetting = styled(Dropdown)`
background: ${({ theme }: ThemeProps) => theme.background};
margin-top: 9px;
margin-bottom: 12px;
width : 100%;
margin-right: 0;
`;
const SettingTitle = styled(Title)`
margin: 0;
`;
const OpenInNewWindowButton = styled(ActionText)`
span {
color: ${({ theme }: ThemeProps) => theme.textColor};
text-decoration: none;
font-weight: 600;
font-size: ${({ theme }: ThemeProps) => theme.fontSize};
line-height: ${({ theme }: ThemeProps) => theme.lineHeight};
}
${Svg} {
width: 20px;
height: 20px;
top: 4px;
background: ${({ theme }: ThemeProps) => theme.textColor};
}
`;
export default React.memo(styled(Settings)`
export default React.memo(styled(Settings)(({ theme }: Props) => `
margin-top: 56px;
right: 24px;
user-select: none;
.setting {
.openWindow {
span {
color: ${theme.textColor};
font-size: ${theme.fontSize};
font-weight: 600;
line-height: ${theme.lineHeight};
text-decoration: none;
}
${Svg} {
background: ${theme.textColor};
height: 20px;
top: 4px;
width: 20px;
}
}
> .setting {
padding: 0 16px;
max-width: 100%;
> .checkbox {
color: ${theme.textColor};
line-height: 20px;
font-size: 15px;
font-weight: 600;
label {
color: ${theme.textColor};
}
}
> .dropdown {
background: ${theme.background};
margin-bottom: 12px;
margin-top: 9px;
margin-right: 0;
width: 100%;
}
> .title {
margin: 0;
}
}
.setting+.setting {
padding-top: 18px;
border-top: 1px solid ${({ theme }: Props): string => theme.inputBorderColor};
border-top: 1px solid ${theme.inputBorderColor};
}
`);
`));