feat: refactor out overlay component and use it to implement click-outside

This commit is contained in:
fragosti
2018-11-07 20:53:25 -08:00
parent c0d8ceca82
commit 4181a040b5
5 changed files with 91 additions and 70 deletions

View File

@@ -1,12 +1,13 @@
import * as _ from 'lodash';
import * as React from 'react';
import { ColorOption } from '../../style/theme';
import { ColorOption, completelyTransparent } from '../../style/theme';
import { zIndex } from '../../style/z_index';
import { Container } from './container';
import { Flex } from './flex';
import { Icon } from './icon';
import { Overlay } from './overlay';
import { Text } from './text';
export interface DropdownItemConfig {
@@ -27,12 +28,12 @@ export interface DropdownState {
export class Dropdown extends React.Component<DropdownProps, DropdownState> {
public static defaultProps = {
items: [
{
text: 'Item 1',
},
{
text: 'Item 2',
},
// {
// text: 'Item 1',
// },
// {
// text: 'Item 2',
// },
],
};
public state: DropdownState = {
@@ -44,48 +45,57 @@ export class Dropdown extends React.Component<DropdownProps, DropdownState> {
const hasItems = !_.isEmpty(items);
const borderRadius = isOpen ? '4px 4px 0px 0px' : '4px';
return (
<Container position="relative">
<Container
cursor={hasItems ? 'pointer' : undefined}
onClick={this._handleDropdownClick}
hasBoxShadow={true}
borderRadius={borderRadius}
border="1px solid"
borderColor={ColorOption.feintGrey}
padding="0.8em"
borderBottom="1px solid"
>
<Flex justify="space-between">
<Text fontSize="16px" lineHeight="19px" fontColor={ColorOption.darkGrey}>
{value}
</Text>
<Container>
<Text fontSize="16px" lineHeight="17px" fontColor={ColorOption.lightGrey}>
{label}
</Text>
{hasItems && (
<Container marginLeft="5px" display="inline-block" position="relative" bottom="2px">
<Icon padding="3px" icon="chevron" width={12} stroke={ColorOption.grey} />
</Container>
)}
</Container>
</Flex>
</Container>
<React.Fragment>
{isOpen && (
<Container
width="100%"
position="absolute"
<Overlay
zIndex={zIndex.dropdownItems - 1}
backgroundColor={completelyTransparent}
onClick={this._closeDropdown}
backgroundColor={ColorOption.white}
hasBoxShadow={true}
zIndex={zIndex.dropdownItems}
>
{_.map(items, (item, index) => (
<DropdownItem key={item.text} {...item} isLast={index === items.length - 1} />
))}
</Container>
/>
)}
</Container>
<Container position="relative">
<Container
cursor={hasItems ? 'pointer' : undefined}
onClick={this._handleDropdownClick}
hasBoxShadow={true}
borderRadius={borderRadius}
border="1px solid"
borderColor={ColorOption.feintGrey}
padding="0.8em"
borderBottom="1px solid"
>
<Flex justify="space-between">
<Text fontSize="16px" lineHeight="19px" fontColor={ColorOption.darkGrey}>
{value}
</Text>
<Container>
<Text fontSize="16px" lineHeight="17px" fontColor={ColorOption.lightGrey}>
{label}
</Text>
{hasItems && (
<Container marginLeft="5px" display="inline-block" position="relative" bottom="2px">
<Icon padding="3px" icon="chevron" width={12} stroke={ColorOption.grey} />
</Container>
)}
</Container>
</Flex>
</Container>
{isOpen && (
<Container
width="100%"
position="absolute"
onClick={this._closeDropdown}
backgroundColor={ColorOption.white}
hasBoxShadow={true}
zIndex={zIndex.dropdownItems}
>
{_.map(items, (item, index) => (
<DropdownItem key={item.text} {...item} isLast={index === items.length - 1} />
))}
</Container>
)}
</Container>
</React.Fragment>
);
}
private readonly _handleDropdownClick = (): void => {

View File

@@ -1,38 +1,30 @@
import * as _ from 'lodash';
import * as React from 'react';
import { ColorOption, overlayBlack, styled } from '../../style/theme';
import { Container } from './container';
import { Flex } from './flex';
import { Icon } from './icon';
import { overlayBlack, styled } from '../../style/theme';
import { zIndex } from '../../style/z_index';
export interface OverlayProps {
className?: string;
onClose?: () => void;
zIndex?: number;
backgroundColor?: string;
}
const PlainOverlay: React.StatelessComponent<OverlayProps> = ({ children, className, onClose }) => (
<Flex height="100vh" className={className}>
<Container position="absolute" top="0px" right="0px">
<Icon height={18} width={18} color={ColorOption.white} icon="closeX" onClick={onClose} padding="2em 2em" />
</Container>
<div>{children}</div>
</Flex>
);
export const Overlay = styled(PlainOverlay)`
export const Overlay =
styled.div <
OverlayProps >
`
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: ${props => props.zIndex}
background-color: ${overlayBlack};
background-color: ${props => props.backgroundColor};
`;
Overlay.defaultProps = {
zIndex: 100,
zIndex: zIndex.overlayDefault,
backgroundColor: overlayBlack,
};
Overlay.displayName = 'Overlay';

View File

@@ -1,5 +1,10 @@
import * as React from 'react';
import { ColorOption, overlayBlack, styled } from '../style/theme';
import { Container } from './ui/container';
import { Flex } from './ui/flex';
import { Icon } from './ui/icon';
import { Overlay } from './ui/overlay';
import { ZeroExInstantContainer } from './zero_ex_instant_container';
import { ZeroExInstantProvider, ZeroExInstantProviderProps } from './zero_ex_instant_provider';
@@ -13,8 +18,20 @@ export const ZeroExInstantOverlay: React.StatelessComponent<ZeroExInstantOverlay
const { onClose, zIndex, ...rest } = props;
return (
<ZeroExInstantProvider {...rest}>
<Overlay onClose={onClose} zIndex={zIndex}>
<ZeroExInstantContainer />
<Overlay zIndex={zIndex}>
<Flex height="100vh">
<Container position="absolute" top="0px" right="0px">
<Icon
height={18}
width={18}
color={ColorOption.white}
icon="closeX"
onClick={onClose}
padding="2em 2em"
/>
</Container>
<ZeroExInstantContainer />
</Flex>
</Overlay>
</ZeroExInstantProvider>
);

View File

@@ -32,5 +32,6 @@ export const theme: Theme = {
export const transparentWhite = 'rgba(255,255,255,0.3)';
export const overlayBlack = 'rgba(0, 0, 0, 0.6)';
export const completelyTransparent = 'rga(0, 0, 0, 0)';
export { styled, css, keyframes, withTheme, ThemeProvider };

View File

@@ -1,6 +1,7 @@
export const zIndex = {
errorPopup: 1,
mainContainer: 2,
dropdownItems: 3,
panel: 4,
errorPopup: 10,
mainContainer: 20,
dropdownItems: 30,
panel: 40,
overlayDefault: 100,
};