From 0c5f2754cfc441d78dc6a94245a0e2208daaf930 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Thu, 16 Jul 2020 13:30:34 +0200 Subject: [PATCH] Native toggle component (#3209) --- packages/apps/webpack.base.config.js | 4 +- packages/page-js/src/constants.tsx | 2 +- packages/page-js/src/types.ts | 4 +- packages/page-settings/src/SelectUrl.tsx | 7 +- .../page-staking/src/Targets/Validator.tsx | 5 +- packages/react-components/src/Checkbox.tsx | 63 +++++++++++++++ packages/react-components/src/Icon.tsx | 6 +- packages/react-components/src/Toggle.tsx | 78 ++++++++++++------- packages/react-components/src/index.tsx | 1 + packages/react-components/src/styles/index.ts | 16 ++-- 10 files changed, 136 insertions(+), 50 deletions(-) create mode 100644 packages/react-components/src/Checkbox.tsx diff --git a/packages/apps/webpack.base.config.js b/packages/apps/webpack.base.config.js index 0e50c8edb7..f746609fed 100644 --- a/packages/apps/webpack.base.config.js +++ b/packages/apps/webpack.base.config.js @@ -157,13 +157,13 @@ function createWebpack (ENV, context) { chunks: 'initial', enforce: true, name: 'other.01', - test: /node_modules\/(@babel|ansi-styles|asn1|browserify-|chalk|color|color-|crypto-browserify|des\.js|diffie-hellman|elliptic|hash|hmac-drbg|js-sha3|lodash|md5|memoizee|miller-rabin|object-|path-|parse-asn1|pbkdf2|process|public-encrypt|query-string|ripemd160|readable-stream|regenerator-runtime|rtcpeerconnection-shim|stream-browserify|store|timers-browserify|tslib|unified|unist-util|util|vfile|vm-browserify|webrtc-adapter|whatwg-fetch|xxhashjs)/ + test: /node_modules\/(@babel|ansi-styles|asn1|browserify-|chalk|color|color-|crypto-browserify|des\.js|diffie-hellman|elliptic|event-emitter|events|eventemitter3|hash|hmac-drbg|js-sha3|lodash|md5|memoizee|miller-rabin|object-|path-|parse-asn1|pbkdf2|process|public-encrypt|query-string|ripemd160|readable-stream|regenerator-runtime|rtcpeerconnection-shim|stream-browserify|store|timers-browserify|tslib|unified|unist-util|util|vfile|vm-browserify|webrtc-adapter|whatwg-fetch|xxhashjs)/ }, vendor02: { chunks: 'initial', enforce: true, name: 'other.02', - test: /node_modules\/(attr-accept|base-x|base64-js|blakejs|bip39|bip66|bn\.js|brorand|buffer|camelcase|cipher-base|core-js|core-util|create-|cuint|decode-uri|deep-equal|define-properties|detect-browser|es-abstract|es5-ext|es6-symbol|event-emitter|events|eventemitter3|extend|function-bind|has-symbols|history|html-parse|ieee754|ip-|is-|minimalistic-crypto-utils|moment|next-tick|node-libs-browser|randombytes|randomfill|regexp|rxjs|safe-buffer|scheduler|sdp|secp256k1|setimmediate|sha\.js|through)/ + test: /node_modules\/(attr-accept|base-x|base64-js|blakejs|bip39|bip66|bn\.js|brorand|buffer|camelcase|cipher-base|core-js|core-util|create-|cuint|decode-uri|deep-equal|define-properties|detect-browser|es-abstract|es5-ext|es6-symbol|extend|function-bind|has-symbols|history|html-parse|ieee754|ip-|is-|minimalistic-crypto-utils|moment|next-tick|node-libs-browser|randombytes|randomfill|regexp|rxjs|safe-buffer|scheduler|sdp|secp256k1|setimmediate|sha\.js|through)/ } } } diff --git a/packages/page-js/src/constants.tsx b/packages/page-js/src/constants.tsx index e09e83c75d..b07227c1e0 100644 --- a/packages/page-js/src/constants.tsx +++ b/packages/page-js/src/constants.tsx @@ -2,7 +2,7 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { StrictLabelProps } from 'semantic-ui-react/dist/commonjs/elements/Label'; +import type { StrictLabelProps } from 'semantic-ui-react/dist/commonjs/elements/Label'; export const STORE_EXAMPLES = 'polkadot-app-js-examples'; export const STORE_SELECTED = 'polkadot-app-js-selected'; diff --git a/packages/page-js/src/types.ts b/packages/page-js/src/types.ts index de08187c36..1a6173c22c 100644 --- a/packages/page-js/src/types.ts +++ b/packages/page-js/src/types.ts @@ -2,8 +2,8 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { SemanticShorthandItem } from 'semantic-ui-react/dist/commonjs/generic'; -import { LabelProps } from 'semantic-ui-react/dist/commonjs/elements/Label'; +import type { SemanticShorthandItem } from 'semantic-ui-react/dist/commonjs/generic'; +import type { LabelProps } from 'semantic-ui-react/dist/commonjs/elements/Label'; export type LogType = 'error' | 'log'; diff --git a/packages/page-settings/src/SelectUrl.tsx b/packages/page-settings/src/SelectUrl.tsx index d70ef40440..e15591208e 100644 --- a/packages/page-settings/src/SelectUrl.tsx +++ b/packages/page-settings/src/SelectUrl.tsx @@ -75,13 +75,12 @@ function SelectUrl ({ className = '', onChange }: Props): React.ReactElement - setInfo((info: State) => ({ ...info, ...makeUrl(url) })), + (url: string) => setInfo((info: State) => ({ ...info, ...makeUrl(url) })), [] ); const _onChangeCustom = useCallback( - (isCustom: boolean): void => setInfo({ + (isCustom: boolean) => setInfo({ ...makeUrl( isCustom ? info.url @@ -116,9 +115,9 @@ function SelectUrl ({ className = '', onChange }: Props): React.ReactElement ('custom endpoint')} onChange={_onChangeCustom} + value={isCustom} /> ); diff --git a/packages/page-staking/src/Targets/Validator.tsx b/packages/page-staking/src/Targets/Validator.tsx index dada2fd87a..f5a0219ced 100644 --- a/packages/page-staking/src/Targets/Validator.tsx +++ b/packages/page-staking/src/Targets/Validator.tsx @@ -7,7 +7,7 @@ import { ValidatorInfo } from '../types'; import React, { useCallback, useEffect, useState } from 'react'; import { ApiPromise } from '@polkadot/api'; -import { AddressSmall, Badge, Icon, Toggle } from '@polkadot/react-components'; +import { AddressSmall, Badge, Checkbox, Icon } from '@polkadot/react-components'; import { FormatBalance } from '@polkadot/react-query'; import { useApi, useCall } from '@polkadot/react-hooks'; import { formatNumber } from '@polkadot/util'; @@ -125,8 +125,7 @@ function Validator ({ canSelect, filterName, info, isNominated, isSelected, togg {!rewardPayout.isZero() && } {(canSelect || isSelected) && ( - diff --git a/packages/react-components/src/Checkbox.tsx b/packages/react-components/src/Checkbox.tsx new file mode 100644 index 0000000000..aada87cddb --- /dev/null +++ b/packages/react-components/src/Checkbox.tsx @@ -0,0 +1,63 @@ +// Copyright 2017-2020 @polkadot/react-components authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import React, { useCallback } from 'react'; +import styled from 'styled-components'; + +import Icon from './Icon'; + +interface Props { + className?: string; + isDisabled?: boolean; + label: React.ReactNode; + onChange?: (isChecked: boolean) => void; + value?: boolean; +} + +function Checkbox ({ className = '', isDisabled, label, onChange, value }: Props): React.ReactElement { + const _onClick = useCallback( + (): void => { + !isDisabled && onChange && onChange(!value); + }, + [isDisabled, onChange, value] + ); + + return ( +
+ + {label && } +
+ ); +} + +export default React.memo(styled(Checkbox)` + &.isDisabled { + opacity: 0.5; + } + + &:not(.isDisabled) { + cursor: pointer; + } + + > label { + color: rgba(78, 78, 78, 0.75); + display: inline-block; + margin: 0 0.5rem; + opacity: 1; + } + + > label, + > .ui--Icon { + vertical-align: middle; + } + + .ui--Icon { + border: 1px solid rgba(34, 36, 38, 0.15); + border-radius: 0.125rem; + } +`); diff --git a/packages/react-components/src/Icon.tsx b/packages/react-components/src/Icon.tsx index 5bd20b27a8..411bdda28e 100644 --- a/packages/react-components/src/Icon.tsx +++ b/packages/react-components/src/Icon.tsx @@ -10,7 +10,7 @@ import styled from 'styled-components'; interface Props { className?: string; - color?: 'gray' | 'green' | 'normal' | 'orange' | 'red'; + color?: 'gray' | 'green' | 'normal' | 'orange' | 'red' | 'transparent'; icon: IconName; isSpinning?: boolean; onClick?: () => void; @@ -58,4 +58,8 @@ export default React.memo(styled(Icon)` &.redColor { color: darkred; } + + &.transparentColor { + color: transparent; + } `); diff --git a/packages/react-components/src/Toggle.tsx b/packages/react-components/src/Toggle.tsx index 013037d84d..9e089eab78 100644 --- a/packages/react-components/src/Toggle.tsx +++ b/packages/react-components/src/Toggle.tsx @@ -3,13 +3,10 @@ // of the Apache-2.0 license. See the LICENSE file for details. import React, { useCallback } from 'react'; -import SUICheckbox from 'semantic-ui-react/dist/commonjs/modules/Checkbox'; import styled from 'styled-components'; interface Props { - asSwitch?: boolean; className?: string; - defaultValue?: boolean; isDisabled?: boolean; label: React.ReactNode; onChange?: (isChecked: boolean) => void; @@ -17,49 +14,78 @@ interface Props { value?: boolean; } -function Toggle ({ asSwitch = true, className = '', defaultValue, isDisabled, label, onChange, preventDefault, value }: Props): React.ReactElement { - const _onChange = useCallback( - (event: React.FormEvent, { checked }: any): void => { - if (preventDefault) { - event.preventDefault(); - event.stopPropagation(); - } +function Toggle ({ className = '', isDisabled, label, onChange, preventDefault, value }: Props): React.ReactElement { + const _onClick = useCallback( + (event: React.MouseEvent): void => { + if (!isDisabled) { + if (preventDefault) { + event.preventDefault(); + event.stopPropagation(); + } - onChange && onChange(checked); + onChange && onChange(!value); + } }, - [onChange, preventDefault] + [isDisabled, onChange, preventDefault, value] ); return ( -
- - +
+ {label && } +
); } export default React.memo(styled(Toggle)` > label { + color: rgba(78, 78, 78, 0.75); display: inline-block; margin: 0 0.5rem; } > label, - > .ui.checkbox { + > div { vertical-align: middle; } - .ui.checkbox + label { - color: rgba(78, 78, 78, 0.75); + .ui--Toggle-Slider { + border-radius: 1.5rem; + display: inline-block; + position: relative; + cursor: pointer; + background-color: #eee; + width: 3rem; + height: 1.5rem; + + &::before { + border: 0.125rem solid #eee; + border-radius: 50%; + position: absolute; + content: ""; + height: 1.5rem; + width: 1.5rem; + left: 0; + top: 0rem; + background-color: white; + } } - &.isCheckbox label { - opacity: 1 !important; + &.not(.isDisabled) .ui--Toggle-Slider { + cursor: pointer; + } + + &.isChecked { + .ui--Toggle-Slider { + background: #2196F3; + + &:before { + border-color: #2196F3; + transform: translateX(1.5rem); + } + } } `); diff --git a/packages/react-components/src/index.tsx b/packages/react-components/src/index.tsx index af71bb3dea..d103619184 100644 --- a/packages/react-components/src/index.tsx +++ b/packages/react-components/src/index.tsx @@ -27,6 +27,7 @@ export { default as CardSummary } from './CardSummary'; export { default as ChainImg } from './ChainImg'; export { default as ChainLock } from './ChainLock'; export { default as Chart } from './Chart'; +export { default as Checkbox } from './Checkbox'; export { default as Columar } from './Columar'; export { default as Column } from './Column'; export { default as ConvictionDropdown } from './ConvictionDropdown'; diff --git a/packages/react-components/src/styles/index.ts b/packages/react-components/src/styles/index.ts index fdeffab0d1..77a1d34521 100644 --- a/packages/react-components/src/styles/index.ts +++ b/packages/react-components/src/styles/index.ts @@ -92,10 +92,11 @@ export default createGlobalStyle` } } - .ui.toggle.checkbox { - input:checked~.box:before, - input:checked~label:before { - background-color: ${getHighlight} !important; + .ui--Toggle.isChecked .ui--Toggle-Slider { + background-color: ${getHighlight} !important; + + &:before { + border-color: ${getHighlight} !important; } } } @@ -126,13 +127,6 @@ export default createGlobalStyle` color: #555 !important; } - .ui.toggle.checkbox { - input:checked~.box:before, - input:checked~label:before { - background-color: #eee !important; - } - } - .ui.button.show-on-hover { visibility: hidden; }