feat(ui): Checkbox/Radio 原子件 + 3 处原生控件采用(P2-5)

- checkboxClass/radioClass(accent-cinnabar + 统一焦点环)+ 同名测试
- Checkbox/Radio 原子件:无 label 只渲染受控原生 input 便于就地替换
- 采用:ChainStarter 链类型单选、GeneratorRunner 入库勾选、CharacterCardItem 角色勾选
This commit is contained in:
Yaojia Wang
2026-07-11 14:04:01 +02:00
parent 45025c36bf
commit 355a2d11cd
7 changed files with 68 additions and 7 deletions

View File

@@ -0,0 +1,20 @@
import type { InputHTMLAttributes, ReactNode } from "react";
import { checkboxClass } from "@/lib/ui/variants";
interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type"> {
label?: ReactNode;
}
// 勾选框:无 label 时只渲染受控原生 input供已有 <label>/布局包裹的调用点直接替换);
// 有 label 时自带 <label> 包裹,保留原生键盘/读屏语义。
export function Checkbox({ label, className, ...props }: CheckboxProps) {
const input = <input type="checkbox" className={checkboxClass(className)} {...props} />;
if (!label) return input;
return (
<label className="inline-flex items-center gap-2 text-sm text-ink">
{input}
<span>{label}</span>
</label>
);
}

View File

@@ -0,0 +1,20 @@
import type { InputHTMLAttributes, ReactNode } from "react";
import { radioClass } from "@/lib/ui/variants";
interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type"> {
label?: ReactNode;
}
// 单选钮:无 label 时只渲染受控原生 input供已有 <label>/布局包裹的调用点直接替换);
// 有 label 时自带 <label> 包裹,保留原生键盘/读屏语义。
export function Radio({ label, className, ...props }: RadioProps) {
const input = <input type="radio" className={radioClass(className)} {...props} />;
if (!label) return input;
return (
<label className="inline-flex items-center gap-2 text-sm text-ink">
{input}
<span>{label}</span>
</label>
);
}