added settings dropdown
This commit is contained in:
@@ -1,20 +1,188 @@
|
||||
import * as React from 'react';
|
||||
import styled, { withTheme } from 'styled-components';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { Heading } from 'ts/components/text';
|
||||
import { colors } from 'ts/style/colors';
|
||||
|
||||
interface ToggleProps {
|
||||
className?: string;
|
||||
name?: string;
|
||||
value?: string;
|
||||
isChecked?: boolean;
|
||||
isDisabled?: boolean;
|
||||
onToggle?: (e: React.ChangeEvent) => void;
|
||||
width?: string;
|
||||
height?: string;
|
||||
borderWidth?: string;
|
||||
borderColor?: string;
|
||||
backgroundColor?: string;
|
||||
backgroundColorDisabled?: string;
|
||||
radius?: string;
|
||||
radiusBackground?: string;
|
||||
knobRadius?: string;
|
||||
knobWidth?: string;
|
||||
knobHeight?: string;
|
||||
knobGap?: string;
|
||||
knobColor?: string;
|
||||
}
|
||||
|
||||
const ToggleContainer = styled.label``;
|
||||
|
||||
const DEFAULT_TOGGLE_STYLES = {
|
||||
WIDTH: '48px',
|
||||
HEIGHT: '24px',
|
||||
KNOB_WIDTH: '12px',
|
||||
KNOB_HEIGHT: '12px',
|
||||
};
|
||||
|
||||
export const ToggleBase = styled.span<ToggleProps>`
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
display: inline-grid;
|
||||
align-items: center;
|
||||
width: ${p => p.width || DEFAULT_TOGGLE_STYLES.WIDTH};
|
||||
height: ${p => p.height || DEFAULT_TOGGLE_STYLES.HEIGHT};
|
||||
vertical-align: text-top;
|
||||
margin: 0 4px;
|
||||
input[type="checkbox"] {
|
||||
position: absolute;
|
||||
margin-left: -9999px;
|
||||
visibility: hidden;
|
||||
// off state
|
||||
& + label {
|
||||
display: inline-grid;
|
||||
box-sizing: border-box;
|
||||
align-items: center;
|
||||
outline: none;
|
||||
user-select: none;
|
||||
width: ${p => p.width || DEFAULT_TOGGLE_STYLES.WIDTH};
|
||||
height: ${p => p.height || DEFAULT_TOGGLE_STYLES.HEIGHT};
|
||||
background-color: ${p =>
|
||||
p.knobColor || '#EAEAEA'};
|
||||
border-radius: ${p => p.radius || '256px'};
|
||||
cursor: pointer;
|
||||
transition: background ease-out 0.3s;
|
||||
&:before {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
border-radius: ${p =>
|
||||
p.radiusBackground || '256px'};
|
||||
width: calc(
|
||||
${p => p.width || DEFAULT_TOGGLE_STYLES.WIDTH} - 2 *
|
||||
${p => p.borderWidth || '2px'}
|
||||
);
|
||||
height: calc(
|
||||
${p => p.height || DEFAULT_TOGGLE_STYLES.HEIGHT} - 2 *
|
||||
${p => p.borderWidth || '2px'}
|
||||
);
|
||||
background-color: ${p => p.backgroundColor || colors.white};
|
||||
left: ${p => p.borderWidth || '2px'};
|
||||
}
|
||||
&:after {
|
||||
display: block;
|
||||
position: absolute;
|
||||
content: "";
|
||||
width: ${p => p.knobWidth || DEFAULT_TOGGLE_STYLES.KNOB_WIDTH};
|
||||
height: ${p => p.knobHeight || DEFAULT_TOGGLE_STYLES.KNOB_HEIGHT};
|
||||
border-radius: ${p => p.knobRadius || '100%'};
|
||||
background-color: ${p =>
|
||||
p.knobColor || '#EAEAEA'};
|
||||
transition: all ease-out 0.4s;
|
||||
margin-left: ${p => p.knobGap || '4px'};
|
||||
}
|
||||
}
|
||||
// on state
|
||||
&:checked {
|
||||
& + label {
|
||||
background-color: ${p => p.borderColor || colors.brandLight};
|
||||
&:before {
|
||||
background-color: ${p => p.backgroundColor || colors.white};
|
||||
}
|
||||
&:after {
|
||||
margin-left: calc(
|
||||
100% - ${p => p.knobWidth || DEFAULT_TOGGLE_STYLES.KNOB_WIDTH} -
|
||||
${p => p.knobGap || '4px'}
|
||||
);
|
||||
transition: all ease-out 0.2s;
|
||||
background-color: ${p =>
|
||||
p.knobColor || colors.brandLight};
|
||||
}
|
||||
}
|
||||
&:disabled {
|
||||
& + label {
|
||||
background-color: ${p => p.backgroundColorDisabled || '#eee'};
|
||||
&:after {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// disabled
|
||||
&:disabled {
|
||||
& + label {
|
||||
background-color: ${p => p.backgroundColorDisabled || '#eee'};
|
||||
cursor: default;
|
||||
&:after {
|
||||
box-shadow: none;
|
||||
background-color: ${p => p.backgroundColorDisabled || '#eee'};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const Toggle = React.forwardRef((props: ToggleProps, ref: React.Ref<HTMLInputElement>) => {
|
||||
const {
|
||||
className,
|
||||
name,
|
||||
isChecked = false,
|
||||
isDisabled = false,
|
||||
value = '',
|
||||
onToggle = () => true,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<ToggleBase className={className} {...props}>
|
||||
<input
|
||||
ref={ref}
|
||||
onChange={onToggle}
|
||||
type={'checkbox'}
|
||||
defaultChecked={isChecked}
|
||||
id={name}
|
||||
name={name}
|
||||
value={value}
|
||||
disabled={isDisabled}
|
||||
/>
|
||||
<ToggleContainer htmlFor={name} />
|
||||
</ToggleBase>
|
||||
);
|
||||
});
|
||||
|
||||
const SwitchWrapper = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0.5rem 0;
|
||||
padding: 0.75rem 0;
|
||||
`;
|
||||
|
||||
export interface SwitchProps {
|
||||
label: string;
|
||||
isChecked?: boolean;
|
||||
onToggle: (checked: boolean) => void;
|
||||
}
|
||||
|
||||
export const Switch = (props: SwitchProps) => {
|
||||
return <SwitchWrapper>
|
||||
<Heading isNoMargin={true} asElement="h3" size={'small'}>{props.label}</Heading>
|
||||
</SwitchWrapper>;
|
||||
};
|
||||
export class Switch extends React.Component<SwitchProps> {
|
||||
public switchRef: React.RefObject<HTMLInputElement> = React.createRef();
|
||||
|
||||
constructor(props: SwitchProps) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
public render(): React.ReactNode {
|
||||
const onToggle = () => { this.props.onToggle(this.switchRef.current.checked); };
|
||||
return <SwitchWrapper>
|
||||
<Heading isNoMargin={true} asElement="h3" size={'small'}>{this.props.label}</Heading>
|
||||
<Toggle ref={this.switchRef} isChecked={this.props.isChecked} onToggle={onToggle} knobGap={'6px'} name={this.props.label}/>
|
||||
</SwitchWrapper>;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user