Skip to content

Commit

Permalink
Merge pull request #32 from acl-services/UX-433/migrate-rawbutton
Browse files Browse the repository at this point in the history
UX-433 Migrate RawButton 🐐
  • Loading branch information
mikrotron authored Feb 21, 2019
2 parents 09a8053 + e09c348 commit 9c28485
Show file tree
Hide file tree
Showing 21 changed files with 268 additions and 47 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
**/node_modules/*
16 changes: 16 additions & 0 deletions .storybook/assets/styles/common.styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import styled from "styled-components";
import stylers from "@paprika/stylers";

// Common Storybook story styles

export const Story = styled.div`
padding: ${stylers.spacer(3)};
`;

export const CenteredStory = styled.div`
align-items: center;
display: flex;
height: 100vh;
justify-content: center;
width: 100%;
`;
32 changes: 17 additions & 15 deletions packages/Popover/Popover.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { Component } from "react";
import memoizeOne from "memoize-one";
import { func, node, bool, string, number, oneOf, oneOfType } from "prop-types";
import PropTypes from "prop-types";
import throttle from "lodash.throttle";
import tokens from "@paprika/tokens";
import isInsideBoundaries from "./helpers/isInsideBoundaries";
Expand Down Expand Up @@ -33,37 +33,37 @@ const throttleDelay = 20;

const propTypes = {
/** Where the popover content is positioned relative to the trigger or getPositioningElement. */
align: oneOf(["top", "right", "bottom", "left"]),
align: PropTypes.oneOf(["top", "right", "bottom", "left"]),

/** Content of the popover */
children: node.isRequired,
children: PropTypes.node.isRequired,

/** Displays as a "tooltip" style with white text on black background. */
isDark: bool,
isDark: PropTypes.bool,

/** Activated by mouseOver / focus instead of onClick. */
isEager: bool,
isEager: PropTypes.bool,

/** How "controlled" popovers are shown / hidden. */
isOpen: bool,
isOpen: PropTypes.bool,

/** How "uncontrolled" popovers can be rendered open by default. */
defaultIsOpen: bool,
defaultIsOpen: PropTypes.bool,

/** Maximum width of popover content. Use of a number will imply px units and is recommended. */
maxWidth: oneOfType([string, number]),
maxWidth: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

/** Callback to fire when user closes popover. */
onClose: func,
onClose: PropTypes.func,

/** Distance, in px, between popover content edge and trigger / getPositioningElement. */
offset: number,
offset: PropTypes.number,

/** Function that provides DOM element to use as target for positioning the popover. */
getPositioningElement: func,
getPositioningElement: PropTypes.func,

/** Function that provides the scrolling DOM element that contains the popover. */
getScrollContainer: func,
getScrollContainer: PropTypes.func,
};

