aboutsummaryrefslogtreecommitdiffstats
path: root/packages/forms/src
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
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')
-rw-r--r--packages/forms/src/button/index.tsx172
-rw-r--r--packages/forms/src/error/styles.ts1
-rw-r--r--packages/forms/src/index.ts1
-rw-r--r--packages/forms/src/input/index.tsx34
-rw-r--r--packages/forms/src/input/styles.ts6
-rw-r--r--packages/forms/src/label/styles.ts1
-rw-r--r--packages/forms/src/toggle/index.tsx8
-rw-r--r--packages/forms/src/typings/generic.ts2
-rw-r--r--packages/forms/src/wrapper/index.tsx2
9 files changed, 201 insertions, 26 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);
diff --git a/packages/forms/src/error/styles.ts b/packages/forms/src/error/styles.ts
index 36a2b24e7..5104838a5 100644
--- a/packages/forms/src/error/styles.ts
+++ b/packages/forms/src/error/styles.ts
@@ -4,5 +4,6 @@ export default (theme: Theme) => ({
4 message: { 4 message: {
5 color: theme.brandDanger, 5 color: theme.brandDanger,
6 margin: '5px 0 0', 6 margin: '5px 0 0',
7 fontSize: theme.uiFontSize,
7 }, 8 },
8}); 9});
diff --git a/packages/forms/src/index.ts b/packages/forms/src/index.ts
index a506de111..fbeb7e3d3 100644
--- a/packages/forms/src/index.ts
+++ b/packages/forms/src/index.ts
@@ -1,2 +1,3 @@
1export { Input } from './input'; 1export { Input } from './input';
2export { Toggle } from './toggle'; 2export { Toggle } from './toggle';
3export { Button } from './button';
diff --git a/packages/forms/src/input/index.tsx b/packages/forms/src/input/index.tsx
index d82ee5fe3..8f17ba2f9 100644
--- a/packages/forms/src/input/index.tsx
+++ b/packages/forms/src/input/index.tsx
@@ -34,6 +34,7 @@ class InputComponent extends Component<IProps, IState> {
34 public static defaultProps = { 34 public static defaultProps = {
35 focus: false, 35 focus: false,
36 onChange: () => {}, 36 onChange: () => {},
37 onBlur: () => {},
37 scorePassword: false, 38 scorePassword: false,
38 showLabel: true, 39 showLabel: true,
39 showPasswordToggle: false, 40 showPasswordToggle: false,
@@ -74,6 +75,7 @@ class InputComponent extends Component<IProps, IState> {
74 render() { 75 render() {
75 const { 76 const {
76 classes, 77 classes,
78 className,
77 disabled, 79 disabled,
78 error, 80 error,
79 id, 81 id,
@@ -84,6 +86,11 @@ class InputComponent extends Component<IProps, IState> {
84 showLabel, 86 showLabel,
85 showPasswordToggle, 87 showPasswordToggle,
86 type, 88 type,
89 value,
90 name,
91 placeholder,
92 spellCheck,
93 onBlur,
87 } = this.props; 94 } = this.props;
88 95
89 const { 96 const {
@@ -91,18 +98,7 @@ class InputComponent extends Component<IProps, IState> {
91 passwordScore, 98 passwordScore,
92 } = this.state; 99 } = this.state;
93 100
94 const inputProps = pick(this.props, htmlElementAttributes['input']); 101 const inputType = type === 'password' && showPassword ? 'text' : type;
95
96 if (type === 'password' && showPassword) {
97 inputProps.type = 'text';
98 }
99
100 inputProps.onChange = this.onChange.bind(this);
101
102 const cssClasses = classnames({
103 [`${inputProps.className}`]: inputProps.className,
104 [`${classes.input}`]: true,
105 });
106 102
107 return ( 103 return (
108 <Wrapper> 104 <Wrapper>
@@ -110,10 +106,11 @@ class InputComponent extends Component<IProps, IState> {
110 title={label} 106 title={label}
111 showLabel={showLabel} 107 showLabel={showLabel}
112 htmlFor={id} 108 htmlFor={id}
109 className={className}
113 > 110 >
114 <div 111 <div
115 className={classnames({ 112 className={classnames({
116 [`${classes.hasPasswordScore}`]: showPasswordToggle, 113 [`${classes.hasPasswordScore}`]: scorePassword,
117 [`${classes.wrapper}`]: true, 114 [`${classes.wrapper}`]: true,
118 [`${classes.disabled}`]: disabled, 115 [`${classes.disabled}`]: disabled,
119 [`${classes.hasError}`]: error, 116 [`${classes.hasError}`]: error,
@@ -124,9 +121,16 @@ class InputComponent extends Component<IProps, IState> {
124 </span> 121 </span>
125 )} 122 )}
126 <input 123 <input
127 {...inputProps} 124 id={id}
128 className={cssClasses} 125 type={inputType}
126 name={name}
127 value={value}
128 placeholder={placeholder}
129 spellCheck={spellCheck}
130 className={classes.input}
129 ref={this.inputRef} 131 ref={this.inputRef}
132 onChange={this.onChange.bind(this)}
133 onBlur={onBlur}
130 /> 134 />
131 {suffix && ( 135 {suffix && (
132 <span className={classes.suffix}> 136 <span className={classes.suffix}>
diff --git a/packages/forms/src/input/styles.ts b/packages/forms/src/input/styles.ts
index 2b34e92c3..a64d2c340 100644
--- a/packages/forms/src/input/styles.ts
+++ b/packages/forms/src/input/styles.ts
@@ -6,12 +6,10 @@ const prefixStyles = (theme: Theme) => ({
6 color: theme.inputPrefixColor, 6 color: theme.inputPrefixColor,
7 lineHeight: theme.inputHeight, 7 lineHeight: theme.inputHeight,
8 padding: '0 10px', 8 padding: '0 10px',
9 fontSize: theme.uiFontSize,
9}); 10});
10 11
11export default (theme: Theme) => ({ 12export default (theme: Theme) => ({
12 container: {
13 // display: 'flex',
14 },
15 disabled: { 13 disabled: {
16 opacity: theme.inputDisabledOpacity, 14 opacity: theme.inputDisabledOpacity,
17 }, 15 },
@@ -33,7 +31,7 @@ export default (theme: Theme) => ({
33 input: { 31 input: {
34 background: 'none', 32 background: 'none',
35 border: 0, 33 border: 0,
36 fontSize: theme.inputFontSize, 34 fontSize: theme.uiFontSize,
37 outline: 'none', 35 outline: 'none',
38 padding: 8, 36 padding: 8,
39 width: '100%', 37 width: '100%',
diff --git a/packages/forms/src/label/styles.ts b/packages/forms/src/label/styles.ts
index 64011a93d..f3998de04 100644
--- a/packages/forms/src/label/styles.ts
+++ b/packages/forms/src/label/styles.ts
@@ -6,6 +6,7 @@ export default (theme: Theme) => ({
6 }, 6 },
7 label: { 7 label: {
8 color: theme.labelColor, 8 color: theme.labelColor,
9 fontSize: theme.uiFontSize,
9 }, 10 },
10 hasError: { 11 hasError: {
11 color: theme.brandDanger, 12 color: theme.brandDanger,
diff --git a/packages/forms/src/toggle/index.tsx b/packages/forms/src/toggle/index.tsx
index 759694dc8..a1cd7f1a4 100644
--- a/packages/forms/src/toggle/index.tsx
+++ b/packages/forms/src/toggle/index.tsx
@@ -11,9 +11,7 @@ import Error from '../error';
11import Label from '../label'; 11import Label from '../label';
12import Wrapper from '../wrapper'; 12import Wrapper from '../wrapper';
13 13
14interface IProps extends React.InputHTMLAttributes<HTMLInputElement>, IFormField, IWithStyle { 14interface IProps extends React.InputHTMLAttributes<HTMLInputElement>, IFormField, IWithStyle {}
15 // field: any;
16}
17 15
18const styles = (theme: Theme) => ({ 16const styles = (theme: Theme) => ({
19 toggle: { 17 toggle: {
@@ -42,7 +40,7 @@ const styles = (theme: Theme) => ({
42 visibility: 'hidden' as any, 40 visibility: 'hidden' as any,
43 }, 41 },
44 disabled: { 42 disabled: {
45 opacity: 0.5, 43 opacity: theme.inputDisabledOpacity,
46 }, 44 },
47 toggleLabel: { 45 toggleLabel: {
48 display: 'flex', 46 display: 'flex',
@@ -77,8 +75,6 @@ class ToggleComponent extends Component<IProps> {
77 onChange, 75 onChange,
78 } = this.props; 76 } = this.props;
79 77
80 console.log('props', this.props);
81
82 return ( 78 return (
83 <Wrapper> 79 <Wrapper>
84 <Label 80 <Label
diff --git a/packages/forms/src/typings/generic.ts b/packages/forms/src/typings/generic.ts
index bd3ea364b..b7f2fc452 100644
--- a/packages/forms/src/typings/generic.ts
+++ b/packages/forms/src/typings/generic.ts
@@ -1,3 +1,4 @@
1import { Theme } from '@meetfranz/theme/lib';
1import { Classes } from 'jss'; 2import { Classes } from 'jss';
2 3
3export interface IFormField { 4export interface IFormField {
@@ -8,6 +9,7 @@ export interface IFormField {
8 9
9export interface IWithStyle { 10export interface IWithStyle {
10 classes: Classes; 11 classes: Classes;
12 theme: Theme;
11} 13}
12 14
13export type Merge<M, N> = Omit<M, Extract<keyof M, keyof N>> & N; 15export type Merge<M, N> = Omit<M, Extract<keyof M, keyof N>> & N;
diff --git a/packages/forms/src/wrapper/index.tsx b/packages/forms/src/wrapper/index.tsx
index b3e92da66..633cc4c99 100644
--- a/packages/forms/src/wrapper/index.tsx
+++ b/packages/forms/src/wrapper/index.tsx
@@ -18,7 +18,7 @@ class Wrapper extends Component<IProps> {
18 } = this.props; 18 } = this.props;
19 19
20 return ( 20 return (
21 <div className={classes.container}> 21 <div className={classes.container}>
22 {children} 22 {children}
23 </div> 23 </div>
24 ); 24 );