feat: refactor out overlay component and use it to implement click-outside
This commit is contained in:
@@ -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 => {
|
||||
|
@@ -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';
|
||||
|
@@ -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>
|
||||
);
|
||||
|
@@ -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 };
|
||||
|
@@ -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,
|
||||
};
|
||||
|
Reference in New Issue
Block a user