diff options
Diffstat (limited to 'packages/forms/src/button/index.tsx')
-rw-r--r-- | packages/forms/src/button/index.tsx | 70 |
1 files changed, 39 insertions, 31 deletions
diff --git a/packages/forms/src/button/index.tsx b/packages/forms/src/button/index.tsx index b81154a43..48fb61635 100644 --- a/packages/forms/src/button/index.tsx +++ b/packages/forms/src/button/index.tsx | |||
@@ -1,21 +1,31 @@ | |||
1 | import Icon from '@mdi/react'; | 1 | import Icon from '@mdi/react'; |
2 | import { Theme } from '@meetfranz/theme'; | ||
3 | import classnames from 'classnames'; | 2 | import classnames from 'classnames'; |
4 | import CSS from 'csstype'; | 3 | import { Property } from 'csstype'; |
5 | import React, { Component } from 'react'; | 4 | import React, { Component } from 'react'; |
6 | import injectStyle, { withTheme } from 'react-jss'; | 5 | import injectStyle, { withTheme } from 'react-jss'; |
7 | import Loader from 'react-loader'; | 6 | import Loader from 'react-loader'; |
8 | 7 | ||
9 | import { IFormField, IWithStyle } from '../typings/generic'; | 8 | import { IFormField, IWithStyle } from '../typings/generic'; |
9 | import { Theme } from '../../../theme'; | ||
10 | 10 | ||
11 | type ButtonType = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'inverted'; | 11 | type ButtonType = |
12 | | 'primary' | ||
13 | | 'secondary' | ||
14 | | 'success' | ||
15 | | 'danger' | ||
16 | | 'warning' | ||
17 | | 'inverted'; | ||
12 | 18 | ||
13 | interface IProps extends IFormField, IWithStyle { | 19 | interface IProps extends IFormField, IWithStyle { |
14 | className?: string; | 20 | className?: string; |
15 | disabled?: boolean; | 21 | disabled?: boolean; |
16 | id?: string; | 22 | id?: string; |
17 | type?: "button" | "reset" | "submit" | undefined; | 23 | type?: 'button' | 'reset' | 'submit' | undefined; |
18 | onClick: (event: React.MouseEvent<HTMLButtonElement> | React.MouseEvent<HTMLAnchorElement>) => void; | 24 | onClick: ( |
25 | event: | ||
26 | | React.MouseEvent<HTMLButtonElement> | ||
27 | | React.MouseEvent<HTMLAnchorElement>, | ||
28 | ) => void; | ||
19 | buttonType?: ButtonType; | 29 | buttonType?: ButtonType; |
20 | stretch?: boolean; | 30 | stretch?: boolean; |
21 | loaded?: boolean; | 31 | loaded?: boolean; |
@@ -25,8 +35,12 @@ interface IProps extends IFormField, IWithStyle { | |||
25 | target?: string; | 35 | target?: string; |
26 | } | 36 | } |
27 | 37 | ||
28 | interface IState { | 38 | let buttonTransition: string = 'none'; |
29 | busy: boolean; | 39 | let loaderContainerTransition: string = 'none'; |
40 | |||
41 | if (window && window.matchMedia('(prefers-reduced-motion: no-preference)')) { | ||
42 | buttonTransition = 'background .5s, opacity 0.3s'; | ||
43 | loaderContainerTransition = 'all 0.3s'; | ||
30 | } | 44 | } |
31 | 45 | ||
32 | const styles = (theme: Theme) => ({ | 46 | const styles = (theme: Theme) => ({ |
@@ -34,16 +48,16 @@ const styles = (theme: Theme) => ({ | |||
34 | borderRadius: theme.borderRadiusSmall, | 48 | borderRadius: theme.borderRadiusSmall, |
35 | border: 'none', | 49 | border: 'none', |
36 | display: 'inline-flex', | 50 | display: 'inline-flex', |
37 | position: 'relative' as CSS.PositionProperty, | 51 | position: 'relative' as Property.Position, |
38 | transition: 'background .5s, opacity 0.3s', | 52 | transition: buttonTransition, |
39 | textAlign: 'center' as CSS.TextAlignProperty, | 53 | textAlign: 'center' as Property.TextAlign, |
40 | outline: 'none', | 54 | outline: 'none', |
41 | alignItems: 'center', | 55 | alignItems: 'center', |
42 | padding: 0, | 56 | padding: 0, |
43 | width: (props: IProps) => (props.stretch ? '100%' : 'auto') as CSS.WidthProperty<string>, | 57 | width: (props: IProps) => |
58 | (props.stretch ? '100%' : 'auto') as Property.Width<string>, | ||
44 | fontSize: theme.uiFontSize, | 59 | fontSize: theme.uiFontSize, |
45 | textDecoration: 'none', | 60 | textDecoration: 'none', |
46 | // height: theme.buttonHeight, | ||
47 | 61 | ||
48 | '&:hover': { | 62 | '&:hover': { |
49 | opacity: 0.8, | 63 | opacity: 0.8, |
@@ -113,7 +127,7 @@ const styles = (theme: Theme) => ({ | |||
113 | opacity: theme.inputDisabledOpacity, | 127 | opacity: theme.inputDisabledOpacity, |
114 | }, | 128 | }, |
115 | loader: { | 129 | loader: { |
116 | position: 'relative' as CSS.PositionProperty, | 130 | position: 'relative' as Property.Position, |
117 | width: 20, | 131 | width: 20, |
118 | height: 18, | 132 | height: 18, |
119 | zIndex: 9999, | 133 | zIndex: 9999, |
@@ -122,10 +136,11 @@ const styles = (theme: Theme) => ({ | |||
122 | width: (props: IProps): string => (!props.busy ? '0' : '40px'), | 136 | width: (props: IProps): string => (!props.busy ? '0' : '40px'), |
123 | height: 20, | 137 | height: 20, |
124 | overflow: 'hidden', | 138 | overflow: 'hidden', |
125 | transition: 'all 0.3s', | 139 | transition: loaderContainerTransition, |
126 | marginLeft: (props: IProps): number => !props.busy ? 10 : 20, | 140 | marginLeft: (props: IProps): number => (!props.busy ? 10 : 20), |
127 | marginRight: (props: IProps): number => !props.busy ? -10 : -20, | 141 | marginRight: (props: IProps): number => (!props.busy ? -10 : -20), |
128 | position: (props: IProps): CSS.PositionProperty => props.stretch ? 'absolute' : 'inherit', | 142 | position: (props: IProps): Property.Position => |
143 | props.stretch ? 'absolute' : 'inherit', | ||
129 | }, | 144 | }, |
130 | icon: { | 145 | icon: { |
131 | margin: [1, 10, 0, -5], | 146 | margin: [1, 10, 0, -5], |
@@ -155,7 +170,7 @@ class ButtonComponent extends Component<IProps> { | |||
155 | if (this.props.busy) { | 170 | if (this.props.busy) { |
156 | setTimeout(() => { | 171 | setTimeout(() => { |
157 | this.setState({ busy: nextProps.busy }); | 172 | this.setState({ busy: nextProps.busy }); |
158 | }, 300); | 173 | }, 300); |
159 | } else { | 174 | } else { |
160 | this.setState({ busy: nextProps.busy }); | 175 | this.setState({ busy: nextProps.busy }); |
161 | } | 176 | } |
@@ -175,19 +190,18 @@ class ButtonComponent extends Component<IProps> { | |||
175 | buttonType, | 190 | buttonType, |
176 | loaded, | 191 | loaded, |
177 | icon, | 192 | icon, |
178 | busy: busyProp, | ||
179 | href, | 193 | href, |
180 | target, | 194 | target, |
181 | } = this.props; | 195 | } = this.props; |
182 | 196 | ||
183 | const { | 197 | const { busy } = this.state; |
184 | busy, | ||
185 | } = this.state; | ||
186 | 198 | ||
187 | let showLoader = false; | 199 | let showLoader = false; |
188 | if (loaded) { | 200 | if (loaded) { |
189 | showLoader = !loaded; | 201 | showLoader = !loaded; |
190 | console.warn('Ferdi Button prop `loaded` will be deprecated in the future. Please use `busy` instead'); | 202 | console.warn( |
203 | 'Ferdi Button prop `loaded` will be deprecated in the future. Please use `busy` instead', | ||
204 | ); | ||
191 | } | 205 | } |
192 | if (busy) { | 206 | if (busy) { |
193 | showLoader = busy; | 207 | showLoader = busy; |
@@ -207,19 +221,13 @@ class ButtonComponent extends Component<IProps> { | |||
207 | )} | 221 | )} |
208 | </div> | 222 | </div> |
209 | <div className={classes.label}> | 223 | <div className={classes.label}> |
210 | {icon && ( | 224 | {icon && <Icon path={icon} size={0.8} className={classes.icon} />} |
211 | <Icon | ||
212 | path={icon} | ||
213 | size={0.8} | ||
214 | className={classes.icon} | ||
215 | /> | ||
216 | )} | ||
217 | {label} | 225 | {label} |
218 | </div> | 226 | </div> |
219 | </> | 227 | </> |
220 | ); | 228 | ); |
221 | 229 | ||
222 | let wrapperComponent = null; | 230 | let wrapperComponent: JSX.Element; |
223 | 231 | ||
224 | if (!href) { | 232 | if (!href) { |
225 | wrapperComponent = ( | 233 | wrapperComponent = ( |