Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UX-565 Takeover component migration #214

Merged
merged 50 commits into from
Nov 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
1721b81
UX-565 Takeover component
Oct 1, 2019
2a46201
UX-565 Animation; portal & inline; close by ESC; focus trap
Oct 1, 2019
60f1335
UX-565 Fix Portal/Inline switching
Oct 4, 2019
62d5ebc
UX-565 Lock body scroll
Oct 4, 2019
6415db7
UX-565 Ability to extend FocusTrap options
Oct 4, 2019
8e32525
UX-565 Compound components: Header, Content
Oct 4, 2019
4f5a37d
UX-565 Comment
Oct 4, 2019
e9e54e4
UX-565 Remove unnecessary dependencies
Oct 4, 2019
ea9dc83
UX-565 Story with nested SidePanel
Oct 4, 2019
a15f557
UX-565 Add @paprika/sidepanel to root
Oct 11, 2019
4cb26ff
UX-565 Fix: Takeover closing on esc press while overlapped sidepanel …
Oct 11, 2019
afea7b3
UX-565 Refactor Takeover.Content
Oct 11, 2019
b6babe2
UX-565 Remove console.log
Oct 11, 2019
4f75cc1
UX-565 Add spec
Nov 1, 2019
c4d8400
UX-565 SidePanel: always stop propagation
Nov 1, 2019
7b18725
UX-565 Takeover: always stop propagation
Nov 1, 2019
28b39d3
UX-565 SidePanel: always stop propagation
Nov 1, 2019
1d53aca
UX-565 Update yarn.lock
Nov 4, 2019
f7e9015
UX-565 Fix ESC key handling
Nov 4, 2019
fbd96f0
UX-565 Use data-pka-anchor
Nov 4, 2019
212f9f3
UX-565 Use displayName instead of componentType
Nov 4, 2019
e8c023f
UX-565 Use value from Tokens
Nov 4, 2019
37c9399
UX-565 Add "given" as allowed global to ESLint
Nov 4, 2019
370a322
UX-565 Sort style rules
Nov 4, 2019
3d6d4b0
UX-565 ESLint: ignore line with hack
Nov 4, 2019
5e05d8b
UX-565 README.md
Nov 4, 2019
749c9b7
UX-565 Using `css` prop instead of `styled.` helper function
Nov 4, 2019
9ef77fa
Merge branch 'master' into UX-565-migrate-takeover
Nov 8, 2019
a43184c
UX-565 Move LockBodyScroll to helpers package
Nov 8, 2019
9daa631
UX-565 Move Portal to helpers package
Nov 8, 2019
9d54ac1
UX-565 Remove an ability to inline Takeover
Nov 8, 2019
5dffdab
UX-565 Ignore ESLint warning
Nov 8, 2019
b6e1e68
UX-565 Update takeover deps
Nov 8, 2019
9e37434
UX-565 Format
Nov 8, 2019
0f0a413
UX-565 Update FocusTrap prop types
Nov 8, 2019
65724c5
UX-565 Update FocusTrap prop types
Nov 8, 2019
a1e044e
UX-565 Fix ButtonIcon styles
Nov 8, 2019
7e618a6
UX-565 Format
Nov 8, 2019
90b1550
UX-565 Get rid of `flex` shorthand
Nov 8, 2019
fe97cb3
UX-565 Move extractChildren to helpers package; move tokens.js
Nov 8, 2019
f9443c6
UX-565 Change defaultProps for FocusTrap
Nov 8, 2019
ab6a6a9
UX-565 Get rid of `css` attr
Nov 11, 2019
99c0be9
UX-565 Remove ESLint ignore comments
Nov 11, 2019
b3abde6
UX-565 Format
Nov 11, 2019
0b857ef
Merge branch 'master' into UX-565-migrate-takeover
Nov 11, 2019
dd568a2
UX-565 Downgrade @babel/runtime-corejs2
Nov 15, 2019
90ce4b0
UX-565 Fix ListBox
Nov 15, 2019
7405712
Merge branch 'master' into UX-565-migrate-takeover
Nov 15, 2019
fe5b4fb
UX-565 Fix SidePanel breaking change
Nov 15, 2019
8c62a0c
UX-565 Format code
Nov 15, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@
},
{
"files": ["packages/**/*.spec.js"],
"rules": { "import/no-extraneous-dependencies": "off" }
"rules": { "import/no-extraneous-dependencies": "off" },
"globals": {
"given": true
}
},
{
"files": ["packages/helpers/**/*.js"],
Expand Down
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module.exports = {
setupFilesAfterEnv: [
"jest-dom/extend-expect",
"@testing-library/react/cleanup-after-each",
"given2/setup",
"./testingHelpers/config.js",
],
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"eslint-plugin-jsx-a11y": "^6.1.1",
"eslint-plugin-react": "^7.11.1",
"eslint-plugin-react-hooks": "^1.6.0",
"given2": "^2.1.7",
"husky": "^2.5.0",
"jest": "^24.1.0",
"jest-cli": "^24.1.0",
Expand Down
4 changes: 3 additions & 1 deletion packages/Button/src/Button.styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,10 @@ function getIconColor(props) {
}

export const iconStyles = props => css`
align-items: center;
color: ${getIconColor(props)};
display: inline-block;
display: inline-flex;
justify-content: center;
margin: 0 ${tokens.spaceSm} 0 0;

svg {
Expand Down
2 changes: 1 addition & 1 deletion packages/FormElement/src/FormElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import React from "react";
import PropTypes from "prop-types";

import { ShirtSizes } from "@paprika/helpers/lib/customPropTypes";
import extractChildren from "@paprika/helpers/lib/extractChildren";
import isNil from "lodash/isNil";
import uuidv4 from "uuid/v4";
import isString from "lodash/isString";

import { extractChildren } from "./helpers/extractChildren";
import Description from "./components/Description";
import Instructions from "./components/Instructions";
import ErrorMessage from "./components/ErrorMessage";
Expand Down
33 changes: 21 additions & 12 deletions packages/SidePanel/src/SidePanel.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import React from "react";
import ReactDOM from "react-dom";
import PropTypes from "prop-types";
import { zValue } from "@paprika/stylers/lib/helpers";
import LockBodyScroll from "@paprika/helpers/lib/components/LockBodyScroll";
import Portal from "@paprika/helpers/lib/components/Portal";
import Dialog from "./components/Dialog";
import Footer from "./components/Footer";
import Header from "./components/Header";
import Overlay from "./components/Overlay";
import Trigger from "./components/Trigger";
import Group from "./components/Group";
import FocusTrap from "./components/FocusTrap";
import LockBodyScroll from "./components/LockBodyScroll";

import { extractChildren } from "./helpers";
import { useOffsetScroll, useEscapeKey } from "./hooks";
import { useOffsetScroll } from "./hooks";

const propTypes = {
/** The content for the SidePanel. */
Expand Down Expand Up @@ -64,7 +64,6 @@ function SidePanel(props) {
// Hooks
const [isVisible, setIsVisible] = React.useState(props.isOpen);
const offsetScroll = useOffsetScroll(offsetY);
useEscapeKey(isOpen, onClose);

// Refs
const refTrigger = React.useRef(null);
Expand Down Expand Up @@ -118,6 +117,14 @@ function SidePanel(props) {
...extendedFocusTrapOptions,
};

function handleEscKey(event) {
if (event.key === "Escape") {
DanilAgafonov marked this conversation as resolved.
Show resolved Hide resolved
event.stopPropagation();

onClose();
}
}

let sidePanel = null;

if (isVisible) {
Expand All @@ -134,6 +141,7 @@ function SidePanel(props) {
refHeader={refHeader}
offsetY={offsetScroll}
isOpen={isOpen}
onKeyDown={handleEscKey}
{...moreProps}
>
{children}
Expand All @@ -143,14 +151,15 @@ function SidePanel(props) {
if (isInline) {
sidePanel = dialog;
} else {
sidePanel = ReactDOM.createPortal(
<React.Fragment>
<FocusTrap focusTrapOptions={focusTrapOptions}>
<div>{dialog}</div>
</FocusTrap>
{overlayExtracted ? React.cloneElement(overlayExtracted, { onClose }) : null}
</React.Fragment>,
document.body
sidePanel = (
<Portal active={!isInline}>
<React.Fragment>
<FocusTrap focusTrapOptions={focusTrapOptions}>
<div>{dialog}</div>
</FocusTrap>
{overlayExtracted ? React.cloneElement(overlayExtracted, { onClose }) : null}
</React.Fragment>
</Portal>
);
}
}
Expand Down
8 changes: 0 additions & 8 deletions packages/SidePanel/src/components/LockBodyScroll.js

This file was deleted.

1 change: 0 additions & 1 deletion packages/SidePanel/src/hooks/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export { default as useEscapeKey } from "./useEscapeKey";
export { default as useOffsetScroll } from "./useOffsetScroll";
export { default as useFooterOffset } from "./useFooterOffset";
19 changes: 0 additions & 19 deletions packages/SidePanel/src/hooks/useEscapeKey.js

This file was deleted.

4 changes: 4 additions & 0 deletions packages/Takeover/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*

!readme.md
!lib/**
34 changes: 34 additions & 0 deletions packages/Takeover/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Takeover

Takeover component can toggle a full-screen view to help the user focus on complex UI tasks.
More information at the design system site: https://design.wegalvanize.com/p/components/takeover

## Components

You can use any of the following components to compose the Takeover:

```jsx
<Takeover.Header />
<Takeover.Content />
<Takeover.FocusTrap />
```

## Basic example

```jsx
<Takeover isOpen={isOpen} onClose={toggle}>
<Takeover.Header>
<Heading level={2}>Header</Heading>
</Takeover.Header>
<Takeover.Content>My content</Takeover.Content>
</Takeover>
```

## Props

- `children` (required)
- `isOpen` (required)
- `onClose`
- `onAfterOpen`
- `onAfterClose`
- `isInline`
31 changes: 31 additions & 0 deletions packages/Takeover/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "@paprika/takeover",
"version": "0.1.0",
"description": "Takeover component",
"author": "@paprika",
"main": "lib/index.js",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/acl-services/paprika/tree/master/packages/Takeover"
},
"publishConfig": {
"access": "public"
},
"dependencies": {
"@babel/runtime-corejs2": "^7.3.1",
"@paprika/button": "^0.2.2",
"@paprika/heading": "^0.2.2",
"@paprika/helpers": "^0.2.3",
"@paprika/stylers": "^0.2.2",
"@paprika/tokens": "^0.1.4",
"focus-trap-react": "^6.0.0",
"prop-types": "^15.7.2",
"react-transition-group": "^4.3.0"
},
"peerDependencies": {
"react": "^16.8.4",
"react-dom": "^16.8.4",
"styled-components": "^4.2.0"
DanilAgafonov marked this conversation as resolved.
Show resolved Hide resolved
}
}
106 changes: 106 additions & 0 deletions packages/Takeover/src/Takeover.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import React from "react";
import PropTypes from "prop-types";
import { Transition } from "react-transition-group";
import FocusTrapLibrary from "focus-trap-react";
import LockBodyScroll from "@paprika/helpers/lib/components/LockBodyScroll";
import Portal from "@paprika/helpers/lib/components/Portal";
import extractChildren from "@paprika/helpers/lib/extractChildren";
import * as styled from "./Takeover.styles";
import { animationDuration } from "./helpers/tokens";

const propTypes = {
/** The content for the Takeover. */
children: PropTypes.node.isRequired,

/** Control the visibility of the takeover */
isOpen: PropTypes.bool.isRequired,

/** Callback triggered when the takeover needs to be close */
onClose: PropTypes.func,

/** Callback once the takeover has been opened event */
onAfterOpen: PropTypes.func,

/** Callback once the takeover has been closed event */
onAfterClose: PropTypes.func,
};

const defaultProps = {
onAfterClose: () => {},
onClose: () => {},
onAfterOpen: () => {},
};

const Takeover = props => {
const { isOpen, onClose, onAfterClose, onAfterOpen, ...moreProps } = props;

function handleTransitionEnter(node) {
// https://github.com/reactjs/react-transition-group/blob/6dbadb594c7c2a2f15bc47afc6b4374cfd73c7c0/src/CSSTransition.js#L44
// eslint-disable-next-line no-unused-expressions
node.scrollTop;
}

const {
DanilAgafonov marked this conversation as resolved.
Show resolved Hide resolved
"Takeover.FocusTrap": focusTrapExtracted,
"Takeover.Header": headerExtracted,
"Takeover.Content": contentExtracted,
children,
} = extractChildren(moreProps.children, ["Takeover.FocusTrap", "Takeover.Header", "Takeover.Content"]);

const extendedFocusTrapOptions = focusTrapExtracted ? focusTrapExtracted.props : {};

const focusTrapOptions = {
fallbackFocus: () => document.createElement("div"),
...extendedFocusTrapOptions,
};

function handleEscKey(event) {
if (event.key === "Escape") {
event.stopPropagation();

onClose();
}
}

return (
<>
{isOpen && <LockBodyScroll />}
<Portal>
<Transition
DanilAgafonov marked this conversation as resolved.
Show resolved Hide resolved
mountOnEnter
unmountOnExit
in={isOpen}
timeout={animationDuration}
onEnter={handleTransitionEnter}
onEntered={onAfterOpen}
onExited={onAfterClose}
>
{state => (
<FocusTrapLibrary focusTrapOptions={focusTrapOptions}>
<styled.Wrapper
state={state}
role="dialog"
tabIndex="-1"
onKeyDown={handleEscKey}
data-pka-anchor="takeover"
>
{headerExtracted && <styled.Header {...headerExtracted.props} onClose={onClose} />}
{contentExtracted && (
<styled.ContentWrapper role="region" tabIndex="0">
{contentExtracted}
</styled.ContentWrapper>
)}
{children}
</styled.Wrapper>
</FocusTrapLibrary>
)}
</Transition>
</Portal>
</>
);
};

Takeover.propTypes = propTypes;
Takeover.defaultProps = defaultProps;

export default Takeover;
41 changes: 41 additions & 0 deletions packages/Takeover/src/Takeover.styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import styled, { css } from "styled-components";
import tokens from "@paprika/tokens";
import { animationDuration } from "./helpers/tokens";
import OriginalHeader from "./components/Header";

const openedCss = css`
opacity: 1;
`;

const closedCss = css`
opacity: 0;
`;

const states = {
entering: openedCss,
entered: openedCss,
exiting: closedCss,
exited: closedCss,
};

export const Wrapper = styled.div`
background-color: ${tokens.backgroundColor.level0};
bottom: 0;
display: flex;
flex-direction: column;
left: 0;
position: fixed;
right: 0;
top: 0;
transition: all ${animationDuration}ms ease;
${({ state }) => states[state]};
`;

export const Header = styled(OriginalHeader)`
flex: none;
`;

export const ContentWrapper = styled.div`
flex-grow: 1;
overflow-y: auto;
`;