diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2020-05-18 16:08:03 +0200 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2020-05-25 12:56:47 +0200 |
| commit | 51009aa592af34e168b152a4e10c841d690962d7 (patch) | |
| tree | a43e18da3efdf24f808bba3e62efa8ac1365e404 /gui | |
| parent | 00591c5fdeb5d56e21c5bc717201d743a289b9db (diff) | |
| download | mullvadvpn-51009aa592af34e168b152a4e10c841d690962d7.tar.xz mullvadvpn-51009aa592af34e168b152a4e10c841d690962d7.zip | |
Add disabled functionality to switch, cell input and cell label
Diffstat (limited to 'gui')
| -rw-r--r-- | gui/src/renderer/components/Cell.tsx | 57 | ||||
| -rw-r--r-- | gui/src/renderer/components/CellStyles.tsx | 6 | ||||
| -rw-r--r-- | gui/src/renderer/components/Switch.tsx | 56 |
3 files changed, 86 insertions, 33 deletions
diff --git a/gui/src/renderer/components/Cell.tsx b/gui/src/renderer/components/Cell.tsx index 23f63114b7..4abcb9f49e 100644 --- a/gui/src/renderer/components/Cell.tsx +++ b/gui/src/renderer/components/Cell.tsx @@ -4,26 +4,38 @@ import { StyledAutoSizingTextInputWrapper, StyledAutoSizingTextInputFiller, StyledCellButton, - StyledSection, + StyledContainer, + StyledLabel, StyledInput, + StyledSection, } from './CellStyles'; +import { default as StandaloneSwitch } from './Switch'; export { - StyledContainer as Container, StyledFooter as Footer, StyledFooterBoldText as FooterBoldText, StyledFooterText as FooterText, StyledIcon as UntintedIcon, StyledInputFrame as InputFrame, - StyledLabel as Label, StyledSectionTitle as SectionTitle, StyledSubText as SubText, StyledTintedIcon as Icon, } from './CellStyles'; -export { default as Switch } from './Switch'; - const CellSectionContext = React.createContext<boolean>(false); +const CellDisabledContext = React.createContext<boolean>(false); + +interface IContainerProps extends React.HTMLAttributes<HTMLDivElement> { + disabled?: boolean; +} + +export function Container({ disabled, ...otherProps }: IContainerProps) { + return ( + <CellDisabledContext.Provider value={disabled ?? false}> + <StyledContainer {...otherProps} /> + </CellDisabledContext.Provider> + ); +} interface ICellButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> { selected?: boolean; @@ -50,6 +62,16 @@ export function Section(props: ISectionProps) { ); } +export function Label(props: React.HTMLAttributes<HTMLDivElement>) { + const disabled = useContext(CellDisabledContext); + return <StyledLabel disabled={disabled} {...props} />; +} + +export function Switch(props: StandaloneSwitch['props']) { + const disabled = useContext(CellDisabledContext); + return <StandaloneSwitch disabled={disabled} {...props} />; +} + interface IInputProps extends React.InputHTMLAttributes<HTMLInputElement> { value?: string; validateValue?: (value: string) => boolean; @@ -104,16 +126,21 @@ export class Input extends React.Component<IInputProps, IInputState> { } = this.props; return ( - <StyledInput - type="text" - valid={validateValue?.(this.state.value)} - onChange={this.onChange} - onFocus={this.onFocus} - onBlur={this.onBlur} - onKeyPress={this.onKeyPress} - value={this.state.value} - {...otherProps} - /> + <CellDisabledContext.Consumer> + {(disabled) => ( + <StyledInput + type="text" + valid={validateValue?.(this.state.value)} + onChange={this.onChange} + onFocus={this.onFocus} + onBlur={this.onBlur} + onKeyPress={this.onKeyPress} + value={this.state.value} + disabled={disabled} + {...otherProps} + /> + )} + </CellDisabledContext.Consumer> ); } diff --git a/gui/src/renderer/components/CellStyles.tsx b/gui/src/renderer/components/CellStyles.tsx index 40b27abbb0..9ae67f733c 100644 --- a/gui/src/renderer/components/CellStyles.tsx +++ b/gui/src/renderer/components/CellStyles.tsx @@ -51,7 +51,7 @@ export const StyledCellButton = styled.button({}, (props: IStyledCellButtonProps }, })); -export const StyledLabel = styled.div({ +export const StyledLabel = styled.div({}, (props: { disabled: boolean }) => ({ margin: '14px 0 14px 8px', flex: 1, fontFamily: 'DINPro', @@ -59,9 +59,9 @@ export const StyledLabel = styled.div({ fontWeight: 900, lineHeight: '26px', letterSpacing: -0.2, - color: colors.white, + color: props.disabled ? colors.white40 : colors.white, textAlign: 'left', -}); +})); export const StyledSubText = styled.span({ color: colors.white60, diff --git a/gui/src/renderer/components/Switch.tsx b/gui/src/renderer/components/Switch.tsx index 7a1555c761..5279181cda 100644 --- a/gui/src/renderer/components/Switch.tsx +++ b/gui/src/renderer/components/Switch.tsx @@ -6,6 +6,7 @@ interface IProps { isOn: boolean; onChange?: (isOn: boolean) => void; className?: string; + disabled?: boolean; } interface IState { @@ -15,30 +16,37 @@ interface IState { const PAN_DISTANCE = 10; -const SwitchContainer = styled.div({ +const SwitchContainer = styled.div({}, (props: { disabled: boolean }) => ({ position: 'relative', width: '52px', height: '32px', - borderColor: colors.white, + borderColor: props.disabled ? colors.white20 : colors.white80, borderWidth: '2px', borderStyle: 'solid', borderRadius: '16px', padding: '2px', -}); - -const Knob = styled.div({}, (props: { isOn: boolean; isPressed: boolean }) => ({ - position: 'absolute', - height: '24px', - borderRadius: '12px', - transition: 'all 200ms linear', - width: props.isPressed ? '28px' : '24px', - backgroundColor: props.isOn ? colors.green : colors.red, - // When enabled the button should be placed all the way to the right (100%) minus padding (2px). - left: props.isOn ? 'calc(100% - 2px)' : '2px', - // This moves the knob to the left making the right side aligned with the parent's right side. - transform: `translateX(${props.isOn ? '-100%' : '0'})`, })); +const Knob = styled.div({}, (props: { isOn: boolean; isPressed: boolean; disabled: boolean }) => { + let backgroundColor = props.isOn ? colors.green : colors.red; + if (props.disabled) { + backgroundColor = props.isOn ? colors.green40 : colors.red40; + } + + return { + position: 'absolute', + height: '24px', + borderRadius: '12px', + transition: 'all 200ms linear', + width: props.isPressed ? '28px' : '24px', + backgroundColor, + // When enabled the button should be placed all the way to the right (100%) minus padding (2px). + left: props.isOn ? 'calc(100% - 2px)' : '2px', + // This moves the knob to the left making the right side aligned with the parent's right side. + transform: `translateX(${props.isOn ? '-100%' : '0'})`, + }; +}); + export default class Switch extends React.Component<IProps, IState> { public state: IState = { isOn: this.props.isOn, @@ -74,8 +82,10 @@ export default class Switch extends React.Component<IProps, IState> { <SwitchContainer ref={this.containerRef} onClick={this.handleClick} + disabled={this.props.disabled ?? false} className={this.props.className}> <Knob + disabled={this.props.disabled ?? false} isOn={this.state.isOn} isPressed={this.state.isPressed} onMouseDown={this.handleMouseDown} @@ -85,6 +95,10 @@ export default class Switch extends React.Component<IProps, IState> { } private handleClick = () => { + if (this.props.disabled) { + return; + } + if (!this.changedDuringPan) { this.setState((state) => ({ isOn: !state.isOn }), this.notify); } @@ -94,6 +108,10 @@ export default class Switch extends React.Component<IProps, IState> { }; private handleMouseDown = (event: React.MouseEvent<HTMLDivElement>) => { + if (this.props.disabled) { + return; + } + this.isPanning = true; this.startPos = event.clientX; this.changedDuringPan = false; @@ -103,6 +121,10 @@ export default class Switch extends React.Component<IProps, IState> { }; private handleMouseUp = (event: MouseEvent) => { + if (this.props.disabled) { + return; + } + document.removeEventListener('mouseup', this.handleMouseUp); document.removeEventListener('mousemove', this.handleMouseMove); @@ -119,6 +141,10 @@ export default class Switch extends React.Component<IProps, IState> { }; private handleMouseMove = (event: MouseEvent) => { + if (this.props.disabled) { + return; + } + if (this.isPanning) { this.setState({ isPressed: true }); |
