feat(Input): 增加只读属性并优化相关交互

- 在 Input 组件的属性中添加 readonly
- 实现只读状态下的输入框行为:禁止输入但允许聚焦
- 为只读状态的输入框添加视觉反馈
This commit is contained in:
Vixalie
2025-08-24 11:19:58 +08:00
parent 9fe13bde17
commit 9eeb223b97

View File

@@ -11,6 +11,7 @@ interface InputProps {
defaultValue?: string; defaultValue?: string;
placeholder?: string; placeholder?: string;
disabled?: boolean; disabled?: boolean;
readonly?: boolean;
onInput?: (value: string | null) => void; onInput?: (value: string | null) => void;
wrapperClass?: JSX.HTMLAttributes<HTMLDivElement>['class']; wrapperClass?: JSX.HTMLAttributes<HTMLDivElement>['class'];
inputClass?: JSX.HTMLAttributes<HTMLInputElement>['class']; inputClass?: JSX.HTMLAttributes<HTMLInputElement>['class'];
@@ -21,6 +22,7 @@ const Input: Component<InputProps> = (props) => {
{ {
variant: 'normal', variant: 'normal',
disabled: false, disabled: false,
readonly: false,
placeholder: '', placeholder: '',
}, },
props, props,
@@ -38,6 +40,9 @@ const Input: Component<InputProps> = (props) => {
}); });
const handleInput: JSX.EventHandler<HTMLInputElement, InputEvent> = (evt) => { const handleInput: JSX.EventHandler<HTMLInputElement, InputEvent> = (evt) => {
if (mProps.readonly || mProps.disabled) {
return;
}
const value = evt.currentTarget.value; const value = evt.currentTarget.value;
setInternalValue(value); setInternalValue(value);
mProps.onInput?.(value); mProps.onInput?.(value);
@@ -46,8 +51,9 @@ const Input: Component<InputProps> = (props) => {
return ( return (
<div <div
aria-disabled={mProps.disabled} aria-disabled={mProps.disabled}
aria-readonly={mProps.readonly}
class={cx( class={cx(
'flex flex-row items-center gap-2 min-h-[1em] px-3 py-1.5', 'flex flex-row items-center gap-2 min-h-[1em] px-3 py-1.5 aria-readonly:cursor-not-allowed',
mProps.variant === 'normal' && mProps.variant === 'normal' &&
'rounded-sm bg-neutral text-on-neutral aria-disabled:cursor-not-allowed aria-disabled:text-neutral-disabled', 'rounded-sm bg-neutral text-on-neutral aria-disabled:cursor-not-allowed aria-disabled:text-neutral-disabled',
mProps.variant === 'underlined' && mProps.variant === 'underlined' &&
@@ -61,6 +67,7 @@ const Input: Component<InputProps> = (props) => {
type={mProps.type} type={mProps.type}
placeholder={mProps.placeholder} placeholder={mProps.placeholder}
disabled={mProps.disabled} disabled={mProps.disabled}
readonly={mProps.readonly}
value={internalValue()} value={internalValue()}
class={cx( class={cx(
'min-h-[1em] grow focus:outline-none placeholder:italic disabled:text-neutral-disabled', 'min-h-[1em] grow focus:outline-none placeholder:italic disabled:text-neutral-disabled',