图片预览文案按封面/截图语境区分

- IconPreview 增加可选 labels,缺省仍是小红书「图标」文案
- FormCard 的封面与截图预览各自传入封面/截图语义的 alt、title 与 aria
This commit is contained in:
2026-10-07 14:16:44 +08:00
parent edaf8896e1
commit cb57e59ec4
2 changed files with 42 additions and 5 deletions
@@ -252,6 +252,12 @@ export function FormCard({
<IconPreview
projectPath={projectPath}
relativePath={form.coverPath}
labels={{
alt: '封面预览',
failedTitle: '读不到这张图,用「选择封面」导入一张就能预览',
failedAria: '封面读不到',
emptyAria: '还没有选封面',
}}
/>
) : (
<span className="grid size-24 shrink-0 place-items-center overflow-hidden rounded-xl border border-dashed border-(--platform-surface-border) bg-(--platform-input-fill) text-center text-xs text-(--platform-text-soft)">
@@ -315,7 +321,16 @@ export function FormCard({
<div className="flex flex-wrap gap-2">
{form.screenshotPaths.map((path, index) => (
<div key={`${path}-${index}`} className="grid gap-1">
<IconPreview projectPath={projectPath} relativePath={path} />
<IconPreview
projectPath={projectPath}
relativePath={path}
labels={{
alt: `第 ${index + 1} 张截图预览`,
failedTitle: '读不到这张图,重新选择截图就能预览',
failedAria: `第 ${index + 1} 张截图读不到`,
emptyAria: `第 ${index + 1} 张截图`,
}}
/>
<PaneButton
variant="ghost"
ariaLabel={`移除第 ${index + 1} 张截图`}
@@ -11,7 +11,18 @@ import {
type ImagePreviewResponse = { dataUrl: string };
/**
* 图标缩略图:把项目里那张图读成 dataUrl 直接显示。
* 无障碍与占位文案;缺省是小红书「图标」语境。封面/截图等复用方按自己的语义覆盖,
* 避免读图失败时对用户说成「选择图标」。
*/
type IconPreviewLabels = {
alt?: string;
failedTitle?: string;
failedAria?: string;
emptyAria?: string;
};
/**
* 图片缩略图:把项目里那张图读成 dataUrl 直接显示。
*
* 走 UI Editor 同一套 `read_local_project_image_preview`——越界、符号链接、敏感路径的门禁在宿主
* 那边,而且宿主只允许预览「已登记资源」。用户手填一条没登记过的路径时这里读不到,退回占位符并
@@ -20,9 +31,11 @@ type ImagePreviewResponse = { dataUrl: string };
export function IconPreview({
projectPath,
relativePath,
labels,
}: {
projectPath: string | null;
relativePath: string;
labels?: IconPreviewLabels;
}) {
const [dataUrl, setDataUrl] = useState<string | null>(null);
const [failed, setFailed] = useState(false);
@@ -71,15 +84,24 @@ export function IconPreview({
<span
className="grid size-24 shrink-0 place-items-center overflow-hidden rounded-xl border border-(--platform-surface-border) bg-(--platform-input-fill)"
title={
failed ? '读不到这张图,用「选择图标」导入一张就能预览' : undefined
failed
? (labels?.failedTitle ??
'读不到这张图,用「选择图标」导入一张就能预览')
: undefined
}
role={dataUrl ? undefined : 'img'}
aria-label={dataUrl ? undefined : failed ? '图标读不到' : '还没有选图标'}
aria-label={
dataUrl
? undefined
: failed
? (labels?.failedAria ?? '图标读不到')
: (labels?.emptyAria ?? '还没有选图标')
}
>
{dataUrl ? (
<img
src={dataUrl}
alt="图标预览"
alt={labels?.alt ?? '图标预览'}
className="size-full object-contain"
/>
) : (