diff --git a/docs/components/upload.md b/docs/components/upload.md
index 9bef5ad..e724f3f 100644
--- a/docs/components/upload.md
+++ b/docs/components/upload.md
@@ -12,11 +12,17 @@
}
`" />
+## 键盘操作
+
+触发区关联原生文件输入,支持通过 `Tab` 聚焦,并使用浏览器默认的文件选择快捷键打开文件选择器。
+
## API
-| 属性 | 说明 | 类型 | 默认值 |
-| --- | --- | --- | --- |
-| accept | 接受的文件类型 | `string` | - |
-| multiple | 是否多选 | `boolean` | `false` |
-| fileList | 文件列表 | `UploadFileItem[]` | - |
-| onChange | 文件变化回调 | `(files) => void` | - |
+| 属性 | 说明 | 类型 | 默认值 |
+| ----------- | -------------- | ------------------ | ------------------------------ |
+| accept | 接受的文件类型 | `string` | - |
+| multiple | 是否多选 | `boolean` | `false` |
+| disabled | 禁用上传 | `boolean` | `false` |
+| fileList | 文件列表 | `UploadFileItem[]` | - |
+| triggerText | 触发区内容 | `ReactNode` | `Click or drag file to upload` |
+| onChange | 文件变化回调 | `(files) => void` | - |
diff --git a/packages/ui/src/components/form/controls/Upload/Upload.test.tsx b/packages/ui/src/components/form/controls/Upload/Upload.test.tsx
new file mode 100644
index 0000000..086d400
--- /dev/null
+++ b/packages/ui/src/components/form/controls/Upload/Upload.test.tsx
@@ -0,0 +1,65 @@
+import { render, screen } from '@testing-library/react'
+import userEvent from '@testing-library/user-event'
+import { describe, expect, it, vi } from 'vitest'
+
+import { Upload } from './Upload'
+
+describe('Upload', () => {
+ it('exposes a focusable file input through the visible trigger text', async () => {
+ const user = userEvent.setup()
+
+ render()
+
+ const input = screen.getByLabelText('Select files')
+ expect(input).toHaveAttribute('type', 'file')
+
+ await user.tab()
+ expect(input).toHaveFocus()
+ })
+
+ it('calls onChange with selected file metadata', async () => {
+ const user = userEvent.setup()
+ const onChange = vi.fn()
+ const file = new File(['hello'], 'report.txt', {
+ lastModified: 123,
+ type: 'text/plain',
+ })
+
+ render()
+
+ await user.upload(screen.getByLabelText('Upload report'), file)
+
+ expect(onChange).toHaveBeenCalledWith([
+ {
+ uid: 'report.txt-123',
+ name: 'report.txt',
+ size: 5,
+ },
+ ])
+ })
+
+ it('passes accept, multiple, and disabled attributes to the input', () => {
+ render()
+
+ const input = screen.getByLabelText('Upload images')
+
+ expect(input).toHaveAttribute('accept', 'image/png')
+ expect(input).toHaveAttribute('multiple')
+ expect(input).toBeDisabled()
+ })
+
+ it('renders the controlled file list with list semantics', () => {
+ render(
+ ,
+ )
+
+ expect(screen.getByRole('list', { name: 'Uploaded files' })).toBeInTheDocument()
+ expect(screen.getByText('first.pdf')).toBeInTheDocument()
+ expect(screen.getByText('second.pdf')).toBeInTheDocument()
+ })
+})
diff --git a/packages/ui/src/components/form/controls/Upload/Upload.tsx b/packages/ui/src/components/form/controls/Upload/Upload.tsx
index a19de2e..f2decb1 100644
--- a/packages/ui/src/components/form/controls/Upload/Upload.tsx
+++ b/packages/ui/src/components/form/controls/Upload/Upload.tsx
@@ -40,19 +40,28 @@ export const Upload = forwardRef(function Upload(
return (