aboutsummaryrefslogtreecommitdiffstats
path: root/packages/forms/src/button/index.tsx
diff options
context:
space:
mode:
authorLibravatar Stefan Malzner <stefan@adlk.io>2019-01-14 22:26:06 +0100
committerLibravatar Stefan Malzner <stefan@adlk.io>2019-01-14 22:26:06 +0100
commit8b4231e3109d4b29e4d90f4553f718a1d7867bc5 (patch)
treeb7c89bd60d01cca3692a3e6df580669fd08a4b27 /packages/forms/src/button/index.tsx
parentUpdate package.json (diff)
downloadferdium-app-8b4231e3109d4b29e4d90f4553f718a1d7867bc5.tar.gz
ferdium-app-8b4231e3109d4b29e4d90f4553f718a1d7867bc5.tar.zst
ferdium-app-8b4231e3109d4b29e4d90f4553f718a1d7867bc5.zip
Add buttons
Diffstat (limited to 'packages/forms/src/button/index.tsx')
-rw-r--r--packages/forms/src/button/index.tsx172
1 files changed, 172 insertions, 0 deletions
diff --git a/packages/forms/src/button/index.tsx b/packages/forms/src/button/index.tsx
new file mode 100644
index 000000000..c4a138b16
--- /dev/null
+++ b/packages/forms/src/button/index.tsx
@@ -0,0 +1,172 @@
1import { Theme } from '@meetfranz/theme';
2import classnames from 'classnames';
3import CSS from 'csstype';
4import { observer } from 'mobx-react';
5import React, { Component } from 'react';
6import injectStyle from 'react-jss';
7import Loader from 'react-loader';
8
9import { IFormField, IWithStyle } from '../typings/generic';
10
11type ButtonType = 'primary' | 'secondary' | 'danger' | 'warning' | 'inverted';
12
13interface IProps extends React.InputHTMLAttributes<HTMLButtonElement>, IFormField, IWithStyle {
14 buttonType?: ButtonType;
15 stretch?: boolean;
16 loaded?: boolean;
17 busy?: boolean;
18}
19
20interface IState {
21 busy: boolean;
22}
23
24const styles = (theme: Theme) => ({
25 button: {
26 borderRadius: theme.borderRadiusSmall,
27 border: 'none',
28 display: 'flex',
29 position: 'relative' as CSS.PositionProperty,
30 transition: 'background .5s',
31 textAlign: 'center' as CSS.TextAlignProperty,
32 outline: 'none',
33 alignItems: 'center',
34 padding: 0,
35 width: (props: IProps) => (props.stretch ? '100%' : 'auto') as CSS.WidthProperty<string>,
36 fontSize: theme.uiFontSize,
37 },
38 label: {
39 margin: '10px 20px',
40 width: '100%',
41 },
42 primary: {
43 background: theme.buttonPrimaryBackground,
44 color: theme.buttonPrimaryTextColor,
45 },
46 secondary: {
47 background: theme.buttonSecondaryBackground,
48 color: theme.buttonSecondaryTextColor,
49 },
50 danger: {
51 background: theme.buttonDangerBackground,
52 color: theme.buttonDangerTextColor,
53 },
54 warning: {
55 background: theme.buttonWarningBackground,
56 color: theme.buttonWarningTextColor,
57 },
58 inverted: {
59 background: theme.buttonInvertedBackground,
60 color: theme.buttonInvertedTextColor,
61 border: theme.buttonInvertedBorder,
62 },
63 disabled: {
64 opacity: theme.inputDisabledOpacity,
65 },
66 loader: {
67 position: 'relative' as CSS.PositionProperty,
68 width: 20,
69 height: 18,
70 zIndex: 9999,
71 },
72 loaderContainer: {
73 width: (props: IProps): string => (!props.busy ? '0' : '40px'),
74 height: 20,
75 overflow: 'hidden',
76 transition: 'all 0.3s',
77 marginLeft: (props: IProps): number => !props.busy ? 10 : 20,
78 marginRight: (props: IProps): number => !props.busy ? -10 : -20,
79 position: (props: IProps): CSS.PositionProperty => props.stretch ? 'absolute' : 'inherit',
80 },
81});
82
83@observer
84class ButtonComponent extends Component<IProps> {
85 public static defaultProps = {
86 type: 'button',
87 disabled: false,
88 onClick: () => null,
89 buttonType: 'primary' as ButtonType,
90 stretch: false,
91 busy: false,
92 };
93
94 state = {
95 busy: false,
96 };
97
98 componentWillMount() {
99 this.setState({ busy: this.props.busy });
100 }
101
102 componentWillReceiveProps(nextProps: IProps) {
103 if (nextProps.busy !== this.props.busy) {
104 if (this.props.busy) {
105 setTimeout(() => {
106 this.setState({ busy: nextProps.busy });
107 }, 300);
108 } else {
109 this.setState({ busy: nextProps.busy });
110 }
111 }
112 }
113
114 render() {
115 const {
116 classes,
117 theme,
118 disabled,
119 id,
120 label,
121 type,
122 onClick,
123 buttonType,
124 loaded,
125 busy: busyProp,
126 } = this.props;
127
128 const {
129 busy,
130 } = this.state;
131
132 let showLoader = false;
133 if (loaded) {
134 showLoader = !loaded;
135 console.warn('Franz Button prop `loaded` will be deprecated in the future. Please use `busy` instead');
136 }
137 if (busy) {
138 showLoader = busy;
139 }
140
141 return (
142 <button
143 id={id}
144 type={type}
145 onClick={onClick}
146 className={classnames({
147 [`${classes.button}`]: true,
148 [`${classes[buttonType as ButtonType]}`]: true,
149 [`${classes.disabled}`]: disabled,
150 })}
151 disabled={disabled}
152 >
153 <div className={classes.loaderContainer}>
154 {showLoader && (
155 <Loader
156 loaded={false}
157 width={4}
158 scale={0.45}
159 color={theme.buttonLoaderColor[buttonType!]}
160 parentClassName={classes.loader}
161 />
162 )}
163 </div>
164 <div className={classes.label}>
165 {label}
166 </div>
167 </button>
168 );
169 }
170}
171
172export const Button = injectStyle(styles)(ButtonComponent);