feat(layout): area 可见性派生自 item 可见性,补掉退役留下的「可见但空」回归 (#3311) - #3322
Merged
Conversation
Spec 17.0.0 retired the authorable area-level visible/requiredPermissions; following it in #3315 left a fully gated area rendering as visible-but-empty in the AreaSwitcher. Per the #3311 ruling (option C), area visibility is now DERIVED: an area appears in the switcher iff at least one of its items survives the exact item-level guards NavigationRenderer applies (visible expression, requiredPermissions, requiresObject/requiresService capability gates, and the onAction dispatcher presence for action items — framework#4509). Separators never count; groups count only through their children; an area with no items at all derives hidden the same way. The active area is elected among visible areas only, so a fully gated first area is never auto-activated, and a gating change that hides the active area re-elects the first visible one — while a change that merely reveals an area never yanks the user away. New export: hasVisibleNavigationItems from @object-ui/layout. No authorable key is involved — nothing for a metadata author to get wrong, and nothing for the spec's .strict() area object to reject. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NVPjPzmmAJ2Ngtvgg5MSRa
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
This was referenced Aug 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3311
按 #3311 裁决实施选项 C:area 可见性派生自「区域内是否存在至少一个可见 item」,不新增、不复活任何 authorable key。
背景
spec 17.0.0 退役了 area 级
visible/requiredPermissions(AREA_VISIBLE_RETIRED/AREA_REQUIRED_PERMISSIONS_RETIRED),#3315 跟随退役删掉了AreaSwitcher的过滤。契约上正确,但留下行为回归:某区域内 item 全部被 gate 掉时,以前整块区域从切换器消失,退役后渲染成「可见但空」的区域,且第一个区域全被 gate 时用户还会被默认落在空区域上。实现
hasVisibleNavigationItems(items, options)(packages/layout/src/NavigationRenderer.tsx,导出):判定一棵导航树里是否存在至少一个「真的会渲染」的 item。守卫逐条对齐NavigationItemRenderer的 item 级判定:visible表达式(evaluateVisibility)、requiredPermissions(checkPermission)、requiresObject/requiresService(checkCapability)、以及 action 项的 dispatcher 存在性(framework#4509:无onAction则不渲染,自然也不能撑起一个区域)。separator 不算内容;group 只经由子项计数,且 group 自身守卫先于递归生效。AppSchemaRenderer用该谓词过滤区域:AreaSwitcher只列出可见区域;只剩一个可见区域时不再显示切换器(与退役前visibleAreas.length <= 1的语义一致)。边界:空区域(本来就没有 item 的 area)
裁决评论定义为「派生自区域内是否存在可见 item」——空区域没有任何 item,自然没有可见 item,按与全被 gate 一致处理(隐藏),已在 issue 认领评论标注、测试
treats an area with no items at all like a fully gated one钉住。请维护者复核这一边界;若希望空区域仍显示,只需把谓词入口改为对navigation.length === 0提前返回 true,一处改动。#3315 两条 item 级断言的语义更新(需要说明)
AppSchemaRenderer.test.tsx里 #3315 落的gates the navigation ITEM by visibility/permission, not the area原断言「区域仍出现在切换器」——其场景恰是「区域内唯一 item 被 gate」,与本 PR 的派生规则语义相反(那正是要修的回归)。两条测试已改为部分被 gate 的区域(被 gate 的 item + 一个可见兄弟 item):区域保持可见且激活、可见 item 渲染、被 gate 的 item 不渲染 —— item 级 gate 断言依旧承重,「全被 gate 则区域隐藏」由新测试块覆盖。types 侧 #3315 的退役钉子(page-nav-misc-spec-parity.test.ts等)未动、全绿。验证
keeps every area in the switcher when every area has a visible itemgates the navigation ITEM …hides an area whose items are ALL gated and activates the first visible areahides an area whose items all fail their permission checkshides the switcher entirely when only one area remains visiblerenders no switcher and no area navigation when every area is fully gatedtreats an area with no items at all like a fully gated one (hidden)derives through groups …re-derives when gating changes …hasVisibleNavigationItemsdescribe 块 6 条破坏验证(改坏 → 红 → 还原 → 绿)
hasVisibleNavigationItems恒返回true(派生失效)→ 13 条断言红(7 条派生行为 + 6 条谓词单测)→ 还原后 47/47 绿。areas(退役后的旧行为)→ 6 条断言红(区域隐藏 + 重新选举各条)→ 还原后 47/47 绿。全量
pnpm exec vitest run packages/layout packages/types:32 文件 / 477 测试全绿(含 feat(deps): track @objectstack/spec 17.0.0-rc.2 and fix every break it lands (#3235, #3208, #3287, #3264) #3315 退役钉子与 parity 测试)。pnpm build:43/43;turbo run type-check lint:123/123;仓根全量vitest run:872 文件 passed(1 skipped)/ 10321 测试 passed(25 skipped)。.changeset/area-visibility-derived-from-items.md(@object-ui/layoutminor,fixed group、无 major),changeset:check通过;未触碰content/docs/releases/。Out of scope
AppSidebar/UnifiedSidebar区域切换器未采用派生可见性 —— 全被 gate 的区域仍渲染为「可见但空」 #3319:app-shell 的AppSidebar/UnifiedSidebar内联区域切换器同样未派生(从来没有过 area 过滤,非 feat(deps): track @objectstack/spec 17.0.0-rc.2 and fix every break it lands (#3235, #3208, #3287, #3264) #3315 回归)——已单独立单,建议直接采用本 PR 导出的谓词。🤖 Generated with Claude Code
https://claude.ai/code/session_01NVPjPzmmAJ2Ngtvgg5MSRa
Generated by Claude Code