Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(checkbox): add checkbox #12

Draft
wants to merge 1 commit into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 66 additions & 1 deletion docs/src/app/module/checkbox/page.mdx
Original file line number Diff line number Diff line change
@@ -1 +1,66 @@
# Checkbox 复选框
# Checkbox 复选框

## 未选定和选定状态

```tsx
import { Checkbox } from '@yike-design/react';

export default () => {
return (
<div>
<Checkbox>选项 1</Checkbox>
<Checkbox checked>选项 2</Checkbox>
</div>
);
};
```

## 特殊的半选状态

```tsx
import { Checkbox } from '@yike-design/react';

export default () => {
return (
<div>
<Checkbox indeterminate>半选</Checkbox>
</div>
);
};
```

## 已禁用

```tsx
import { Checkbox } from '@yike-design/react';

export default () => {
return (
<div>
<Checkbox disabled>未选</Checkbox>
<Checkbox
checked
disabled
>
已选
</Checkbox>
<Checkbox
indeterminate
disabled
>
半选
</Checkbox>
</div>
);
};
```

## API

### `<Checkbox>`

| 属性 | 类型 | 默认值 | 说明 |
| --------------- | ------------------------------ | ------ | ------------------------ |
| `checked` | `boolean` | - | 设置是否勾选的状态 |
| `indeterminate` | `boolean` | - | 设置是否为半选状态 |
| `onChange` | `(isChecked: boolean) => void` | - | 勾选状态改变时的回调函数 |
62 changes: 62 additions & 0 deletions packages/yike-design/src/components/Checkbox/Checkbox.tsx
Original file line number Diff line number Diff line change
@@ -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<React.InputHTMLAttributes<HTMLInputElement>, keyof CheckboxProps>
> = props => {
const {
children,
checked,
indeterminate = false,
onChange,

// rest
...restProps
} = props;

const inputRef = React.useRef<HTMLInputElement>(null);

const handleChange = React.useCallback<React.ChangeEventHandler<HTMLInputElement>>(
evt => {
const { checked } = evt.target;

if (typeof onChange === 'function') {
onChange(checked);
}
},
[onChange]
);

React.useLayoutEffect(() => {
if (inputRef.current) {
inputRef.current.indeterminate = indeterminate;
}
}, [indeterminate]);

return (
<div className="yk-checkbox">
<label>
<input
ref={inputRef}
{...restProps}
type="checkbox"
onChange={handleChange}
{...(checked != null ? { checked } : {})}
/>
<span className="yk-checkbox_content">{children}</span>
</label>
</div>
);
};

export default Checkbox;
3 changes: 3 additions & 0 deletions packages/yike-design/src/components/Checkbox/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Checkbox from './Checkbox';

export { Checkbox };
103 changes: 103 additions & 0 deletions packages/yike-design/src/components/Checkbox/style/Checkbox.scss
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
}
}
1 change: 1 addition & 0 deletions packages/yike-design/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './components/Button';
export * from './components/Space';
export * from './components/Checkbox';