发现于 #3987 的实施(PR #3995),不在该 PR 处理 —— 那单的边界是 navigation-renderer 的 items 声明面 + 测试,这里是另一个组件、另一个文件(README),未认领,交 PM triage。
机制
packages/layout/README.md 的 ### SidebarNav 段落(约 :76-90)给的示例:
const navItems = [
{ label: 'Dashboard', path: '/dashboard', icon: 'home' },
{ label: 'Users', path: '/users', icon: 'users' },
{ label: 'Settings', path: '/settings', icon: 'settings' }
];
而 packages/layout/src/SidebarNav.tsx:23-30 的 NavItem 是:
title: string;
href: string;
icon?: React.ComponentType< { className?: string } >;
badge?: string | number;
badgeVariant?: ...;
children?: NavItem[];
三个键全错,不是一个笔误:
label → 真实键是 title;
path → 真实键是 href;
icon: 'home' → 类型错。icon 是组件而不是图标名,渲染点是 item.icon && < item.icon / >(:60、:110)。
后果(不是"文档不全")
按示例写出来的对象既没有 items 也没有 href,isNavGroup(:45,判据 'items' in item && !('href' in item))因此返回 false,走 NavItem 分支:
< span >{item.title}< /span >(:110-111)拿到 undefined —— 每一行没有标签;
< NavLink to={item.href} >(:109)拿到 undefined —— react-router 的 to 必填,实际表现待复现(warning / 抛错);
item.icon 是字符串 'home',< item.icon / > 会被 React 当作未知小写标签渲染,而不是图标。
在 TS 消费者里这段会直接类型报错(label 不在 NavItem 上),所以最直接的受害者是 JS 消费者、以及照抄后自己"改到能编译"的作者(含 AI 作者) —— 而 README 是这个包在 npm 上的门面页。这与 #3972 / #3987 是同一族缺陷(声明面/文档面教了组件消费不了的形状),只是载体从 inputs 换成了 README。
可达性诚实标注
修法(未做决定,PM 定)
最小修法是把示例改成 title / href,并给 icon 用真实的组件写法(如 lucide 的 Home),或在示例里干脆省掉 icon。要不要顺带给 SidebarNav 补一段 props 表、以及要不要为 README 的代码块上门禁(#3786 家族的"文档与代码同源"问题),都超出这条 finding 的判断范围。
参考位置:
packages/layout/README.md:76-90 —— 出错的示例
packages/layout/src/SidebarNav.tsx:23-30 —— NavItem 真实形状
packages/layout/src/SidebarNav.tsx:45 / :60 / :109-111 —— isNavGroup 与两个渲染点
关联:#3987 / #3972(同族,声明面/文档面教错形状)、#3786(文档与实现漂移)。
发现于 #3987 的实施(PR #3995),不在该 PR 处理 —— 那单的边界是
navigation-renderer的items声明面 + 测试,这里是另一个组件、另一个文件(README),未认领,交 PM triage。机制
packages/layout/README.md的### SidebarNav段落(约 :76-90)给的示例:而
packages/layout/src/SidebarNav.tsx:23-30的NavItem是:三个键全错,不是一个笔误:
label→ 真实键是title;path→ 真实键是href;icon: 'home'→ 类型错。icon是组件而不是图标名,渲染点是item.icon && < item.icon / >(:60、:110)。后果(不是"文档不全")
按示例写出来的对象既没有
items也没有href,isNavGroup(:45,判据'items' in item && !('href' in item))因此返回 false,走NavItem分支:< span >{item.title}< /span >(:110-111)拿到undefined—— 每一行没有标签;< NavLink to={item.href} >(:109)拿到undefined—— react-router 的to必填,实际表现待复现(warning / 抛错);item.icon是字符串'home',< item.icon / >会被 React 当作未知小写标签渲染,而不是图标。在 TS 消费者里这段会直接类型报错(
label不在NavItem上),所以最直接的受害者是 JS 消费者、以及照抄后自己"改到能编译"的作者(含 AI 作者) —— 而 README 是这个包在 npm 上的门面页。这与 #3972 / #3987 是同一族缺陷(声明面/文档面教了组件消费不了的形状),只是载体从inputs换成了 README。可达性诚实标注
SidebarNav没有注册到ComponentRegistry(packages/layout/src/index.ts只import了它却没register,eslint 因此报'SidebarNav' is defined but never used—— 该 warning 在main上已存在);它只是被export * from './SidebarNav'导出的 React 组件。所以这条只影响 React 直调侧,与 schema/manifest 那条链无关。SidebarNav(仓内调用点都用title/href),所以是仓外消费者受影响 —— 与 packages/layout: registerLayout 的 inputs 声明面与组件实现不符 —— page-header 漏 icon(文档 demo 今天就吃假 unknown-prop),navigation-renderer 的 items 声明成 object 而 prop 是数组 #3972 现象二同级的可达性标注。packages/layout/src/__tests__/side-effects-manifest.test.ts:289的注释写着 "the SidebarNav component reaches the registry undernavigation-renderer" —— 但注册的是NavigationRenderer,SidebarNav是另一个文件里的另一个组件。若该说法确实不成立,那是同一段文档链上的第二处失真,但是不是只是措辞松散,我没有判定。修法(未做决定,PM 定)
最小修法是把示例改成
title/href,并给icon用真实的组件写法(如 lucide 的Home),或在示例里干脆省掉icon。要不要顺带给SidebarNav补一段 props 表、以及要不要为 README 的代码块上门禁(#3786 家族的"文档与代码同源"问题),都超出这条 finding 的判断范围。参考位置:
packages/layout/README.md:76-90—— 出错的示例packages/layout/src/SidebarNav.tsx:23-30——NavItem真实形状packages/layout/src/SidebarNav.tsx:45/:60/:109-111——isNavGroup与两个渲染点关联:#3987 / #3972(同族,声明面/文档面教错形状)、#3786(文档与实现漂移)。