diff --git a/docs/components/toast.md b/docs/components/toast.md
index 79f45f5..9decf4b 100644
--- a/docs/components/toast.md
+++ b/docs/components/toast.md
@@ -7,14 +7,18 @@
+## 可访问性
+
+Toast 默认会把 `info`、`success`、`warning` 作为 `role="status"` 的礼貌通知呈现;`error` 默认作为 `role="alert"` 的紧急通知呈现。需要更细粒度控制时,可以显式传入 `role` 与 `aria-live`。
+
## API
| 属性 | 说明 | 类型 | 默认值 |
@@ -22,4 +26,6 @@
| open | 是否显示 | `boolean` | `false` |
| duration | 显示时长(ms),0 表示不自动关闭 | `number` | `3000` |
| status | 状态 | `'info' \| 'success' \| 'warning' \| 'error'` | `'info'` |
+| role | live region 语义,默认 error 为 alert,其余状态为 status | `'status' \| 'alert'` | - |
+| aria-live | live region 播报优先级,传入后覆盖默认值 | `'off' \| 'polite' \| 'assertive'` | - |
| onClose | 关闭回调 | `() => void` | - |
diff --git a/packages/ui/src/components/feedback/Toast/Toast.test.tsx b/packages/ui/src/components/feedback/Toast/Toast.test.tsx
index b290059..7b88741 100644
--- a/packages/ui/src/components/feedback/Toast/Toast.test.tsx
+++ b/packages/ui/src/components/feedback/Toast/Toast.test.tsx
@@ -17,6 +17,30 @@ describe('Toast', () => {
expect(toast).toHaveTextContent('Saved successfully')
})
+ it('renders error updates as alert regions', () => {
+ render(
+
+ Save failed
+ ,
+ )
+
+ const toast = screen.getByRole('alert')
+ expect(toast).not.toHaveAttribute('aria-live')
+ expect(toast).toHaveTextContent('Save failed')
+ })
+
+ it('allows callers to override live region urgency', () => {
+ render(
+
+ Session expiring
+ ,
+ )
+
+ const toast = screen.getByRole('alert')
+ expect(toast).toHaveAttribute('aria-live', 'assertive')
+ expect(toast).toHaveTextContent('Session expiring')
+ })
+
it('uses a 3000ms default auto-close duration', () => {
vi.useFakeTimers()
const onClose = vi.fn()
diff --git a/packages/ui/src/components/feedback/Toast/Toast.tsx b/packages/ui/src/components/feedback/Toast/Toast.tsx
index 9fe06ef..1742169 100644
--- a/packages/ui/src/components/feedback/Toast/Toast.tsx
+++ b/packages/ui/src/components/feedback/Toast/Toast.tsx
@@ -1,17 +1,35 @@
import { forwardRef, type HTMLAttributes, useEffect } from 'react'
import { cn } from '../../../utils/cn'
+type ToastStatus = 'info' | 'success' | 'warning' | 'error'
+type ToastRole = 'status' | 'alert'
+
export interface ToastProps extends HTMLAttributes {
open?: boolean
duration?: number
onClose?: () => void
- status?: 'info' | 'success' | 'warning' | 'error'
+ status?: ToastStatus
+ /** 轻提示的 live region 语义,默认 error 为 alert,其余状态为 status */
+ role?: ToastRole
}
export const Toast = forwardRef(function Toast(
- { className, open = false, duration = 3000, onClose, status = 'info', children, ...props },
+ {
+ className,
+ open = false,
+ duration = 3000,
+ onClose,
+ status = 'info',
+ role,
+ 'aria-live': ariaLive,
+ children,
+ ...props
+ },
ref,
) {
+ const toastRole = role ?? (status === 'error' ? 'alert' : 'status')
+ const toastAriaLive = ariaLive ?? (toastRole === 'status' ? 'polite' : undefined)
+
useEffect(() => {
if (!open || duration <= 0) {
return
@@ -29,8 +47,8 @@ export const Toast = forwardRef(function Toast(
return (