mirror of
https://github.com/status-im/safe-react.git
synced 2025-01-13 11:34:08 +00:00
Components V2 (#562)
* components v2 * Fix type * Adding TextBox component and some minor changes * replacing harcoded color by the one defined in varibales * TextBox: Replacing div by p
This commit is contained in:
parent
2698dcb6e8
commit
8d81104894
3
src/components-v2/dataDisplay/DividerLine/arrow-down.svg
Normal file
3
src/components-v2/dataDisplay/DividerLine/arrow-down.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="21" viewBox="0 0 13 21">
|
||||
<path fill="#B2B5B2" fill-rule="evenodd" d="M8.7 11.266V0H4.27v11.266H0l6.484 9.172 6.493-9.172z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 195 B |
30
src/components-v2/dataDisplay/DividerLine/index.js
Normal file
30
src/components-v2/dataDisplay/DividerLine/index.js
Normal file
@ -0,0 +1,30 @@
|
||||
// @flow
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import Hairline from '~/components/layout/Hairline'
|
||||
import { sm, md } from '~/theme/variables'
|
||||
import ArrowDown from './arrow-down.svg'
|
||||
|
||||
const Wrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: ${md} 0;
|
||||
|
||||
img {
|
||||
margin: 0 ${sm};
|
||||
}
|
||||
`
|
||||
|
||||
type Props = {
|
||||
withArrow: boolean,
|
||||
}
|
||||
|
||||
const DividerLine = ({ withArrow }: Props) => (
|
||||
<Wrapper>
|
||||
{withArrow && <img src={ArrowDown} alt="Arrow Down" />}
|
||||
<Hairline />
|
||||
</Wrapper>
|
||||
)
|
||||
|
||||
export default DividerLine
|
21
src/components-v2/dataDisplay/TextBox/index.js
Normal file
21
src/components-v2/dataDisplay/TextBox/index.js
Normal file
@ -0,0 +1,21 @@
|
||||
// @flow
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import { border } from '~/theme/variables'
|
||||
|
||||
type Props = {
|
||||
children: React.Node,
|
||||
}
|
||||
|
||||
const Box = styled.p`
|
||||
padding: 10px;
|
||||
word-wrap: break-word;
|
||||
border: solid 2px ${border};
|
||||
`
|
||||
|
||||
const TextBox = ({ children }: Props) => {
|
||||
return <Box>{children}</Box>
|
||||
}
|
||||
|
||||
export default TextBox
|
3
src/components-v2/dataDisplay/index.js
Normal file
3
src/components-v2/dataDisplay/index.js
Normal file
@ -0,0 +1,3 @@
|
||||
// @flow
|
||||
export { default as DividerLine } from './DividerLine'
|
||||
export { default as TextBox } from './TextBox'
|
20
src/components-v2/feedback/Loader/index.jsx
Normal file
20
src/components-v2/feedback/Loader/index.jsx
Normal file
@ -0,0 +1,20 @@
|
||||
// @flow
|
||||
import React from 'react'
|
||||
import CircularProgress from '@material-ui/core/CircularProgress'
|
||||
import styled from 'styled-components'
|
||||
|
||||
const Wrapper = styled.div`
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
`
|
||||
|
||||
const Loader = () => (
|
||||
<Wrapper>
|
||||
<CircularProgress size={60} />
|
||||
</Wrapper>
|
||||
)
|
||||
|
||||
export default Loader
|
2
src/components-v2/feedback/index.js
Normal file
2
src/components-v2/feedback/index.js
Normal file
@ -0,0 +1,2 @@
|
||||
// @flow
|
||||
export { default as Loader } from './Loader'
|
7
src/components-v2/index.js
Normal file
7
src/components-v2/index.js
Normal file
@ -0,0 +1,7 @@
|
||||
// @flow
|
||||
export * from './dataDisplay'
|
||||
export * from './feedback'
|
||||
export * from './layouts'
|
||||
export * from './safeUtils'
|
||||
export * from './surfaces'
|
||||
export * from './utils'
|
46
src/components-v2/layouts/ListContentLayout/Layout.jsx
Normal file
46
src/components-v2/layouts/ListContentLayout/Layout.jsx
Normal file
@ -0,0 +1,46 @@
|
||||
// @flow
|
||||
import styled from 'styled-components'
|
||||
|
||||
export const Wrapper = styled.div`
|
||||
display: grid;
|
||||
grid-template-columns: 245px auto;
|
||||
grid-template-rows: 62px auto 25px;
|
||||
min-height: 500px;
|
||||
|
||||
.background {
|
||||
box-shadow: 1px 2px 10px 0 rgba(212, 212, 211, 0.59);
|
||||
background-color: white;
|
||||
}
|
||||
`
|
||||
export const Nav = styled.div`
|
||||
grid-column: 1/3;
|
||||
grid-row: 1;
|
||||
margin: 8px 0;
|
||||
padding: 16px 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
`
|
||||
|
||||
export const Menu = styled.div.attrs(() => ({ className: 'background' }))`
|
||||
grid-column: 1;
|
||||
grid-row: 2/4;
|
||||
border-right: solid 2px #e8e7e6;
|
||||
border-top-left-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
`
|
||||
|
||||
export const Content = styled.div.attrs(() => ({ className: 'background' }))`
|
||||
grid-column: 2;
|
||||
grid-row: 2;
|
||||
border-top-right-radius: 8px;
|
||||
`
|
||||
|
||||
export const Footer = styled.div.attrs(() => ({ className: 'background' }))`
|
||||
grid-column: 2;
|
||||
grid-row: 3;
|
||||
border-bottom-right-radius: 8px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
`
|
59
src/components-v2/layouts/ListContentLayout/List.jsx
Normal file
59
src/components-v2/layouts/ListContentLayout/List.jsx
Normal file
@ -0,0 +1,59 @@
|
||||
// @flow
|
||||
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
import cn from 'classnames'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
|
||||
// TODO: move these styles to a generic place
|
||||
import styles from './style'
|
||||
|
||||
const Wrapper = styled.div``
|
||||
|
||||
const Item = styled.div`
|
||||
border-bottom: solid 2px rgb(232, 231, 230);
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
`
|
||||
|
||||
const IconImg = styled.img`
|
||||
width: 20px;
|
||||
margin-right: 10px;
|
||||
`
|
||||
type Props = {
|
||||
items: Array<{
|
||||
id: string,
|
||||
name: string,
|
||||
iconUrl?: string,
|
||||
}>,
|
||||
activeItem: string,
|
||||
onItemClick: () => void,
|
||||
classes: Object,
|
||||
}
|
||||
|
||||
const List = ({ items, activeItem, onItemClick, classes }: Props) => {
|
||||
return (
|
||||
<Wrapper>
|
||||
{items.map(i => (
|
||||
<Item
|
||||
key={i.id}
|
||||
className={cn(
|
||||
classes.menuOption,
|
||||
activeItem === i.id && classes.active
|
||||
)}
|
||||
onClick={() => onItemClick(i.id)}
|
||||
>
|
||||
<div className="container">
|
||||
{i.iconUrl && <IconImg src={i.iconUrl} alt={i.name} />}
|
||||
<span>{i.name}</span>
|
||||
</div>
|
||||
</Item>
|
||||
))}
|
||||
</Wrapper>
|
||||
)
|
||||
}
|
||||
|
||||
export default withStyles(styles)(List)
|
10
src/components-v2/layouts/ListContentLayout/index.js
Normal file
10
src/components-v2/layouts/ListContentLayout/index.js
Normal file
@ -0,0 +1,10 @@
|
||||
// @flow
|
||||
import * as LayoutComponents from './Layout'
|
||||
import List from './List'
|
||||
|
||||
const ListContentLayout = {
|
||||
...LayoutComponents,
|
||||
List,
|
||||
}
|
||||
|
||||
export default ListContentLayout
|
66
src/components-v2/layouts/ListContentLayout/style.js
Normal file
66
src/components-v2/layouts/ListContentLayout/style.js
Normal file
@ -0,0 +1,66 @@
|
||||
// @flow
|
||||
import {
|
||||
xs,
|
||||
sm,
|
||||
md,
|
||||
border,
|
||||
secondary,
|
||||
bolderFont,
|
||||
background,
|
||||
largeFontSize,
|
||||
fontColor,
|
||||
screenSm,
|
||||
} from '~/theme/variables'
|
||||
|
||||
const styles = () => ({
|
||||
menuOption: {
|
||||
alignItems: 'center',
|
||||
borderRight: `solid 1px ${border}`,
|
||||
boxSizing: 'border-box',
|
||||
cursor: 'pointer',
|
||||
flexGrow: '1',
|
||||
flexShrink: '1',
|
||||
fontSize: '13px',
|
||||
justifyContent: 'center',
|
||||
lineHeight: '1.2',
|
||||
minWidth: '0',
|
||||
padding: `${md} ${sm}`,
|
||||
width: '100%',
|
||||
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
borderRight: 'none',
|
||||
flexGrow: '0',
|
||||
fontSize: largeFontSize,
|
||||
justifyContent: 'flex-start',
|
||||
padding: `${md} 0 ${md} ${md}`,
|
||||
},
|
||||
'&:last-of-type': {
|
||||
borderRight: 'none',
|
||||
},
|
||||
'&:first-child': {
|
||||
borderTopLeftRadius: sm,
|
||||
},
|
||||
'& svg': {
|
||||
display: 'block',
|
||||
marginRight: xs,
|
||||
maxWidth: '16px',
|
||||
|
||||
[`@media (min-width: ${screenSm}px)`]: {
|
||||
marginRight: sm,
|
||||
},
|
||||
},
|
||||
'& .fill': {
|
||||
fill: fontColor,
|
||||
},
|
||||
},
|
||||
active: {
|
||||
backgroundColor: background,
|
||||
color: secondary,
|
||||
fontWeight: bolderFont,
|
||||
'& .fill': {
|
||||
fill: secondary,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export default styles
|
2
src/components-v2/layouts/index.js
Normal file
2
src/components-v2/layouts/index.js
Normal file
@ -0,0 +1,2 @@
|
||||
// @flow
|
||||
export { default as ListContentLayout } from './ListContentLayout'
|
77
src/components-v2/safeUtils/AddressInfo/index.js
Normal file
77
src/components-v2/safeUtils/AddressInfo/index.js
Normal file
@ -0,0 +1,77 @@
|
||||
// @flow
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import Paragraph from '~/components/layout/Paragraph'
|
||||
import EtherscanBtn from '~/components/EtherscanBtn'
|
||||
import CopyBtn from '~/components/CopyBtn'
|
||||
import Identicon from '~/components/Identicon'
|
||||
import Bold from '~/components/layout/Bold'
|
||||
import { xs, border } from '~/theme/variables'
|
||||
import Block from '~/components/layout/Block'
|
||||
|
||||
const Wrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.icon-section {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.data-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.address {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
`
|
||||
const StyledBlock = styled(Block)`
|
||||
font-size: 12px;
|
||||
line-height: 1.08;
|
||||
letter-spacing: -0.5;
|
||||
background-color: ${border};
|
||||
width: fit-content;
|
||||
padding: 5px 10px;
|
||||
margin-top: ${xs};
|
||||
border-radius: 3px;
|
||||
`
|
||||
type Props = {
|
||||
safeName: string,
|
||||
safeAddress: string,
|
||||
ethBalance: string,
|
||||
}
|
||||
|
||||
const AddressInfo = ({ safeName, safeAddress, ethBalance }: Props) => {
|
||||
return (
|
||||
<Wrapper>
|
||||
<div className="icon-section">
|
||||
<Identicon address={safeAddress} diameter={32} />
|
||||
</div>
|
||||
<div className="data-section">
|
||||
{safeName && (
|
||||
<Paragraph weight="bolder" noMargin>
|
||||
{safeName}
|
||||
</Paragraph>
|
||||
)}
|
||||
<div className="address">
|
||||
<Paragraph weight="bolder" noMargin>
|
||||
{safeAddress}
|
||||
</Paragraph>
|
||||
<CopyBtn content={safeAddress} />
|
||||
<EtherscanBtn type="address" value={safeAddress} />
|
||||
</div>
|
||||
{ethBalance && (
|
||||
<StyledBlock>
|
||||
<Paragraph noMargin>
|
||||
Balance: <Bold>{`${ethBalance} ETH`}</Bold>
|
||||
</Paragraph>
|
||||
</StyledBlock>
|
||||
)}
|
||||
</div>
|
||||
</Wrapper>
|
||||
)
|
||||
}
|
||||
|
||||
export default AddressInfo
|
2
src/components-v2/safeUtils/index.js
Normal file
2
src/components-v2/safeUtils/index.js
Normal file
@ -0,0 +1,2 @@
|
||||
// @flow
|
||||
export { default as AddressInfo } from './AddressInfo'
|
48
src/components-v2/surfaces/Collapse/index.js
Normal file
48
src/components-v2/surfaces/Collapse/index.js
Normal file
@ -0,0 +1,48 @@
|
||||
// @flow
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
import CollapseMUI from '@material-ui/core/Collapse'
|
||||
import IconButton from '@material-ui/core/IconButton'
|
||||
import ExpandLess from '@material-ui/icons/ExpandLess'
|
||||
import ExpandMore from '@material-ui/icons/ExpandMore'
|
||||
|
||||
const Wrapper = styled.div``
|
||||
|
||||
const Header = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
`
|
||||
|
||||
const Title = styled.div``
|
||||
|
||||
type Props = {
|
||||
title: string,
|
||||
children: React.Node,
|
||||
description: React.Node,
|
||||
}
|
||||
|
||||
const Collapse = ({ title, description, children }: Props) => {
|
||||
const [open, setOpen] = React.useState(false)
|
||||
|
||||
const handleClick = () => {
|
||||
setOpen(!open)
|
||||
}
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<Title>{title}</Title>
|
||||
<Header>
|
||||
<IconButton disableRipple size="small" onClick={handleClick}>
|
||||
{open ? <ExpandLess /> : <ExpandMore />}
|
||||
</IconButton>
|
||||
{description}
|
||||
</Header>
|
||||
|
||||
<CollapseMUI in={open} timeout="auto" unmountOnExit>
|
||||
{children}
|
||||
</CollapseMUI>
|
||||
</Wrapper>
|
||||
)
|
||||
}
|
||||
|
||||
export default Collapse
|
2
src/components-v2/surfaces/index.js
Normal file
2
src/components-v2/surfaces/index.js
Normal file
@ -0,0 +1,2 @@
|
||||
// @flow
|
||||
export { default as Collapse } from './Collapse'
|
2
src/components-v2/utils/index.js
Normal file
2
src/components-v2/utils/index.js
Normal file
@ -0,0 +1,2 @@
|
||||
// @flow
|
||||
export * from './modals'
|
79
src/components-v2/utils/modals/GenericModal/index.js
Normal file
79
src/components-v2/utils/modals/GenericModal/index.js
Normal file
@ -0,0 +1,79 @@
|
||||
// @flow
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
import Close from '@material-ui/icons/Close'
|
||||
import { makeStyles, createStyles } from '@material-ui/core/styles'
|
||||
import IconButton from '@material-ui/core/IconButton'
|
||||
|
||||
import Modal from '~/components/Modal'
|
||||
import Hairline from '~/components/layout/Hairline'
|
||||
|
||||
const TitleSection = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 10px 20px;
|
||||
`
|
||||
const BodySection = styled.div`
|
||||
padding: 10px 20px;
|
||||
max-height: 460px;
|
||||
overflow-y: auto;
|
||||
`
|
||||
const FooterSection = styled.div`
|
||||
margin: 10px 20px;
|
||||
`
|
||||
|
||||
const StyledClose = styled(Close)`
|
||||
&& {
|
||||
height: 35px;
|
||||
width: 35px;
|
||||
}
|
||||
`
|
||||
|
||||
const useStyles = makeStyles(() =>
|
||||
createStyles({
|
||||
paper: {
|
||||
height: 'auto',
|
||||
position: 'static',
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
type Props = {
|
||||
title: string,
|
||||
body: React.Node,
|
||||
footer: React.Node,
|
||||
onClose: () => void,
|
||||
}
|
||||
|
||||
const GenericModal = ({ title, body, footer, onClose }: Props) => {
|
||||
const classes = useStyles()
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="GenericModal"
|
||||
description="GenericModal"
|
||||
handleClose={onClose}
|
||||
paperClassName={classes.paper}
|
||||
open
|
||||
>
|
||||
<TitleSection>
|
||||
{title}
|
||||
<IconButton onClick={onClose} disableRipple>
|
||||
<StyledClose />
|
||||
</IconButton>
|
||||
</TitleSection>
|
||||
|
||||
<Hairline />
|
||||
<BodySection>{body}</BodySection>
|
||||
|
||||
{footer && (
|
||||
<>
|
||||
<Hairline />
|
||||
<FooterSection>{footer}</FooterSection>
|
||||
</>
|
||||
)}
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
export default GenericModal
|
3
src/components-v2/utils/modals/index.js
Normal file
3
src/components-v2/utils/modals/index.js
Normal file
@ -0,0 +1,3 @@
|
||||
// @flow
|
||||
export { default as GenericModal } from './GenericModal'
|
||||
export * from './utils'
|
53
src/components-v2/utils/modals/utils.js
Normal file
53
src/components-v2/utils/modals/utils.js
Normal file
@ -0,0 +1,53 @@
|
||||
// @flow
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import Paragraph from '~/components/layout/Paragraph'
|
||||
import Button from '~/components/layout/Button'
|
||||
import { lg } from '~/theme/variables'
|
||||
|
||||
const StyledParagraph = styled(Paragraph)`
|
||||
&& {
|
||||
font-size: ${lg};
|
||||
}
|
||||
`
|
||||
export const ModalTitle = ({ title }: { title: string }) => {
|
||||
return (
|
||||
<StyledParagraph weight="bolder" noMargin>
|
||||
{title}
|
||||
</StyledParagraph>
|
||||
)
|
||||
}
|
||||
|
||||
const FooterWrapper = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
`
|
||||
|
||||
export const ModalFooterConfirmation = ({
|
||||
okText,
|
||||
cancelText,
|
||||
handleOk,
|
||||
handleCancel,
|
||||
}: {
|
||||
okText: string,
|
||||
cancelText: string,
|
||||
handleOk: () => void,
|
||||
handleCancel: () => void,
|
||||
}) => {
|
||||
return (
|
||||
<FooterWrapper>
|
||||
<Button minWidth={130} onClick={handleCancel}>
|
||||
{cancelText}
|
||||
</Button>
|
||||
<Button
|
||||
color="primary"
|
||||
minWidth={130}
|
||||
onClick={handleOk}
|
||||
variant="contained"
|
||||
>
|
||||
{okText}
|
||||
</Button>
|
||||
</FooterWrapper>
|
||||
)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user