Skip to content

Commit

Permalink
Merge pull request #426 from dcos-labs/mp/feat/fullscreen-view
Browse files Browse the repository at this point in the history
Adds FullscreenView component
  • Loading branch information
mperrotti authored Nov 4, 2019
2 parents b675727 + dcb6fef commit 7a30ccc
Show file tree
Hide file tree
Showing 14 changed files with 744 additions and 189 deletions.
5 changes: 5 additions & 0 deletions packages/fullscreenView/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# FullscreenView

The FullscreenView component should be used when we want to bring the user into a flow that does not have any of the usual app's chrome.

The FullscreenModal component can be used in cases where we don't want to remove all other content from the page.
67 changes: 67 additions & 0 deletions packages/fullscreenView/components/FullscrenView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import * as React from "react";
import { cx } from "emotion";
import Delegate from "react-delegate-component";
import { ButtonProps } from "../../button/components/ButtonBase";
import { flex, padding, flexItem } from "../../shared/styles/styleUtils";
import { modalContent, fullscreenModalHeader } from "../style";
import FullscreenViewHeader from "./FullscreenViewHeader";

interface FullscreenViewProps {
/** The primary button */
ctaButton?: React.ReactElement<ButtonProps>;
/** The text for the button that secondary button, which closes the modal */
closeText: React.ReactNode;
/** The title that appears in the header */
title: React.ReactNode;
/** The subtitle that appears in the header */
subtitle?: React.ReactNode;
/** Whether we automatically add padding to the body of the modal. */
isContentFlush?: boolean;
/** Custom header content component. ⚠️Use rarely and with caution⚠️ */
headerComponent?: React.ReactNode;
/** Function that gets called when the modal is closed */
onClose: (event?: React.SyntheticEvent<HTMLElement>) => void;
/** The base of the `data-cy` value. This is used for writing selectors in Cypress. */
cypressSelectorBase?: string;
}

class FullscreenView extends React.PureComponent<FullscreenViewProps, {}> {
public render() {
const {
children,
ctaButton,
closeText,
isContentFlush,
onClose,
title,
subtitle,
headerComponent,
cypressSelectorBase = "fullscreenView"
} = this.props;

return (
<div className={flex({ direction: "column" })}>
<div
className={cx(fullscreenModalHeader, padding("all", "xl"))}
data-cy={`${cypressSelectorBase}-header`}
>
<Delegate
to={headerComponent}
default={FullscreenViewHeader}
props={{ title, subtitle, ctaButton, closeText, onClose }}
/>
</div>
<div
className={cx(modalContent, flexItem("grow"), {
[padding("all", "xl")]: !isContentFlush
})}
data-cy={`${cypressSelectorBase}-content`}
>
{children}
</div>
</div>
);
}
}

export default FullscreenView;
1 change: 1 addition & 0 deletions packages/fullscreenView/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as FullscreenView } from "./components/FullscrenView";
107 changes: 107 additions & 0 deletions packages/fullscreenView/stories/fullscreenView.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import * as React from "react";
import { storiesOf } from "@storybook/react";
import { withReadme } from "storybook-readme";
import FullscreenView from "../components/FullscrenView";
import {
flex,
flexItem,
textSize,
tintContentSecondary,
padding
} from "../../shared/styles/styleUtils";
import { cx } from "emotion";
import { fullscreenModalTitle } from "../style";
import { SecondaryButton, PrimaryButton } from "../../button";
import { action } from "@storybook/addon-actions";
import {
ModalContent,
BorderedModalContent
} from "../../modal/stories/helpers/modalContents";

const onClose = () => {
alert("calling onClose");
};

const readme = require("../README.md");

storiesOf("FullscreenView", module)
.addDecorator(withReadme([readme]))
.add("default", () => (
<div style={{ height: "500px" }}>
<FullscreenView closeText="Close" title="Title" onClose={onClose}>
<ModalContent />
</FullscreenView>
</div>
))
.add("with additional header content", () => {
const HeaderContent = ({ ctaButton, closeText, title, onClose }) => (
<div className={cx(flex({ align: "center" }), flexItem("shrink"))}>
<div className={flexItem("grow")}>
<SecondaryButton onClick={onClose}>{closeText}</SecondaryButton>
</div>
<div className={cx(fullscreenModalTitle, flexItem("grow"))}>
<div className={textSize("l")}>{title}</div>
<div className={cx(tintContentSecondary, textSize("s"))}>
Some subheader
</div>
</div>
<div className={flexItem("grow")}>
<div className={cx(flex({ align: "center", justify: "flex-end" }))}>
<div className={flexItem("shrink")}>
<input type="checkbox" id="fauxToggle" />
<label htmlFor="fauxToggle">Faux toggle</label>
</div>
<div className={cx(flexItem("shrink"), padding("left", "s"))}>
{ctaButton}
</div>
</div>
</div>
</div>
);
return (
<div style={{ height: "500px" }}>
<FullscreenView
onClose={onClose}
title="Title"
closeText="Close"
ctaButton={
<PrimaryButton
onClick={action("handling CTA")}
aria-haspopup={true}
>
Continue
</PrimaryButton>
}
headerComponent={HeaderContent}
>
<ModalContent />
</FullscreenView>
</div>
);
})
.add("with flushed content", () => (
<div style={{ height: "500px" }}>
<FullscreenView
onClose={onClose}
title="Title"
closeText="Close"
isContentFlush={true}
ctaButton={
<PrimaryButton onClick={action("handling CTA")} aria-haspopup={true}>
Continue
</PrimaryButton>
}
>
<BorderedModalContent horizPadding="32px" />
</FullscreenView>
</div>
))
.add("scrolling body", () => (
<div style={{ height: "500px" }}>
<FullscreenView closeText="Close" title="Title" onClose={onClose}>
<BorderedModalContent horizPadding="32px" />
<BorderedModalContent horizPadding="32px" />
<BorderedModalContent horizPadding="32px" />
</FullscreenView>
</div>
));
29 changes: 29 additions & 0 deletions packages/fullscreenView/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { css } from "emotion";
import {
themeBgSecondary,
borderColorDefault
} from "../design-tokens/build/js/designTokens";

export const fullscreenModalHeader = css`
background-color: ${themeBgSecondary};
box-sizing: border-box;
border-bottom: 1px solid ${borderColorDefault};
`;

export const fullscreenModalTitle = css`
text-align: center;
`;

export const fullscreenModalAction = {
dismiss: css`
text-align: left;
`,
cta: css`
text-align: right;
`
};

export const modalContent = css`
box-sizing: border-box;
overflow: auto;
`;
Loading

0 comments on commit 7a30ccc

Please sign in to comment.