Skip to content
Merged
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
157 changes: 57 additions & 100 deletions assets/index.less
Original file line number Diff line number Diff line change
@@ -1,140 +1,97 @@
@checkboxPrefixCls: rc-checkbox;
@checkboxInnerPrefixCls: ~"@{checkboxPrefixCls}-inner";

/* Default state */
.@{checkboxPrefixCls} {
white-space: nowrap;
cursor: pointer;
outline: none;
display: inline-block;
position: relative;
display: inline-block;
width: 14px;
height: 14px;
line-height: 1;
white-space: nowrap;
vertical-align: middle;
background-color: #ffffff;
border-color: #d9d9d9;
border-style: solid;
border-width: 1px;
Comment on lines +13 to +15
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For conciseness and better readability, consider using the border shorthand property to set the width, style, and color of the border in one declaration.

  border: 1px solid #d9d9d9;

border-radius: 3px;
outline: none;
cursor: pointer;
transition: border-color 0.3s cubic-bezier(0.68, -0.55, 0.27, 1.55),
background-color 0.3s cubic-bezier(0.68, -0.55, 0.27, 1.55);

&:hover .@{checkboxInnerPrefixCls},
&-input:focus + .@{checkboxInnerPrefixCls} {
&:hover,
&-input:focus + & {
border-color: #3dbcf6;
}
Comment on lines +22 to 25
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

find . -name "*.tsx" -o -name "*.jsx" -o -name "*.ts" -o -name "*.js" | grep -E "(index|checkbox)" | head -20

Repository: react-component/checkbox

Length of output: 106


🏁 Script executed:

# Look for the checkbox component structure
rg -n "className.*rc-checkbox" --type tsx --type jsx -A 5 -B 5

Repository: react-component/checkbox

Length of output: 95


🏁 Script executed:

# Search for input element and checkbox wrapper relationship
rg -n "rc-checkbox-input" --type tsx --type jsx -A 3 -B 3

Repository: react-component/checkbox

Length of output: 95


🏁 Script executed:

cat -n ./src/index.tsx | head -100

Repository: react-component/checkbox

Length of output: 3239


🏁 Script executed:

# Search for the input and checkbox element relationship
rg -n "rc-checkbox-input\|rc-checkbox" -A 5 -B 5

Repository: react-component/checkbox

Length of output: 50


🏁 Script executed:

cat -n ./src/index.tsx | tail -20

Repository: react-component/checkbox

Length of output: 611


🏁 Script executed:

# Check if there's more content after line 100
wc -l ./src/index.tsx

Repository: react-component/checkbox

Length of output: 87


🏁 Script executed:

sed -n '90,110p' ./src/index.tsx

Repository: react-component/checkbox

Length of output: 423


🏁 Script executed:

sed -n '1,50p' ./assets/index.less

Repository: react-component/checkbox

Length of output: 1152


修复 focus 选择器与 DOM 结构的不兼容问题。

选择器 &-input:focus + & 编译后为 .rc-checkbox-input:focus + .rc-checkbox,这是一个相邻兄弟选择器。然而,根据 src/index.tsx 的 DOM 结构,input 元素是 .rc-checkbox 的子元素而非兄弟元素,因此该选择器永远无法匹配。这导致 input 获得焦点时的边框颜色变化样式不会生效。

需要将选择器改为适配当前 DOM 结构的方案,例如使用 :has() 伪类或重构 DOM 关系。

🤖 Prompt for AI Agents
In `@assets/index.less` around lines 22 - 25, The current selector `&-input:focus
+ &` assumes the input is a sibling of `.rc-checkbox` but the DOM in
`src/index.tsx` places the input inside `.rc-checkbox`, so the focus border
style never matches; update the LESS to target the parent when its child input
is focused (e.g. replace the sibling selector reference of `&-input:focus + &`
with a parent selector that matches `.rc-checkbox` containing the focused input,
such as using `:has(.rc-checkbox-input:focus)` on `.rc-checkbox`, or
alternatively move the focus style to the input and cascade it to the parent via
a class toggle), ensuring you reference the existing class names `&-input` /
`.rc-checkbox` used in the component.


&-inner {
&:after {
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
position: absolute;
left: 4px;
top: 1px;
display: table;
width: 5px;
height: 8px;
border: 2px solid #ffffff;
border-top: 0;
border-left: 0;
content: ' ';
animation-timing-function: cubic-bezier(0.68, -0.55, 0.27, 1.55);
animation-duration: 0.3s;
animation-name: amCheckboxOut;
}

position: relative;
top: 0;
left: 0;
display: inline-block;
width: 14px;
height: 14px;
border-width: 1px;
border-style: solid;
border-radius: 3px;
border-color: #d9d9d9;
background-color: #ffffff;
transition: border-color 0.3s cubic-bezier(0.68, -0.55, 0.27, 1.55), background-color 0.3s cubic-bezier(0.68, -0.55, 0.27, 1.55);
&:after {
position: absolute;
top: 1px;
left: 4px;
display: table;
width: 5px;
height: 8px;
border: 2px solid #ffffff;
border-top: 0;
border-left: 0;
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
animation-name: amCheckboxOut;
animation-duration: 0.3s;
animation-timing-function: cubic-bezier(0.68, -0.55, 0.27, 1.55);
content: ' ';
}

&-input {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 9999;
cursor: pointer;
opacity: 0;
top: 0;
bottom: 0;
right: 0;
}
}

/* Checked state */
.@{checkboxPrefixCls}-checked {
background-color: #3dbcf6;
border-color: #3dbcf6;

&:hover {
.@{checkboxInnerPrefixCls} {
border-color: #3dbcf6;
}
}

.@{checkboxInnerPrefixCls} {
border-color: #3dbcf6;
background-color: #3dbcf6;

&:after {
transform: rotate(45deg);
position: absolute;
left: 4px;
top: 1px;
display: table;
width: 5px;
height: 8px;
border: 2px solid #ffffff;
border-top: 0;
border-left: 0;
content: ' ';
animation-timing-function: cubic-bezier(0.68, -0.55, 0.27, 1.55);
animation-duration: 0.3s;
animation-name: amCheckboxOut;
}
}

@media print {
box-shadow: inset 0 0 0 16px #3dbcf6;
}
@media print {
box-shadow: inset 0 0 0 16px #3dbcf6;
}
}
Comment on lines 58 to 69
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This refactoring correctly preserves the existing styles. However, I noticed a potential pre-existing issue with the checkmark animation that could be fixed here. The checkmark currently fades out after appearing because of animation-name: amCheckboxOut on the base :after element. To fix this, you can override the animation for the checked state to use amCheckboxIn and ensure the final state persists. This will make use of the currently unused amCheckboxIn keyframes and provide a better user experience.

.@{checkboxPrefixCls}-checked {
  background-color: #3dbcf6;
  border-color: #3dbcf6;

  &:after {
    animation-name: amCheckboxIn;
    animation-fill-mode: forwards;
  }

  &:hover {
    border-color: #3dbcf6;
  }

  @media print {
    box-shadow: inset 0 0 0 16px #3dbcf6;
  }
}

Comment on lines 58 to 69
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

选中状态缺少 amCheckboxIn 动画。

默认的 :after 伪元素设置了 animation-name: amCheckboxOut,但选中状态没有添加 &:after 规则来应用 amCheckboxIn 动画。这会导致勾选标记在选中时无法正确显示动画效果。

🐛 建议添加选中状态的动画规则
 .@{checkboxPrefixCls}-checked {
   background-color: `#3dbcf6`;
   border-color: `#3dbcf6`;

+  &:after {
+    animation-name: amCheckboxIn;
+  }
+
   &:hover {
     border-color: `#3dbcf6`;
   }

   `@media` print {
     box-shadow: inset 0 0 0 16px `#3dbcf6`;
   }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.@{checkboxPrefixCls}-checked {
background-color: #3dbcf6;
border-color: #3dbcf6;
&:hover {
.@{checkboxInnerPrefixCls} {
border-color: #3dbcf6;
}
}
.@{checkboxInnerPrefixCls} {
border-color: #3dbcf6;
background-color: #3dbcf6;
&:after {
transform: rotate(45deg);
position: absolute;
left: 4px;
top: 1px;
display: table;
width: 5px;
height: 8px;
border: 2px solid #ffffff;
border-top: 0;
border-left: 0;
content: ' ';
animation-timing-function: cubic-bezier(0.68, -0.55, 0.27, 1.55);
animation-duration: 0.3s;
animation-name: amCheckboxOut;
}
}
@media print {
box-shadow: inset 0 0 0 16px #3dbcf6;
}
@media print {
box-shadow: inset 0 0 0 16px #3dbcf6;
}
}
.@{checkboxPrefixCls}-checked {
background-color: `#3dbcf6`;
border-color: `#3dbcf6`;
&:after {
animation-name: amCheckboxIn;
}
&:hover {
border-color: `#3dbcf6`;
}
`@media` print {
box-shadow: inset 0 0 0 16px `#3dbcf6`;
}
}
🤖 Prompt for AI Agents
In `@assets/index.less` around lines 58 - 69, The checked state block for
@{checkboxPrefixCls}-checked is missing the &:after rule to apply the
amCheckboxIn animation (the default :after uses amCheckboxOut), so add an
&:after nested rule inside @{checkboxPrefixCls}-checked that sets
animation-name: amCheckboxIn (and matching animation-duration/animation-timing
if used elsewhere) so the check mark plays the "in" animation when checked;
update the &:after selector that references the pseudo-element and ensure it
mirrors the properties used by the default :after except with animation-name
changed to amCheckboxIn.


.@{checkboxPrefixCls}-disabled {
background-color: #f3f3f3;
border-color: #d9d9d9;

&.@{checkboxPrefixCls}-checked {
&:after {
border-color: #f3f3f3;
animation-name: none;
}

&:hover {
.@{checkboxInnerPrefixCls} {
border-color: #d9d9d9;
}
&.@{checkboxPrefixCls}-checked {
background-color: #f3f3f3;
border-color: #d9d9d9;
&:after {
border-color: #cccccc;
animation-name: none;
}

.@{checkboxInnerPrefixCls} {
background-color: #f3f3f3;
border-color: #d9d9d9;

&:after {
animation-name: none;
border-color: #cccccc;
}

@media print {
box-shadow: inset 0 0 0 16px #f3f3f3;
}
@media print {
box-shadow: inset 0 0 0 16px #f3f3f3;
}
}

&:hover {
.@{checkboxInnerPrefixCls} {
border-color: #d9d9d9;
}
}

.@{checkboxInnerPrefixCls} {
border-color: #d9d9d9;
background-color: #f3f3f3;
&:after {
animation-name: none;
border-color: #f3f3f3;
}
}

.@{checkboxPrefixCls}-input {
Expand All @@ -144,14 +101,14 @@

@keyframes amCheckboxIn {
0% {
opacity: 0;
transform-origin: 50% 50%;
transform: scale(0, 0) rotate(45deg);
transform-origin: 50% 50%;
opacity: 0;
}
100% {
opacity: 1;
transform-origin: 50% 50%;
transform: scale(1, 1) rotate(45deg);
transform-origin: 50% 50%;
opacity: 1;
}
}

Expand Down
1 change: 0 additions & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ export const Checkbox = forwardRef<CheckboxRef, CheckboxProps>((props, ref) => {
checked={!!rawValue}
type={type}
/>
<span className={`${prefixCls}-inner`} />
</span>
);
});
Expand Down
12 changes: 0 additions & 12 deletions tests/__snapshots__/index.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ exports[`rc-checkbox click checkbox 1`] = `
class="rc-checkbox-input"
type="checkbox"
/>
<span
class="rc-checkbox-inner"
/>
</span>
`;

Expand All @@ -22,9 +19,6 @@ exports[`rc-checkbox click radio 1`] = `
class="rc-checkbox-input"
type="radio"
/>
<span
class="rc-checkbox-inner"
/>
</span>
`;

Expand All @@ -37,9 +31,6 @@ exports[`rc-checkbox control mode 1`] = `
class="rc-checkbox-input"
type="checkbox"
/>
<span
class="rc-checkbox-inner"
/>
</span>
`;

Expand All @@ -51,8 +42,5 @@ exports[`rc-checkbox works 1`] = `
class="rc-checkbox-input"
type="checkbox"
/>
<span
class="rc-checkbox-inner"
/>
</span>
`;