aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/ui/toggle/index.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/ui/toggle/index.tsx')
-rw-r--r--src/components/ui/toggle/index.tsx125
1 files changed, 125 insertions, 0 deletions
diff --git a/src/components/ui/toggle/index.tsx b/src/components/ui/toggle/index.tsx
new file mode 100644
index 000000000..67b6c3835
--- /dev/null
+++ b/src/components/ui/toggle/index.tsx
@@ -0,0 +1,125 @@
1import classnames from 'classnames';
2import { Property } from 'csstype';
3import { Component, InputHTMLAttributes } from 'react';
4import injectStyle from 'react-jss';
5import { Theme } from '@meetfranz/theme';
6
7import { IFormField, IWithStyle } from '../typings/generic';
8
9import { Error } from '../error';
10import { Label } from '../label';
11import { Wrapper } from '../wrapper';
12
13interface IProps
14 extends InputHTMLAttributes<HTMLInputElement>,
15 IFormField,
16 IWithStyle {
17 className?: string;
18}
19
20let buttonTransition: string = 'none';
21
22if (window && window.matchMedia('(prefers-reduced-motion: no-preference)')) {
23 buttonTransition = 'all .5s';
24}
25
26const styles = (theme: Theme) => ({
27 toggle: {
28 background: theme.toggleBackground,
29 borderRadius: theme.borderRadius,
30 height: theme.toggleHeight,
31 position: 'relative' as Property.Position,
32 width: theme.toggleWidth,
33 },
34 button: {
35 background: theme.toggleButton,
36 borderRadius: '100%',
37 boxShadow: '0 1px 4px rgba(0, 0, 0, .3)',
38 width: theme.toggleHeight - 2,
39 height: theme.toggleHeight - 2,
40 left: 1,
41 top: 1,
42 position: 'absolute' as Property.Position,
43 transition: buttonTransition,
44 },
45 buttonActive: {
46 background: theme.toggleButtonActive,
47 left: theme.toggleWidth - theme.toggleHeight + 1,
48 },
49 input: {
50 visibility: 'hidden' as any,
51 },
52 disabled: {
53 opacity: theme.inputDisabledOpacity,
54 },
55 toggleLabel: {
56 display: 'flex',
57 alignItems: 'center',
58
59 '& > span': {
60 order: 1,
61 marginLeft: 15,
62 },
63 },
64});
65
66class ToggleComponent extends Component<IProps> {
67 public static defaultProps = {
68 onChange: () => {},
69 showLabel: true,
70 disabled: false,
71 error: '',
72 };
73
74 render() {
75 const {
76 classes,
77 className,
78 disabled,
79 error,
80 id,
81 label,
82 showLabel,
83 checked,
84 value,
85 onChange,
86 } = this.props;
87
88 return (
89 <Wrapper className={className} identifier="franz-toggle">
90 <Label
91 title={label}
92 showLabel={showLabel}
93 htmlFor={id}
94 className={classes.toggleLabel}
95 >
96 <div
97 className={classnames({
98 [`${classes.toggle}`]: true,
99 [`${classes.disabled}`]: disabled,
100 })}
101 >
102 <div
103 className={classnames({
104 [`${classes.button}`]: true,
105 [`${classes.buttonActive}`]: checked,
106 })}
107 />
108 <input
109 className={classes.input}
110 id={id}
111 type="checkbox"
112 checked={checked}
113 value={value}
114 onChange={onChange}
115 disabled={disabled}
116 />
117 </div>
118 </Label>
119 {error && <Error message={error} />}
120 </Wrapper>
121 );
122 }
123}
124
125export const Toggle = injectStyle(styles)(ToggleComponent);