Files
codex-proxy-rs/frontend/src/components/base/BaseInput.vue
T
zyycnandClaude ae46d89de6 refactor(web): consolidate the font-weight scale to four semantic tiers
Replace the nine ad-hoc arbitrary font weights (620-820, 208 usages) with a four-tier scale: font-emphasis (650) and font-heavy (760) as new theme tokens, plus the standard font-bold (700) and font-extrabold (800). Every merge moves a weight by at most 30 units, below the perceptible threshold for UI text sizes. The SystemUpdateModal release-notes scoped styles reference the same tokens. Arbitrary font-[N] classes are now zero across the codebase; the scale is documented in the theme block.

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-26 22:21:36 +08:00

117 lines
3.7 KiB
Vue

<script setup lang="ts">
import { computed } from 'vue'
const props = withDefaults(
defineProps<{
placeholder?: string
type?: string
disabled?: boolean
error?: string
autocomplete?: string
name?: string
ariaLabel?: string
}>(),
{
placeholder: '',
type: 'text',
disabled: false,
error: undefined,
autocomplete: undefined,
name: undefined,
ariaLabel: undefined,
},
)
const model = defineModel<string>({ default: '' })
// number 输入也保持字符串契约,避免原生 v-model 隐式转换为 number。
function updateModel(event: Event) {
model.value = (event.target as HTMLInputElement).value
}
const containerClasses = computed(() => [
'relative inline-flex h-(--cp-input-height-default) w-full min-w-0 items-center gap-2.5 overflow-visible rounded-(--cp-input-radius-base) border-0 px-3.5 text-[13px] text-(--cp-text-primary) shadow-(--cp-shadow-input) transition-[background-color,box-shadow,color] duration-[160ms]',
props.disabled
? 'cursor-not-allowed bg-(--cp-disabled-bg) text-(--cp-disabled-text) shadow-none'
: props.error
? 'bg-(--cp-input-error-soft-bg) shadow-(--cp-shadow-input-error)'
: [
'bg-[var(--cp-input-current-bg,var(--cp-input-context-bg))]',
'hover:bg-[var(--cp-input-current-bg-hover,var(--cp-input-context-bg-hover))] hover:shadow-(--cp-shadow-input-hover)',
'focus-within:bg-(--cp-input-soft-bg-focus) focus-within:shadow-(--cp-shadow-input-focus)',
],
])
const iconClasses = computed(() => [
'inline-flex shrink-0',
props.disabled
? 'text-(--cp-disabled-icon)'
: props.error
? 'text-(--cp-danger)'
: 'text-(--cp-text-muted)',
])
const inputClasses = computed(() => [
'h-full min-w-0 flex-1 border-0 bg-transparent text-[13px] font-emphasis leading-[1.15] outline-0',
'placeholder:text-(--cp-text-muted) disabled:cursor-not-allowed disabled:text-(--cp-disabled-text)',
props.error
? 'text-(--cp-danger-text)'
: props.disabled
? 'text-(--cp-disabled-text)'
: 'text-(--cp-text-primary)',
])
</script>
<template>
<div class="grid box-content gap-2 overflow-visible p-0.75">
<span class="base-input__control" :class="containerClasses">
<span v-if="$slots.prefix" :class="iconClasses">
<slot name="prefix" />
</span>
<input
:value="model"
class="base-input__field"
:class="inputClasses"
:name="name"
:placeholder="placeholder"
:type="type"
:disabled="disabled"
:autocomplete="autocomplete"
:aria-label="ariaLabel"
:aria-invalid="error ? 'true' : undefined"
@input="updateModel"
>
<span v-if="$slots.suffix" :class="iconClasses">
<slot name="suffix" />
</span>
</span>
<span v-if="error" class="text-xs font-emphasis leading-[1.15] text-(--cp-danger-text)">{{
error
}}</span>
</div>
</template>
<style scoped>
.base-input__control {
--base-input-autofill-bg: var(--cp-input-current-bg, var(--cp-input-context-bg));
}
.base-input__control:hover {
--base-input-autofill-bg: var(--cp-input-current-bg-hover, var(--cp-input-context-bg-hover));
}
.base-input__control:focus-within {
--base-input-autofill-bg: var(--cp-input-soft-bg-focus);
}
.base-input__field:-webkit-autofill,
.base-input__field:-webkit-autofill:hover,
.base-input__field:-webkit-autofill:focus,
.base-input__field:autofill {
caret-color: var(--cp-text-primary);
-webkit-text-fill-color: var(--cp-text-primary) !important;
-webkit-box-shadow: 0 0 0 1000px var(--base-input-autofill-bg) inset !important;
box-shadow: 0 0 0 1000px var(--base-input-autofill-bg) inset !important;
}
</style>