const defaultProps = {
Expand All @@ -79,7 +79,7 @@ const defaultProps = {
getScrollContainer: null,
};

export default class Popover extends Component {
class Popover extends Component {
constructor(props) {
super(props);

Expand All @@ -89,7 +89,7 @@ export default class Popover extends Component {
this.$tip = null; // this ref comes from a callback of the <Tip /> component

const portalNode = document.createElement("div");
portalNode.setAttribute("data-paprika-type", "Popover");
// portalNode.setAttribute("data-paprika-type", "Popover");
this.$portal = document.body.appendChild(portalNode);

this.state = {
Expand Down Expand Up @@ -237,7 +237,7 @@ export default class Popover extends Component {
};

// eslint is forcing to put handleReposition before ComponentDidMount
// eslint-disable-next-line
// eslint-disable-next-line react/sort-comp
handleReposition = throttle(() => {
if (this.isOpen()) {
const scrollContainer =
Expand Down Expand Up @@ -406,3 +406,5 @@ Popover.Trigger = Trigger;
Popover.Content = Content;
Popover.Card = Card;
Popover.Tip = Tip;

export default Popover;
4 changes: 2 additions & 2 deletions packages/Popover/components/Card/Card.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react";
import { node } from "prop-types";
import PropTypes from "prop-types";
import { PopoverContext } from "../../Popover";
import CardStyled from "./Card.styles";

Expand All @@ -12,7 +12,7 @@ const Card = ({ children }) => (
Card.displayName = "Popover.Card";

Card.propTypes = {
children: node.isRequired,
children: PropTypes.node.isRequired,
};

export default Card;
10 changes: 6 additions & 4 deletions packages/Popover/components/Content/Content.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import React, { Component } from "react";
import ReactDOM from "react-dom";
import { number, node } from "prop-types";
import PropTypes from "prop-types";
import isCurrentTargetFocused from "../../helpers/isCurrentTargetFocused";
import { PopoverContext } from "../../Popover";
import { consts as PopoverConstants } from "../../Popover.styles";
import { ContentStyled } from "./Content.styles";

const propTypes = {
children: node.isRequired,
zIndex: number,
children: PropTypes.node.isRequired,
zIndex: PropTypes.number,
};

const defaultProps = {
zIndex: 1,
};

export default class Content extends Component {
class Content extends Component {
handleMouseEvent = (isEager, onDelayedClose, onDelayedOpen) => event => {
if (!isEager) return;
if (event.type === "mouseover") {
Expand Down Expand Up @@ -96,3 +96,5 @@ Content.displayName = "Popover.Content";

Content.propTypes = propTypes;
Content.defaultProps = defaultProps;

export default Content;
19 changes: 11 additions & 8 deletions packages/Popover/components/Tip/Tip.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import React from "react";
import ReactDOM from "react-dom";
import { number } from "prop-types";
import PropTypes from "prop-types";
import tokens from "@paprika/tokens";
import { TipStyled } from "./Tip.styles";
import { PopoverContext } from "../../Popover";

const propTypes = {
zIndex: PropTypes.number,
};

const defaultProps = {
zIndex: 2,
};

const Tip = props => (
<PopoverContext.Consumer>
{({ tip, refTip, isDark, isOpen, portalElement }) => {
Expand Down Expand Up @@ -32,12 +40,7 @@ const Tip = props => (

Tip.displayName = "Popover.Tip";

Tip.propTypes = {
zIndex: number,
};

Tip.defaultProps = {
zIndex: 2,
};
Tip.propTypes = propTypes;
Tip.defaultProps = defaultProps;

export default Tip;
20 changes: 9 additions & 11 deletions packages/Popover/components/Trigger/Trigger.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import React, { Component } from "react";
import { node, func, oneOfType } from "prop-types";
import styled from "styled-components";
import { PopoverContext } from "../../Popover";
import PropTypes from "prop-types";
import RawButton from "@paprika/raw-button";

// TODO: migrate actual <RawButton> component
const RawButton = styled.div`
display: inline-block;
`;
import { PopoverContext } from "../../Popover";

const propTypes = {
children: oneOfType([func, node]).isRequired,
children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]).isRequired,
};

export default class Trigger extends Component {
class Trigger extends Component {
handleTriggerEvent = (isEager, isOpen, onClick, onDelayedClose, onDelayedOpen, onOpen) => event => {
if (isEager && (event.type === "mouseover" || event.type === "focus")) {
if (event.type === "mouseover") {
Expand Down Expand Up @@ -42,12 +38,12 @@ export default class Trigger extends Component {
onMouseOver={handler}
onMouseOut={handler}
onFocus={handler}
tabIndex={0}
onBlur={handler}
>
{this.props.children}
</RawButton>
) : (
<RawButton data-qa-anchor="popover-trigger" onClick={handler} tabIndex={0} role="button">
<RawButton data-qa-anchor="popover-trigger" onClick={handler}>
{this.props.children}
</RawButton>
);
Expand All @@ -63,3 +59,5 @@ export default class Trigger extends Component {
Trigger.displayName = "Popover.Trigger";

Trigger.propTypes = propTypes;

export default Trigger;
2 changes: 1 addition & 1 deletion packages/Popover/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"dependencies": {
"@paprika/tokens": "^0.0.1",
"lodash.throttle": "^4.1.1",
"prop-types": "^15.6.2"
"prop-types": "^15.7.2"
},
"peerDependencies": {
"react": "^16.4.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/Popover/stories/examples/Basic.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { Component } from "react";
import { text, number, select } from "@storybook/addon-knobs";
import styled from "styled-components";
import { CenteredStory } from "../Popover.stories.styles";
import { CenteredStory } from "storybook/assets/styles/common.styles";
import Popover from "../../Popover";

const Gap = styled.div`
Expand Down
3 changes: 2 additions & 1 deletion packages/Popover/stories/examples/Controlled.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { Component } from "react";
import { CenteredStory } from "storybook/assets/styles/common.styles";

import Popover from "../../Popover";
import { CenteredStory } from "../Popover.stories.styles";

export default class PopoverStory extends Component {
state = {
Expand Down
2 changes: 1 addition & 1 deletion packages/Popover/stories/examples/PositioningElement.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { Component } from "react";
import { select } from "@storybook/addon-knobs";
import styled from "styled-components";
import { CenteredStory } from "../Popover.stories.styles";
import { CenteredStory } from "storybook/assets/styles/common.styles";
import Popover from "../../Popover";

const PositioningElementStyled = styled.div`
Expand Down
2 changes: 1 addition & 1 deletion packages/Popover/stories/examples/ScrollContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { Component } from "react";
import { select, text, number } from "@storybook/addon-knobs";
import { func } from "prop-types";
import styled from "styled-components";
import { CenteredStory } from "../Popover.stories.styles";
import { CenteredStory } from "storybook/assets/styles/common.styles";
import Popover from "../../Popover";

const PopoverContainer = styled.div`
Expand Down
2 changes: 1 addition & 1 deletion packages/Popover/stories/examples/Transformed.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { Component } from "react";
import styled from "styled-components";
import { CenteredStory } from "../Popover.stories.styles";
import { CenteredStory } from "storybook/assets/styles/common.styles";
import Popover from "../../Popover";

const TransformedStory = styled(CenteredStory)`
Expand Down
2 changes: 1 addition & 1 deletion packages/Popover/stories/examples/WithTriggers.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable jsx-a11y/mouse-events-have-key-events */
import React, { Component } from "react";
import styled from "styled-components";
import { CenteredStory } from "../Popover.stories.styles";
import { CenteredStory } from "storybook/assets/styles/common.styles";
import Popover from "../../Popover";

const Icon = styled.span`
Expand Down
94 changes: 94 additions & 0 deletions packages/RawButton/RawButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import React from "react";
import PropTypes from "prop-types";

import RawButtonStyled from "./RawButton.styles";

const propTypes = {
ariaText: PropTypes.string,
buttonRef: PropTypes.shape({ current: PropTypes.instanceOf(Element) }),
canPropagate: PropTypes.bool,
children: PropTypes.node.isRequired,
className: PropTypes.string,
isDisabled: PropTypes.bool,
onClick: PropTypes.func,
tabIndex: PropTypes.number,
role: PropTypes.string,
};

const defaultProps = {
ariaText: null,
buttonRef: null,
canPropagate: true,
className: null,
isDisabled: false,
onClick: () => {},
role: "button",
tabIndex: 0,
};

class RawButton extends React.Component {
constructor(props) {
super(props);
this.setRef(props);
}

componentDidUpdate() {
this.setRef(this.props);
}

setRef(props) {
this.$rawButton = props.buttonRef || React.createRef();
}

handleKeyDown = event => {
if (
// Prevent scrolling the page with a spacerbar keypress
event.key === " " ||
// Prevent submitting forms in IE/Edge with and enter keypress
event.key === "Enter"
) {
event.preventDefault();
}
};

handleKeyUp = event => {
if (this.props.isDisabled || (!this.props.canPropagate && event.target !== this.$rawButton.current)) {
return;
}
if (event.key === " " || event.key === "Enter") {
this.props.onClick(event);
}
};

handleClick = event => {
if (!this.props.canPropagate) event.stopPropagation();
if (!this.props.isDisabled) this.props.onClick(event);
};

render() {
const { ariaText, buttonRef, canPropagate, children, isDisabled, tabIndex, ...moreProps } = this.props;
if (ariaText) moreProps["aria-label"] = ariaText;

return (
<RawButtonStyled
aria-disabled={isDisabled}
innerRef={this.$rawButton}
isDisabled={isDisabled}
onClick={this.handleClick}
onKeyDown={this.handleKeyDown}
onKeyUp={this.handleKeyUp}
tabIndex={isDisabled ? -1 : tabIndex}
{...moreProps}
>
{children}
</RawButtonStyled>
);
}
}

RawButton.displayName = "RawButton";

RawButton.propTypes = propTypes;
RawButton.defaultProps = defaultProps;

export default RawButton;
Loading

0 comments on commit 9c28485

Please sign in to comment.