Skip to content

Commit

Permalink
feat(FullscreenModal): apply grid to modal content
Browse files Browse the repository at this point in the history
  • Loading branch information
ajkl2533 committed Dec 17, 2020
1 parent fb2832c commit cea34fb
Show file tree
Hide file tree
Showing 26 changed files with 327 additions and 443 deletions.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 0 additions & 5 deletions src/components/FullscreenModal/Content/Content.tsx

This file was deleted.

12 changes: 0 additions & 12 deletions src/components/FullscreenModal/Context/Context.tsx

This file was deleted.

7 changes: 0 additions & 7 deletions src/components/FullscreenModal/Context/Context.types.ts

This file was deleted.

38 changes: 25 additions & 13 deletions src/components/FullscreenModal/Footer/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import React, { useContext, useRef } from 'react';
import React, { useRef } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';

import { getColor, pxToRem } from '../../../utils/helpers';
import { FlexContainer } from '../../FlexContainer';
import { ScrollToTop } from '../ScrollToTop';
import { FullscreenModalProps } from '../FullscreenModal.types';
import ModalContext from '../Context/Context';
import { useStickyFooter } from '../hooks/useStickyFooter';
import { Col, Container, Row } from '../../layout';
import { FooterProps } from './Footer.types';

const BaseStickyFooter = styled.footer`
position: fixed;
Expand All @@ -18,21 +19,18 @@ const BaseStickyFooter = styled.footer`
border-top: 1px solid ${getColor('graphiteHB')};
`;
const BaseFooter = styled.footer`
background-color: ${getColor('graphite5H')};
border-top: 1px solid ${getColor('graphiteHB')};
padding-top: ${pxToRem(24)};
margin-top: ${pxToRem(40)};
`;

const FooterInnerContainer = styled.div<Pick<FullscreenModalProps, 'size'>>`
width: ${({ size, theme }) => pxToRem(theme.modals.size[size])};
margin: 0 auto;
`;

const Footer: React.FC = ({ children }) => {
const { size, modalRef } = useContext(ModalContext);
const Footer: React.FC<FooterProps> = ({
children,
width,
offset,
modalRef,
}) => {
const modalFooterRef = useRef(null);

const { isFixed, shouldShowScrollToTopButton } = useStickyFooter(
modalRef,
modalFooterRef,
Expand All @@ -46,7 +44,13 @@ const Footer: React.FC = ({ children }) => {
<>
{isFixed && (
<BaseStickyFooter as="div">
<FooterInnerContainer size={size}>{children}</FooterInnerContainer>
<Container>
<Row>
<Col cols={width} offset={offset}>
{children}
</Col>
</Row>
</Container>
</BaseStickyFooter>
)}
<BaseFooter ref={modalFooterRef}>
Expand All @@ -65,4 +69,12 @@ const Footer: React.FC = ({ children }) => {
);
};

Footer.propTypes = {
width: PropTypes.number.isRequired,
offset: PropTypes.number.isRequired,
modalRef: PropTypes.exact({
current: PropTypes.instanceOf(HTMLElement),
}).isRequired,
};

export default Footer;
5 changes: 5 additions & 0 deletions src/components/FullscreenModal/Footer/Footer.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface FooterProps {
width: number;
offset: number;
modalRef: React.MutableRefObject<HTMLElement>;
}
7 changes: 7 additions & 0 deletions src/components/FullscreenModal/FullscreenModal.enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,10 @@ export const FullscreenModalSizes = {
md: 'md',
sm: 'sm',
} as const;

export const FullscreenModalLayouts = {
single6: 'single-6',
single8: 'single-8',
sidebar46: 'sidebar-4-6',
sidebar48: 'sidebar-4-8',
} as const;
400 changes: 127 additions & 273 deletions src/components/FullscreenModal/FullscreenModal.stories.tsx

Large diffs are not rendered by default.

129 changes: 91 additions & 38 deletions src/components/FullscreenModal/FullscreenModal.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,14 @@
import React, { useRef } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import { isUndefined, noop } from 'ramda-adjunct';

import { getColor, getDepth, getModalSize } from '../../utils/helpers';
import { FlexContainer } from '../FlexContainer';
import ModalContext from './Context/Context';
import { getColor, getDepth } from '../../utils/helpers';
import ModalHeader from './Header/Header';
import ModalContent from './Content/Content';
import ModalSidebar from './Sidebar/Sidebar';
import ModalFooter from './Footer/Footer';
import { FullscreenModalSizes } from './FullscreenModal.enums';
import { FullscreenModalProps } from './FullscreenModal.types';

export interface FullscreenModalSubcomponents {
Header: typeof ModalHeader;
Content: typeof ModalContent;
Sidebar: typeof ModalSidebar;
Footer: typeof ModalFooter;
}
import { FullscreenModalLayouts } from './FullscreenModal.enums';
import { ColumnConfigMap, FullscreenModalProps } from './FullscreenModal.types';
import { Col, Container, Row } from '../layout';

const BaseModal = styled.div`
width: 100vw;
Expand All @@ -30,39 +21,101 @@ const BaseModal = styled.div`
z-index: ${getDepth('modal')};
`;

