docs(ui): expand bilingual component guides
This commit is contained in:
@@ -1,31 +1,98 @@
|
||||
---
|
||||
title: 添加响应式行为
|
||||
description: 当 CSS 无法表达行为变化时,使用共享的断点和交互 Hooks。
|
||||
title: 响应式与交互 Hooks
|
||||
description: 在行为必须随视口改变时同步断点,并为自定义交互元素添加波纹。
|
||||
order: 20
|
||||
toc:
|
||||
- id: breakpoints
|
||||
title: 断点
|
||||
- id: breakpoint-contract
|
||||
title: 断点约定
|
||||
- id: reading-breakpoints
|
||||
title: 读取断点
|
||||
- id: root-classes
|
||||
title: 根节点 class
|
||||
- id: server-rendering
|
||||
title: 服务端渲染
|
||||
- id: ripple
|
||||
title: 波纹交互
|
||||
---
|
||||
|
||||
## 断点 {#breakpoints}
|
||||
## 断点约定 {#breakpoint-contract}
|
||||
|
||||
共享断点把视口分成三段:
|
||||
|
||||
| 返回值 | 范围 |
|
||||
| --------- | --------------- |
|
||||
| `mobile` | 小于 768px |
|
||||
| `tablet` | 768px 至 1023px |
|
||||
| `desktop` | 大于等于 1024px |
|
||||
|
||||
仅视觉变化应优先使用 CSS。只有挂载内容、交互方式或数据量必须变化时,才在渲染逻辑中读取断点。
|
||||
|
||||
## 读取断点 {#reading-breakpoints}
|
||||
|
||||
```tsx
|
||||
import { useBreakpoint, useIsMobile } from "@workspace/ui/hooks/use-breakpoint"
|
||||
import {
|
||||
useBreakpoint,
|
||||
useIsDesktop,
|
||||
useIsMobile,
|
||||
useIsTablet,
|
||||
useOnBreakpoint,
|
||||
} from "@workspace/ui/hooks/use-breakpoint"
|
||||
|
||||
const breakpoint = useBreakpoint()
|
||||
const isMobile = useIsMobile()
|
||||
```
|
||||
|
||||
视觉变化优先使用 CSS 响应式变体。只有组件行为或挂载内容必须变化时才使用这些 Hooks。
|
||||
每个 hook 通过 `useSyncExternalStore` 订阅同一组 `matchMedia` 查询。`useOnBreakpoint(listener)` 只在断点发生变化后调用 listener,不会把初始值作为一次变化上报。
|
||||
|
||||
## 根节点 class {#root-classes}
|
||||
|
||||
挂载 `BreakpointReactor` 后,文档根节点会且只会拥有 `.ui:mobile`、`.ui:tablet`、`.ui:desktop` 中的一个:
|
||||
|
||||
```tsx
|
||||
import { BreakpointReactor } from "@workspace/ui/hooks/use-breakpoint"
|
||||
|
||||
;<>
|
||||
<BreakpointReactor />
|
||||
<App />
|
||||
</>
|
||||
```
|
||||
|
||||
`globals.css` 把它们注册为 `mobile:`、`tablet:`、`desktop:` 自定义变体。这样组件可以让 CSS 与行为层使用同一份三段式定义。
|
||||
|
||||
## 服务端渲染 {#server-rendering}
|
||||
|
||||
断点 Store 使用确定的桌面端服务端快照。当应用需要 CSS 与行为断点在水合前保持一致时,可用 `getBreakpointInitializationScript` 提前设置匹配的根节点类名。
|
||||
服务端快照固定为 `desktop`,保证 SSR 可重复。为了在水合前写入真实 class,可把 `getBreakpointInitializationScript()` 的结果作为内联脚本放到文档头部:
|
||||
|
||||
```tsx
|
||||
import { getBreakpointInitializationScript } from "@workspace/ui/hooks/use-breakpoint"
|
||||
|
||||
;<script
|
||||
dangerouslySetInnerHTML={{ __html: getBreakpointInitializationScript() }}
|
||||
/>
|
||||
```
|
||||
|
||||
在严格 CSP 下为脚本传入应用生成的 nonce。脚本只同步 class,不替代 `BreakpointReactor` 后续监听变化。
|
||||
|
||||
## 波纹交互 {#ripple}
|
||||
|
||||
`useRipple` 返回一个 ref 回调,为交互元素加入指针反馈。元素应创建定位上下文,使生成的覆盖层使用正确边界。
|
||||
`Button` 已自动使用 `useRippleRef`,普通按钮无需重复配置。自定义交互表面可直接使用 hook:
|
||||
|
||||
```tsx
|
||||
import { useRipple } from "@workspace/ui/hooks/use-ripple"
|
||||
|
||||
export function Tile() {
|
||||
const ref = useRipple<HTMLButtonElement>({
|
||||
duration: 500,
|
||||
opacity: 0.2,
|
||||
rippleClassName: "bg-primary",
|
||||
})
|
||||
|
||||
return (
|
||||
<button ref={ref} className="relative">
|
||||
打开项目
|
||||
</button>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
元素必须建立定位上下文,通常使用 `relative`。hook 会忽略 disabled、`aria-disabled="true"` 和非主鼠标键,并在 ref 变化或卸载时移除监听器和动画节点。需要合并外部 ref 时使用 `useRippleRef(ref, options)`。
|
||||
|
||||
Reference in New Issue
Block a user