docs(ui): explain shared controls and canvas display adapters

This commit is contained in:
2026-11-12 01:51:59 +08:00
parent 1306df2b35
commit b51d78b47d
11 changed files with 115 additions and 0 deletions
+9
View File
@@ -1,3 +1,7 @@
/**
* 画布等工具栏使用的图标按钮。统一按钮尺寸、图标与可访问名称,并按反馈Provider决定使用浮层提示还是原生title。
* 按钮的业务动作由onClick等原生属性传入;这里不维护工具选择状态。
*/
"use client";
import { FeedbackContext } from "./app-feedback";
@@ -6,13 +10,17 @@ import { useContext, forwardRef, type ButtonHTMLAttributes } from "react";
import type { LucideIcon } from "lucide-react";
import styles from "./icon-button.module.css";
/** icon提供Lucide图标实现,label提供默认可访问名称与提示;不接受任意children替换内部图标。 */
export type IconButtonProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children"> & {
icon: LucideIcon;
label: string;
};
/** 将ref交给真实button;type默认为button,避免放进表单时意外提交。
* 调用方仍可传aria-pressed、disabled等状态,组件不会自行判断命令是否可用。 */
export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
function IconButton({ icon: Icon, label, title = label, className = "", type = "button", ...props }, ref) {
// Provider存在时由Radix显示提示,移除原生title以免出现两层提示;图标自身对读屏隐藏。
const feedback = useContext(FeedbackContext);
const button = (
<button
@@ -26,6 +34,7 @@ export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
<Icon size={16} strokeWidth={1.6} aria-hidden="true" />
</button>
);
// 没有全局提示环境就返回原生按钮;空title也不创建Tooltip。提示通过Portal避免被工具栏裁切。
if (!feedback || !title) return button;
return <Tooltip.Root><Tooltip.Trigger asChild>{button}</Tooltip.Trigger><Tooltip.Portal>
<Tooltip.Content className={styles.tooltip} sideOffset={7} collisionPadding={8}>