Skip to content

Commit

Permalink
feat: ✨ implement switch
Browse files Browse the repository at this point in the history
  • Loading branch information
huang-xiao-jian committed Jun 7, 2020
1 parent 278c5ed commit 7b9e2c7
Show file tree
Hide file tree
Showing 4 changed files with 205 additions and 0 deletions.
63 changes: 63 additions & 0 deletions packages/Switch/Switch.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
.van-switch {
position: relative;
display: inline-block;
box-sizing: content-box;
width: 2em;
width: var(--switch-width, 2em);
height: 1em;
height: var(--switch-height, 1em);
background-color: #fff;
background-color: var(--switch-background-color, #fff);
border: 1px solid rgba(0, 0, 0, 0.1);
border: var(--switch-border, 1px solid rgba(0, 0, 0, 0.1));
border-radius: 1em;
border-radius: var(--switch-node-size, 1em);
transition: background-color 0.3s;
transition: background-color var(--switch-transition-duration, 0.3s);
}
.van-switch__node {
position: absolute;
top: 0;
left: 0;
border-radius: 100%;
z-index: 1;
z-index: var(--switch-node-z-index, 1);
width: 1em;
width: var(--switch-node-size, 1em);
height: 1em;
height: var(--switch-node-size, 1em);
background-color: #fff;
background-color: var(--switch-node-background-color, #fff);
box-shadow: 0 3px 1px 0 rgba(0, 0, 0, 0.05), 0 2px 2px 0 rgba(0, 0, 0, 0.1),
0 3px 3px 0 rgba(0, 0, 0, 0.05);
box-shadow: var(
--switch-node-box-shadow,
0 3px 1px 0 rgba(0, 0, 0, 0.05),
0 2px 2px 0 rgba(0, 0, 0, 0.1),
0 3px 3px 0 rgba(0, 0, 0, 0.05)
);
transition: transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05);
transition: transform var(--switch-transition-duration, 0.3s)
cubic-bezier(0.3, 1.05, 0.4, 1.05);
}
.van-switch__loading {
position: absolute !important;
top: 25%;
left: 25%;
width: 50%;
height: 50%;
}
.van-switch--on {
background-color: #1989fa;
background-color: var(--switch-on-background-color, #1989fa);
}
.van-switch--on .van-switch__node {
transform: translateX(calc(2em - 1em));
transform: translateX(
calc(var(--switch-width, 2em) - var(--switch-node-size, 1em))
);
}
.van-switch--disabled {
opacity: 0.4;
opacity: var(--switch-disabled-opacity, 0.4);
}
92 changes: 92 additions & 0 deletions packages/Switch/Switch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// packages
import React, { FunctionComponent, CSSProperties } from 'react';
import clsx from 'clsx';
import { View } from 'remax/wechat';
// internal
import Loading from '../Loading';
import { Select } from '../tools/Switch';
import pickStyle from '../tools/pick-style';
import withDefaultProps from '../tools/with-default-props-advance';
import './Switch.css';

// 默认值填充属性
interface NeutralSwitchProps {
checked: any;
loading: boolean;
disabled: boolean;
size: string;
activeColor: string;
inactiveColor: string;
activeValue: any;
inactiveValue: any;
}

interface ExogenousSwitchProps {
name?: string;
// 容器类名,用以覆盖内部
className?: string;
// 事件绑定
onChange?: (event: any) => void;
}

type SwitchProps = NeutralSwitchProps & ExogenousSwitchProps;

const DefaultSwitchProps: NeutralSwitchProps = {
checked: false,
loading: false,
disabled: false,
size: '30px',
activeColor: '#1989fa',
inactiveColor: '#969799',
activeValue: true,
inactiveValue: false,
};

const Switch: FunctionComponent<SwitchProps> = (props) => {
const {
checked,
size,
disabled,
loading,
activeColor,
activeValue,
inactiveColor,
inactiveValue,
className,
onChange,
} = props;
const classnames = {
container: clsx(className, 'van-switch', {
'van-switch--disabled': disabled,
'van-switch--on': checked === activeValue,
}),
};
const style: CSSProperties = pickStyle({
fontSize: size,
backgroundColor: checked ? activeColor : inactiveColor,
});
const loadingColor = checked ? activeColor : inactiveColor;
const onClick = () => {
if (!disabled && !loading) {
const value = checked === activeValue ? inactiveValue : activeValue;

if (typeof onChange === 'function') {
onChange({ detail: value });
}
}
};

return (
<View className={classnames.container} style={style} onClick={onClick}>
<View className="van-switch__node">
<Select in={loading}>
<Loading color={loadingColor} className="van-switch__loading" />
</Select>
</View>
</View>
);
};

export default withDefaultProps<ExogenousSwitchProps, NeutralSwitchProps>(
DefaultSwitchProps
)(Switch);
4 changes: 4 additions & 0 deletions packages/Switch/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/**
* @description - nothing but export component
*/
export { default } from './Switch';
46 changes: 46 additions & 0 deletions public/pages/switch/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// packages
import React, { useState } from 'react';
import { View, Text } from 'remax/wechat';

// internal
import Switch from '../../../packages/Switch';

export default () => {
const [checked, setChecked] = useState(true);
const onChange = () => {
setChecked((prev) => !prev);
};

return (
<View className="demo-block">
<Text className="demo-block__title">基础用法</Text>
<View className="demo-block__content">
<Switch checked={checked} onChange={onChange} />
</View>

<Text className="demo-block__title">禁用状态</Text>
<View className="demo-block__content">
<Switch checked={checked} disabled onChange={onChange} />
</View>

<Text className="demo-block__title">加载状态</Text>
<View className="demo-block__content">
<Switch checked={checked} loading onChange={onChange} />
</View>

<Text className="demo-block__title">自定义大小</Text>
<View className="demo-block__content">
<Switch checked={checked} size="24px" onChange={onChange} />
</View>
<Text className="demo-block__title">自定义颜色</Text>
<View className="demo-block__content">
<Switch
checked={checked}
activeColor="#07c160"
inactiveColor="#ee0a24"
onChange={onChange}
/>
</View>
</View>
);
};

0 comments on commit 7b9e2c7

Please sign in to comment.