Skip to content

Commit b2a4ab1

Browse files
committed
docs(qa): shell-nav-personalization judges the pinned order, and the authored menu as not reorderable
The runtime sidebar's menu is no longer user-reorderable; personal ordering lives only in the Pinned section (objectui 8a55f0ccda). The item's drag-reorder step and clause, which judged the retired useNavOrder localStorage order, are replaced by a desktop-only pinned-order clause (drag the row or Space/arrows/Space; persists with the nav favorites) and a negative clause on the authored menu (no grip, no sortable role, no grab cursor; authored order whatever objectui-nav-order key is stored). Revision 2, with its history entry. Claude-Session: https://claude.ai/code/session_01LYXc6ckoWuZyVZpWYizdMh Co-authored-by: Claude <noreply@anthropic.com>
1 parent 4e9fe9f commit b2a4ab1

1 file changed

Lines changed: 30 additions & 14 deletions

File tree

‎docs/qa/platform-checklist/areas/platform-core.json‎

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -962,27 +962,29 @@
962962
},
963963
{
964964
"id": "platform-core.shell-nav-personalization",
965-
"title": "Shell nav personalization: sidebar collapse, pin/reorder, favorites, recents and header breadcrumbs each persist and stay navigable across reload",
965+
"title": "Shell nav personalization: sidebar collapse, pins and the user's pinned order, favorites, recents and header breadcrumbs each persist and stay navigable across reload; the authored menu keeps the app's order",
966966
"since": "v16",
967967
"status": "active",
968-
"revision": 1,
968+
"revision": 2,
969969
"priority": "P2",
970970
"surface": "browser",
971971
"personas": ["seeded admin (admin@objectos.ai / admin123)"],
972972
"fixtures": {
973973
"app": "showcase",
974974
"requires": [
975-
"stock showcase nav (multiple objects/dashboards/reports so there is something to pin, reorder, favorite, and visit as recents)"
975+
"stock showcase nav (multiple objects/dashboards/reports so there is something to pin — at least three entries, so the pinned order can change — favorite, and visit as recents)",
976+
"a desktop viewport, at least 768px wide, for the Pinned section: below it useIsMobile is true and UnifiedSidebar passes enablePinning={!isMobile}, so a phone draws no Pinned section and has no pinned order to judge"
976977
]
977978
},
978979
"steps": [
979980
"sidebar collapse: toggle the sidebar to icon (collapsed) mode; confirm nav items still NAVIGATE in icon mode; reload — the collapsed state persists (cookie sidebar_state, packages/components/src/ui/sidebar.tsx SIDEBAR_COOKIE_NAME)",
980981
"nav pin/unpin: pin a nav item (UnifiedSidebar → useNavPins.togglePin → favorite id nav:<navId>, backed by FavoritesProvider/UserDataAdapter); it appears in the Pinned section; reload — the pin persists (syncs via UserDataAdapter; migrates the legacy objectui-nav-pins key); unpin removes it",
981-
"drag-reorder: reorder nav items by drag (UnifiedSidebar useNavOrder, enableReorder / onReorder=handleReorder); reload — the order persists (localStorage per-app key)",
982+
"pinned order (desktop only): with at least three entries pinned, reorder them inside the Pinned section — the group NavigationRenderer draws above the menu, headed console.nav.favorites ('Favorites' in en, 「收藏」 in zh, a star icon), not the content-favorites group UnifiedSidebar draws below Recent. By pointer: drag a pinned row by the row itself (no grip at rest; the row's link carries cursor-grab; a press becomes a drag only after 5px of travel; a 2px insertion line, data-drop-indicator, marks where it lands). By keyboard: focus a pinned row's link, Space picks it up, the arrow keys move it, Space drops it, Escape cancels; Enter is not a drag key, it follows the link. Reload — the pinned order persists: NavigationRenderer onPinnedReorder → useNavPins.reorderPins → FavoritesProvider reorderNavPins stores it as the order of the type 'nav' favorites (nav:<navId>) in the UserDataAdapter-backed favorites list. A new pin joins the end; an unpin leaves the others in order",
982983
"favorites star/unstar: star an object/record as a favorite (useFavorites / FavoritesProvider); it appears in favorites; reload — persists; unstar removes it",
983984
"recents rail: visit several records/objects/dashboards; the sidebar Recent section (collapsed by default, top 5 — useTrackRouteAsRecent → RecentItemsProvider, localStorage objectui-recent-items scoped by userId, hydrates UserDataAdapter) lists them; reload — recents survive",
984985
"header record-trail breadcrumbs: on a record detail the AppHeader breadcrumb shows the app/section/record trail; click a crumb to navigate back to its level; reload — the trail rebuilds from the route",
985-
"record which persistence each feature uses: pins/favorites/recents are UserDataAdapter-backed (cross-device sync), reorder + collapse are local (localStorage / cookie)"
986+
"authored menu (any viewport): the app's own menu — every row outside the Pinned section — offers no reorder: no drag grip, no aria-roledescription=\"sortable\", no aria-describedby=\"nav-pinned\" (the pinned list's DndContext id, which names dnd-kit's drag instructions) and no cursor-grab on its links, and dragging a menu row moves nothing (a browser's native link-drag ghost is not a reorder). Its order is the app's authored navigation order: each level sorted by order, lower first, ties in authored array order (objectui packages/layout/src/navOrder.ts byNavOrder). Then plant the retired per-user key — localStorage objectui-nav-order-<app name> holding a JSON map of __root__ and each group id to that level's ids reversed, the shape the retired useNavOrder read — and reload: the menu order does not change, because UnifiedSidebar no longer reads the key",
987+
"record which persistence each feature uses: pins and their order, favorites and recents are UserDataAdapter-backed (cross-device sync; pins, their order and favorites are one sys_user_preference row, key ui.favorites), collapse is local (cookie sidebar_state)"
986988
],
987989
"acceptance": [
988990
{
@@ -998,10 +1000,10 @@
9981000
"evidence": "pre/post-reload DOM"
9991001
},
10001002
{
1001-
"clause": "drag-reorder persists: the reordered nav order is restored after reload (useNavOrder localStorage)",
1003+
"clause": "pinned order (desktop): a pinned entry is reordered by dragging its row and by keyboard (Space, arrows, Space), and the Pinned section's order is restored after reload (the order of the nav:<navId> favorites — useNavPins.reorderPins → FavoritesProvider reorderNavPins, UserDataAdapter-backed)",
10021004
"oracle": "dom",
1003-
"verify": "the nav item order before reload equals the order after reload",
1004-
"evidence": "order before/after reload"
1005+
"verify": "after a screenshot confirms render, at a viewport at least 768px wide: read the Pinned section's link order; move one row by a pointer drag on the row itself (with intermediate pointer moves — a press must travel 5px before it is a drag) and another by keyboard (focus its link, Space, ArrowUp/ArrowDown, Space) — each drop leaves the section in the dropped order; pick a row up and press Escape — the order is unchanged; reload — the order read after reload equals the order read before it. Control that the probe sees a sortable row: each pinned link carries aria-describedby=\"nav-pinned\" and cursor-grab, and no grip element is drawn",
1006+
"evidence": "the Pinned section's order before the drags, after each drop, after the Escape, and after reload"
10051007
},
10061008
{
10071009
"clause": "favorites star/unstar persists across reload",
@@ -1020,25 +1022,39 @@
10201022
"oracle": "screenshot",
10211023
"verify": "breadcrumb screenshot + a crumb navigation that routes back + the trail present after reload",
10221024
"evidence": "breadcrumb screenshot + the crumb navigation"
1025+
},
1026+
{
1027+
"clause": "the authored menu is not user-reorderable (any viewport): no row outside the Pinned section draws a drag grip or carries aria-roledescription=\"sortable\", aria-describedby=\"nav-pinned\" or cursor-grab, and the menu renders in the app's authored order even with a stored objectui-nav-order-<app name> key",
1028+
"oracle": "dom",
1029+
"verify": "after a screenshot confirms render: the sidebar holds zero [aria-roledescription=\"sortable\"] elements; every menu link outside the Pinned section has no aria-describedby=\"nav-pinned\" and no cursor-grab class (control, on desktop with a pin: the Pinned section's links DO carry both, so the probe can see them); the rendered order of each menu level equals the app's authored navigation order (by order, ties in array order); plant objectui-nav-order-<app name> with every level reversed, reload, and read the menu order again — unchanged. Repeat the attribute probe at a phone viewport (under 768px) with the mobile sidebar open",
1030+
"evidence": "the attribute-probe counts with the pinned-row control; authored vs rendered menu order, before and after planting the stored key"
10231031
}
10241032
],
10251033
"negative": [
10261034
"a collapsed sidebar whose icon items no longer navigate (dead icon mode) is a FAIL",
1027-
"a pin / favorite / reorder / recent that does NOT survive reload is a FAIL of its persistence contract",
1035+
"a pin, the pinned order, a favorite or a recent that does NOT survive reload is a FAIL of its persistence contract",
1036+
"on the authored menu (every row outside the Pinned section, any viewport) a drag grip, an aria-roledescription=\"sortable\" element, dnd-kit's drag-instructions aria-describedby, a grab cursor, a drag that moves a row, or an order other than the app's authored order (with or without a stored objectui-nav-order-<app name> key) is a FAIL: arranging the menu is Studio's work, not the end user's",
1037+
"a phone viewport (under 768px) draws no Pinned section (UnifiedSidebar enablePinning={!isMobile}): its absence there is expected, not a FAIL of the pinned order",
10281038
"a breadcrumb crumb that is inert (does not navigate) is a FAIL",
10291039
"transitional emptiness right after navigation (empty nav/recents) must be ruled out by the screenshot-first protocol before any persistence FAIL is recorded"
10301040
],
1031-
"traps": ["hydration-race", "shared-browser-tab"],
1041+
"traps": ["hydration-race", "shared-browser-tab", "stale-console-bundle", "automation-input"],
10321042
"source": [
1033-
"objectui packages/app-shell/src/layout/UnifiedSidebar.tsx (useNavOrder drag-reorder localStorage; Recent section; applyPins)",
1034-
"objectui packages/app-shell/src/hooks/useNavPins.ts (togglePin → nav:<navId> favorite, MAX_PINS 20, UserDataAdapter-backed, legacy objectui-nav-pins migration)",
1035-
"objectui packages/app-shell/src/hooks/useFavorites.ts + context/FavoritesProvider.tsx (favorites state)",
1043+
"objectui packages/app-shell/src/layout/UnifiedSidebar.tsx (no menu reorder: useNavOrder is gone and a stored objectui-nav-order-<app> key is not read; the app arm passes NavigationRenderer enablePinning={!isMobile}, pinnedOrder={pinnedIds}, onPinnedReorder={reorderPins}; Recent section; applyPins)",
1044+
"objectui packages/layout/src/NavigationRenderer.tsx (enableReorder / onReorder RETIRED; the Pinned section, headed console.nav.favorites, is PinnedNavigationList: its own DndContext id nav-pinned, PointerSensor after 5px, KeyboardSensor start and end Space and cancel Escape, the row's link as the drag activator with cursor-grab and aria-describedby, DropIndicator data-drop-indicator; orderPinnedItems by pinnedOrder; menu levels sorted by byNavOrder only)",
1045+
"objectui packages/layout/src/navOrder.ts (byNavOrder — the authored order: order ascending, ties in array order)",
1046+
"objectui packages/app-shell/src/hooks/useNavPins.ts (togglePin → nav:<navId> favorite, MAX_PINS 20, UserDataAdapter-backed, legacy objectui-nav-pins migration; pinnedIds in the user's order; reorderPins)",
1047+
"objectui packages/app-shell/src/hooks/useFavorites.ts + context/FavoritesProvider.tsx (favorites state; reorderNavPins and withNavPinOrder — the pinned order is the order of the type 'nav' favorites; withAddedFavorite appends a new nav pin)",
1048+
"objectui packages/components/src/hooks/use-mobile.tsx (useIsMobile, MOBILE_BREAKPOINT 768 — the phone/desktop line for the Pinned section)",
1049+
"objectui packages/app-shell/src/console/ConsoleShell.tsx (createObjectStackUserStateAdapter key ui.favorites — the favorites list, nav pins and their order included, is one per-user row)",
1050+
"packages/platform-objects/src/identity/sys-user-preference.object.ts#sys_user_preference (the per-user row that favorites list is stored in)",
10361051
"objectui packages/app-shell/src/context/RecentItemsProvider.tsx + hooks/useTrackRouteAsRecent.ts (recents — objectui-recent-items localStorage + UserDataAdapter hydrate)",
10371052
"objectui packages/app-shell/src/layout/AppHeader.tsx (breadcrumb record-trail)",
10381053
"objectui packages/components/src/ui/sidebar.tsx (SIDEBAR_COOKIE_NAME sidebar_state — collapse persistence)"
10391054
],
10401055
"history": [
1041-
{ "revision": 1, "date": "2026-08-08", "change": "initial — sidebar collapse/icon-mode, nav pin+reorder, favorites, recents rail, header breadcrumbs, each with its real persistence layer (cookie/localStorage/UserDataAdapter)", "ref": "claude/platform-test-checklist-ocwugl" }
1056+
{ "revision": 1, "date": "2026-08-08", "change": "initial — sidebar collapse/icon-mode, nav pin+reorder, favorites, recents rail, header breadcrumbs, each with its real persistence layer (cookie/localStorage/UserDataAdapter)", "ref": "claude/platform-test-checklist-ocwugl" },
1057+
{ "revision": 2, "date": "2026-10-09", "change": "end users no longer reorder the runtime sidebar's menu. Maintainer ruling (#22487): 「右侧浏览器,左侧菜单在用户界面不应该显示拖动按钮,拖动设计是studio的工作。」 Scope note: personal ordering survives only in the Pinned section. Landed in objectui 8a55f0ccda (objectui PR #12066, objectui#12059), and every new text cites that code. Step 3 and acceptance[2], which drag-reordered the menu (useNavOrder, localStorage objectui-nav-order-<app>), are REPLACED, not only removed: they now judge the Pinned section's order (desktop only, since a phone draws no Pinned section), dragged by the row or reordered by keyboard (Space, arrows, Space), and persisting across reload as the order of the nav favorites in the UserDataAdapter-backed favorites list. A new step and acceptance[6] judge the negative: no grip, sortable role, drag instructions or grab cursor on the authored menu, and the authored order whatever objectui-nav-order key is stored. Title, fixtures.requires, the persistence step (now 'collapse is local'), the reload negative and source are re-pointed to the landed code. Traps gain stale-console-bundle (the console pin f0268ad784 predates 8a55f0ccda, so a console built at it still draws the menu grip) and automation-input (a one-jump synthetic pointer move never crosses dnd-kit's 5px activation distance and reads as a dead drag)", "ref": "#22487" }
10421058
]
10431059
},
10441060
{

0 commit comments

Comments
 (0)