const ModalInnerContainer = styled(FlexContainer)<FullscreenModalProps>`
width: ${getModalSize};
margin: 0 auto;
`;
const columnConfigMap: ColumnConfigMap = {
[FullscreenModalLayouts.single6]: {
header: [6, 3],
sidebar: [0, 0],
content: [6, 3],
},
[FullscreenModalLayouts.single8]: {
header: [8, 2],
sidebar: [0, 0],
content: [8, 2],
},
[FullscreenModalLayouts.sidebar46]: {
header: [10, 1],
sidebar: [4, 1],
content: [6, 0],
},
[FullscreenModalLayouts.sidebar48]: {
header: [12, 0],
sidebar: [4, 0],
content: [8, 0],
},
};

const FullscreenModal: React.FC<FullscreenModalProps> &
FullscreenModalSubcomponents = ({ children, size, onClose }) => {
const FullscreenModal: React.FC<FullscreenModalProps> = ({
layout = FullscreenModalLayouts.single6,
header,
content,
sidebar,
footer,
onClose = noop,
}) => {
const modalRef = useRef<HTMLDivElement>(null);
const modalContext = {
size,
modalRef,
handleClose: onClose,
};

const {
header: headerConfig,
sidebar: sidebarConfig,
content: contentConfig,
} = columnConfigMap[layout];

const hasLayoutSidebar = sidebarConfig[0] > 0;
const totalContentWidth = contentConfig[0] + sidebarConfig[0];

if (hasLayoutSidebar && isUndefined(sidebar)) {
// eslint-disable-next-line no-console
console.warn(
`You chose to use modal layout with sidebar (current: ${layout}) but you didn't provide sidebar content.
You should either provide content in "sidebar" property or switch layout to "${FullscreenModalLayouts.single6}" or "${FullscreenModalLayouts.single8}"
`,
);
}

return (
<ModalContext.Provider value={modalContext}>
<BaseModal ref={modalRef}>
<ModalInnerContainer flexDirection="column" size={size}>
{children}
</ModalInnerContainer>
</BaseModal>
</ModalContext.Provider>
<BaseModal ref={modalRef}>
<Container>
<Row>
<Col cols={headerConfig[0]} offset={headerConfig[1]}>
<ModalHeader
handleClose={onClose}
modalRef={modalRef}
offset={headerConfig[1]}
width={totalContentWidth}
>
{header}
</ModalHeader>
</Col>
</Row>
<Row>
{hasLayoutSidebar && (
<Col cols={sidebarConfig[0]} offset={sidebarConfig[1]}>
{sidebar}
</Col>
)}
<Col cols={contentConfig[0]} offset={contentConfig[1]}>
{content}
<ModalFooter
modalRef={modalRef}
offset={headerConfig[1]}
width={totalContentWidth}
>
{footer}
</ModalFooter>
</Col>
</Row>
</Container>
</BaseModal>
);
};

FullscreenModal.propTypes = {
size: PropTypes.oneOf(Object.values(FullscreenModalSizes)),
header: PropTypes.node.isRequired,
content: PropTypes.node.isRequired,
footer: PropTypes.node.isRequired,
sidebar: PropTypes.node,
layout: PropTypes.oneOf(Object.values(FullscreenModalLayouts)),
onClose: PropTypes.func,
};

FullscreenModal.Header = ModalHeader;
FullscreenModal.Content = ModalContent;
FullscreenModal.Sidebar = ModalSidebar;
FullscreenModal.Footer = ModalFooter;

export default FullscreenModal;
18 changes: 15 additions & 3 deletions src/components/FullscreenModal/FullscreenModal.types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
import { FullscreenModalSizes } from './FullscreenModal.enums';
import {
FullscreenModalLayouts,
FullscreenModalSizes,
} from './FullscreenModal.enums';

export type Sizes = typeof FullscreenModalSizes[keyof typeof FullscreenModalSizes];

export type Layouts = typeof FullscreenModalLayouts[keyof typeof FullscreenModalLayouts];
export type ColumnConfig = Record<
'header' | 'sidebar' | 'content',
[number, number]
>;
export type ColumnConfigMap = Record<Layouts, ColumnConfig>;
export interface FullscreenModalProps {
size?: Sizes;
layout: Layouts;
header: React.ReactNode;
content: React.ReactNode;
footer: React.ReactNode;
sidebar?: React.ReactNode;
onClose?: () => void;
}
Loading

0 comments on commit cea34fb

Please sign in to comment.