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

Modify popup actions to allow confirmation requirements, allow multiple directions #164

Merged
merged 3 commits into from
Sep 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,21 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- `Fixed` for any bug fixes.
- `Security`

## [3.2.1] - 2019-90-11

- https://github.com/teamsnap/teamsnap-ui/pull/164

### Changed

- `Changed` Popupactions to support react elements as well as strings for body content.
- `Changed` Popupactions to support required confirmation from users

## [3.2.0] - 2019-09-10

- https://github.com/teamsnap/teamsnap-ui/pull/162

### Changed

- `Added` Components for Popup buttons

## [3.1.0] - 2019-09-09
Expand All @@ -28,7 +38,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

- `Added` CSS & HTML for modals
- `Security` Refactored theme variables for direct import
- `Added` Utilities more for colors and borders
- `Added` Utilities more for colors and borders

## [3.0.0] - 2019-09-04

Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@teamsnap/teamsnap-ui",
"version": "3.2.0",
"version": "3.2.1",
"description": "a CSS component library for TeamSnap",
"main": "dist/js/index.js",
"types": "dist/js/index.d.ts",
Expand Down
24 changes: 6 additions & 18 deletions src/js/components/Popup/Popup.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import * as React from "react";
import { storiesOf } from "@storybook/react";
import { select } from "@storybook/addon-knobs/react";
import PopupAction from "./PopupAction";
import PopupAction, { Action } from "./PopupAction";
import PopupConfirm from "./PopupConfirm";

const stories = storiesOf("Popup", module);

const actions = [
const actions: Array<Action> = [
{
text: "Log to console",
callback: () => {
console.log("Logging to console");
}
},
requiresConfirmation: true,
confirmationText: "Do you really want to write to the console?"
},
{
text: "JavaScript Alert",
Expand All @@ -21,31 +23,18 @@ const actions = [
}
];

const directionOptions = [
"default",
"down",
"right",
"left",
"rightHang",
"leftHang",
"overlay"
];
stories.add("PopupActions", () => {
const dir = select("direction", directionOptions);
const direction = dir === "default" ? null : dir;
return (
<PopupAction
text="..."
actions={actions}
direction={direction}
direction={["down", "left"]}
popupStyle={{ width: "150px" }}
/>
);
});

stories.add("PopupConfirm", () => {
const dir = select("direction", directionOptions);
const direction = dir === "default" ? null : dir;
const popupText = (
<h4>Do you really want to hurt me? Do you really want to make me cry?</h4>
);
Expand All @@ -61,7 +50,6 @@ stories.add("PopupConfirm", () => {
onCancel={onCancel}
buttonText="Perform the Culture Club!"
popUpText={popupText}
direction={direction}
/>
);
});
154 changes: 108 additions & 46 deletions src/js/components/Popup/PopupAction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,37 @@ import * as React from "react";

interface State {
isPopupOpen: boolean;
isConfirmOpen: boolean;
selectedAction: Action;
}

interface Action {
export interface Action {
text: string;
callback: () => void;
requiresConfirmation?: boolean;
confirmationText?: string | React.ReactElement;
}

interface Props {
text: string | React.ReactElement;
actions: Array<Action>;
popupStyle?: React.CSSProperties;
direction?: "down" | "right" | "left" | "rightHang" | "leftHang" | "overlay";
direction?: (
| "down"
| "right"
| "left"
| "rightHang"
| "leftHang"
| "overlay")[];
}

export default class PopUpAction extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
isPopupOpen: false
isPopupOpen: false,
isConfirmOpen: false,
selectedAction: {} as Action
};
}

Expand All @@ -34,7 +46,8 @@ export default class PopUpAction extends React.Component<Props, State> {

handleBodyClick() {
this.setState({
isPopupOpen: false
isPopupOpen: false,
isConfirmOpen: false
});
}

Expand All @@ -45,53 +58,102 @@ export default class PopUpAction extends React.Component<Props, State> {
});
}

handleActionClick(action: Action) {
if (action.requiresConfirmation) {
this.setState({
...this.state,
isConfirmOpen: true,
selectedAction: action
});
} else {
action.callback();
}
}

render() {
const dirString = this.props.direction.reduce((acc, cur) => {
return acc + ` Popup-container--${cur}`;
}, "");
return (
<div className="Popup Popup--hover">
<button
className="Button Button--small"
onClick={this.togglePopup.bind(this)}
>
{this.props.text}
</button>
<div
className={
"Popup-container " +
(this.props.direction
? ` Popup-container--${this.props.direction}`
: "") +
(this.state.isPopupOpen ? " is-open" : "")
}
style={this.props.popupStyle}
>
<div className="Popup-content">
<div className="u-textLeft">
{this.props.actions.map(action => {
return (
<div key={action.text}>
<button
tabIndex={0}
className="u-padEndsSm u-padSidesMd"
style={{
cursor: "pointer",
appearance: "none",
border: "none",
background: "none",
width: "100%",
textAlign: "left"
}}
onClick={action.callback}
>
{action.text}
</button>
<hr className="Divider u-spaceEndsNone" />
</div>
);
})}
<>
<div className="Popup Popup--hover">
<button
className="Button Button--small"
onClick={this.togglePopup.bind(this)}
>
{this.props.text}
</button>
<div
className={"Popup-container " + dirString}
style={this.props.popupStyle}
>
<div className="Popup-content">
<div className="u-textLeft">
{this.props.actions.map(action => {
return (
<div key={action.text}>
<button
tabIndex={0}
className="u-padEndsSm u-padSidesMd"
style={{
cursor: "pointer",
appearance: "none",
border: "none",
background: "none",
width: "100%",
textAlign: "left"
}}
onClick={this.handleActionClick.bind(this, action)}
>
{action.text}
</button>
<hr className="Divider u-spaceEndsNone" />
</div>
);
})}
</div>
</div>
</div>
</div>
<div className="Popup">
<div
className={
"Popup-container Popup-container--overlay" +
(this.state.selectedAction.requiresConfirmation &&
this.state.isConfirmOpen
? " is-open"
: "")
}
>
<div className="Popup-content u-padMd">
<h3 className="u-spaceBottomSm u-textCenter">Are you sure?</h3>
<p className="u-textLeft">
{this.state.selectedAction.confirmationText}
</p>
<div className="u-textCenter u-spaceTopMd">
<button
onClick={() =>
this.setState({
...this.state,
isConfirmOpen: false,
selectedAction: {} as Action
})
}
className="u-spaceRightSm Button Button--negative"
>
Cancel
</button>
<button
onClick={this.state.selectedAction.callback}
className="Button Button--primary"
>
Confirm
</button>
</div>
</div>
</div>
</div>
</div>
</>
);
}
}
6 changes: 1 addition & 5 deletions src/js/components/Popup/PopupConfirm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ interface Props {
buttonText: string | React.ReactElement;
popUpText: string | React.ReactElement;
popupStyle?: React.CSSProperties;
direction?: "down" | "right" | "left" | "rightHang" | "leftHang" | "overlay";
onAccept: () => void;
onCancel?: () => void;
}
Expand Down Expand Up @@ -53,10 +52,7 @@ export default class Popup extends React.Component<Props, State> {
</button>
<div
className={
"Popup-container " +
(this.props.direction
? ` Popup-container--${this.props.direction}`
: "") +
"Popup-container Popup-container--overlay" +
(this.state.isPopupOpen ? " is-open" : "")
}
style={this.props.popupStyle}
Expand Down