feat(ui): add PasswordInput(锁图标 + 显隐切换)

- Input + IconButton 组合,type 切换、aria-pressed、尺寸对齐内建
- 展示页补「密码框」示例与 props 表;COMPONENTS.md / README 同步
- 版本 0.3.0
This commit is contained in:
2026-10-29 20:46:07 +08:00
parent 0d5d7753e2
commit 93b1e41d28
8 changed files with 147 additions and 5 deletions
+2 -2
View File
@@ -147,7 +147,7 @@ export function App() {
<span className="doc-brand-mark">S</span>
<span>
<strong>Stash UI</strong>
<em>v0.1.0</em>
<em>v0.3.0</em>
</span>
</a>
@@ -189,7 +189,7 @@ export function App() {
组件只依赖令牌,不依赖任何页面数据,所以换页面、换应用都能直接拼。
</p>
<div className="doc-hero-meta">
<span>40 个基础组件</span>
<span>42 个基础组件</span>
<span>零运行时依赖</span>
<span>CSS Modules + 设计令牌</span>
<span>对齐 Alright 参考站</span>
+40 -1
View File
@@ -1,5 +1,5 @@
import { useState } from 'react'
import { Button, FormField, Icon, Input, Space, Text, Textarea } from '../../src'
import { Button, FormField, Icon, Input, PasswordInput, Space, Text, Textarea } from '../../src'
import { Demo } from '../components/Demo'
import { PropsTable } from '../components/PropsTable'
import { Section } from '../components/Section'
@@ -8,6 +8,7 @@ export function Inputs() {
const [keyword, setKeyword] = useState('')
const [host, setHost] = useState('127.0.0.1:8080')
const [email, setEmail] = useState('not-an-email')
const [password, setPassword] = useState('')
return (
<Section
@@ -133,6 +134,31 @@ export function Inputs() {
</div>
</Demo>
<Demo
title="密码框"
desc="PasswordInput 在 Input 右侧固定一个眼睛按钮,显隐切换与无障碍名称都封装在组件里;登录、改密这类页面直接用它,不要漏掉切换按钮。"
layout="column"
code={`<FormField label="密码" htmlFor="demo-password" required hint="至少 8 位">
<PasswordInput
id="demo-password"
value={password}
onChange={(event) => setPassword(event.target.value)}
placeholder="输入密码"
/>
</FormField>`}
>
<div style={{ width: 320 }}>
<FormField label="密码" htmlFor="demo-password" required hint="至少 8 位">
<PasswordInput
id="demo-password"
value={password}
onChange={(event) => setPassword(event.target.value)}
placeholder="输入密码"
/>
</FormField>
</div>
</Demo>
<PropsTable
rows={[
{ name: 'icon', type: 'IconName', desc: '左侧前缀图标' },
@@ -157,6 +183,19 @@ export function Inputs() {
{ name: '…rest', type: 'TextareaHTMLAttributes', desc: '透传原生属性' },
]}
/>
<Text size="sm" tone="muted" style={{ marginTop: 24 }}>
PasswordInput
</Text>
<PropsTable
rows={[
{ name: 'icon', type: 'IconName | null', defaultValue: "'lock_line'", desc: '左侧图标;null 表示不显示' },
{ name: 'size', type: "'sm' | 'md' | 'lg'", defaultValue: "'md'", desc: '32 / 36 / 44px,与 Input 一致' },
{ name: 'toggle', type: 'boolean', defaultValue: 'true', desc: '是否显示右侧显隐按钮' },
{ name: 'className / style', type: 'string / CSSProperties', desc: '作用在最外层容器上' },
{ name: '…rest', type: 'InputHTMLAttributes', desc: '透传原生属性(type / size / icon 由组件接管)' },
]}
/>
</Section>
)
}