From b3685210da3e6f7ea80dc7563ece1012809d80a6 Mon Sep 17 00:00:00 2001 From: Jimmy Ben Klieve Date: Sat, 12 Aug 2023 23:05:11 +0800 Subject: [PATCH] feat(checkbox): add checkbox --- docs/src/app/module/checkbox/page.mdx | 67 +++++++++++- .../src/components/Checkbox/Checkbox.tsx | 62 +++++++++++ .../src/components/Checkbox/index.ts | 3 + .../components/Checkbox/style/Checkbox.scss | 103 ++++++++++++++++++ packages/yike-design/src/index.ts | 1 + 5 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 packages/yike-design/src/components/Checkbox/Checkbox.tsx create mode 100644 packages/yike-design/src/components/Checkbox/index.ts create mode 100644 packages/yike-design/src/components/Checkbox/style/Checkbox.scss diff --git a/docs/src/app/module/checkbox/page.mdx b/docs/src/app/module/checkbox/page.mdx index f16c1677..02d665d1 100644 --- a/docs/src/app/module/checkbox/page.mdx +++ b/docs/src/app/module/checkbox/page.mdx @@ -1 +1,66 @@ -# Checkbox 复选框 \ No newline at end of file +# Checkbox 复选框 + +## 未选定和选定状态 + +```tsx +import { Checkbox } from '@yike-design/react'; + +export default () => { + return ( +
+ 选项 1 + 选项 2 +
+ ); +}; +``` + +## 特殊的半选状态 + +```tsx +import { Checkbox } from '@yike-design/react'; + +export default () => { + return ( +
+ 半选 +
+ ); +}; +``` + +## 已禁用 + +```tsx +import { Checkbox } from '@yike-design/react'; + +export default () => { + return ( +
+ 未选 + + 已选 + + + 半选 + +
+ ); +}; +``` + +## API + +### `` + +| 属性 | 类型 | 默认值 | 说明 | +| --------------- | ------------------------------ | ------ | ------------------------ | +| `checked` | `boolean` | - | 设置是否勾选的状态 | +| `indeterminate` | `boolean` | - | 设置是否为半选状态 | +| `onChange` | `(isChecked: boolean) => void` | - | 勾选状态改变时的回调函数 | diff --git a/packages/yike-design/src/components/Checkbox/Checkbox.tsx b/packages/yike-design/src/components/Checkbox/Checkbox.tsx new file mode 100644 index 00000000..eea2dc1b --- /dev/null +++ b/packages/yike-design/src/components/Checkbox/Checkbox.tsx @@ -0,0 +1,62 @@ +'use client'; + +import React from 'react'; + +import './style/Checkbox.scss'; + +export interface CheckboxProps { + checked?: boolean; + indeterminate?: boolean; + + onChange: (isChecked: boolean) => void; +} + +const Checkbox: React.FC< + CheckboxProps & Omit, keyof CheckboxProps> +> = props => { + const { + children, + checked, + indeterminate = false, + onChange, + + // rest + ...restProps + } = props; + + const inputRef = React.useRef(null); + + const handleChange = React.useCallback>( + evt => { + const { checked } = evt.target; + + if (typeof onChange === 'function') { + onChange(checked); + } + }, + [onChange] + ); + + React.useLayoutEffect(() => { + if (inputRef.current) { + inputRef.current.indeterminate = indeterminate; + } + }, [indeterminate]); + + return ( +
+ +
+ ); +}; + +export default Checkbox; diff --git a/packages/yike-design/src/components/Checkbox/index.ts b/packages/yike-design/src/components/Checkbox/index.ts new file mode 100644 index 00000000..c81c2c02 --- /dev/null +++ b/packages/yike-design/src/components/Checkbox/index.ts @@ -0,0 +1,3 @@ +import Checkbox from './Checkbox'; + +export { Checkbox }; diff --git a/packages/yike-design/src/components/Checkbox/style/Checkbox.scss b/packages/yike-design/src/components/Checkbox/style/Checkbox.scss new file mode 100644 index 00000000..384baec3 --- /dev/null +++ b/packages/yike-design/src/components/Checkbox/style/Checkbox.scss @@ -0,0 +1,103 @@ +@use 'sass:color'; +@import '../../../styles/tokens/index'; + +.yk-checkbox { + display: inline-flex; + margin-right: 1rem; + + > label { + position: relative; + + > input[type='checkbox'] { + position: absolute; + visibility: hidden; + opacity: 0; + + &:checked { + + .yk-checkbox_content { + &::before { + background-color: $color-primary; + border-color: $color-primary; + } + + &::after { + opacity: 1; + } + } + } + + &:indeterminate { + + .yk-checkbox_content { + &::before { + background-color: $color-primary; + border-color: $color-primary; + } + + &::after { + top: 50%; + height: 0; + border-left: none; + opacity: 1; + transform: translate(-50%); + } + } + } + + &:disabled { + + .yk-checkbox_content { + &::before { + cursor: auto; + background-color: #f3f3f4; + border-color: #e8e9eb; + } + + &::after { + border-color: #000; + } + } + } + } + + .yk-checkbox_content { + padding-left: 1.5em; + + &::before { + position: absolute; + top: 50%; + left: 0; + display: block; + width: 1em; + height: 1em; + line-height: 1em; + cursor: pointer; + content: ' '; + border: 1px solid color.mix(#1e2025, #fff, 18%); + border-radius: 4px; + transition: all $motion-duration-short3 $motion-easing-standard; + transform: translateY(-50%); + } + + &::after { + position: absolute; + top: calc(50% - 1px); + left: 0.5em; + width: 0.5em; + height: 0.25em; + pointer-events: none; + content: ' '; + border-bottom: 1px solid #fff; + border-left: 1px solid #fff; + opacity: 0; + transform: translate(-50%, -50%) rotate(-45deg); + } + } + + &:hover { + .yk-checkbox_content { + &::before { + border-color: $color-primary; + } + } + } + } +} diff --git a/packages/yike-design/src/index.ts b/packages/yike-design/src/index.ts index 28a6ee3b..42185b0c 100644 --- a/packages/yike-design/src/index.ts +++ b/packages/yike-design/src/index.ts @@ -1,2 +1,3 @@ export * from './components/Button'; export * from './components/Space'; +export * from './components/Checkbox';