Skip to content

Commit 08ed7e2

Browse files
refactor(app-shell): move ObjectView's view tab strip, plugin schema and header chrome into sibling hooks (slice 9) (#26412)
<!-- claude-projects-attribution: {"github_login":"os-steve"} --> _Requested by **Steve** · [project thread](https://claude.ai/code/project/chan_01FdL1XeUyvVNxLreh3F4Qi9?thread=cmsg_01FdL1XeUyvVNxLreh3F4Qi9VtKf3F9dzJPJM4RRtABaEc)_ Part of #25992 (slice 9 of the move-only split; slices 1 to 8 landed as #26152, #26233, #26310, #26336, #26353, #26374 and #26396, and the card stays open for the slices listed below). Clause-②: no Metadata-protocol: none ## What moved Base `e4434f75` (slice 8 merged, latest `main` merged in). `ui/packages/app-shell/src/views/ObjectView.tsx` is 2554 lines there. Three concerns of `ObjectViewInner` move verbatim into custom hooks in three new sibling modules. In each, every input is passed as an argument, typed from its source (no `any`), the component destructures the returned values under their original names, no identifier is renamed and no context is added. ### N: the view tab strip → `objectViewTabBar.tsx` Lines 1131–1206 move into `useObjectViewTabBar({ views, savedViews, objectDef, servedViews, viewLabel, unlabelledViewText, language, t, viewAccess, activeViewId, handleViewChange, isAdmin, handleAddView, handleRenameView, handleDeleteView, handlePinView, handleSetDefaultView, handleConfigView, setManageViewsOpen })`. That covers the View Tabs docblock, `useViewTabsFit()`, `useDisplayLocale()`, `viewTabItems`, the `<ViewTabBar>` node (`viewTabBar`, objectui#12440) and its own-row face `viewTabRow` (objectui#13114). It returns `viewTabItems`, `viewTabBar` and `viewTabRow`. The view handlers it wires are typed from the `ViewTabBarProps` callbacks they are handed to. ### P (plugin schema): the merged views and `ObjectViewSchema` → `objectViewPluginSchema.ts` Lines 1975–2034 move into `useObjectViewPluginSchema({ views, activeViewId, viewDraft, activeView, objectDef, onEdit, isAdmin, location, navigate, viewId, servedViews, viewLabel, unlabelledViewText, language })`: `mergedViews`, the active view's `userActions` toolbar policy (objectui#11013) and `objectViewSchema`. It returns `mergedViews` and `objectViewSchema`. `viewDraft` is declared in the component as `useState<Record<string, any> | null>`, so it is typed as `Partial<ReturnType<typeof buildViewTabs>[number]> | null`: a partial of the tab it is merged over, which is the only way the block reads it. ### P (header chrome): the create button, folded header actions and refused-view face → `objectViewHeaderChrome.tsx` Lines 2036–2146 move into `useObjectViewHeaderChrome({ objectCanCreate, createVisible, createDisabled, actions, t, listActions, toolbarActionsWithDeepLink, identityImportEnabled, objectCanImport, importVisible, importDisabled, setShowImport, listFavorite, activeViewHasPreference, handleResetView, isEnvironmentList, toolbarBar, viewAccess })`: `showCreate`, `listFabClearance`, `createButton`, `toolbarRowActions`, `primaryToolbarAction`, `importShown`, `foldedMenuBar`, `foldedHeaderActions` (objectui#12705) and `refusedViewFace` (objectui#12112). It returns `showCreate`, `listFabClearance`, `createButton`, `importShown`, `foldedHeaderActions` and `refusedViewFace`. The block calls no React hook; it keeps the `use` name so it reads like its siblings and stays at the top level of the component. Each hook is called where its block stood, so the order of React hooks in the component is unchanged. ### Imports Each import moves with its only readers. `ViewTabBar`, `ViewTabItem`, `useViewTabsFit`, `useDisplayLocale` and `pickLocalized` go to the tab bar module. `Empty`, `EmptyTitle`, `EmptyDescription`, `Lock`, `ActionBarSchema`, `UIActionSchema` and `MOBILE_FAB_LIST_CLEARANCE` go to the header chrome module. `declaredPrimaryToolbarAction` also goes there; it is still re-exported from `ObjectView.tsx`, line unchanged. Imports still read elsewhere in the component (`viewTabLabel`, `viewRowId`, `VIEW_TYPE_ICONS`, `normalizeListViewSchema`, `Button`, `Plus`, `SchemaRenderer`) are imported by the modules as well. Nothing new is exported from `ObjectView.tsx`, and the package entry is untouched. `ObjectView.tsx` goes from 2554 to 2374 lines. Move-only proof: the multiset of non-blank lines of the base `ObjectView.tsx` is contained in new `ObjectView.tsx` plus the three modules. The only base lines missing are 11 import lines or import-list entries that lost a moved name: the `@object-ui/plugin-view` value and type imports, `Empty` / `EmptyTitle` / `EmptyDescription` in the `@object-ui/components` list, the `lucide-react`, `@object-ui/types`, `@object-ui/i18n` and `./objectViewChrome.js` imports, and the `declaredPrimaryToolbarAction` and `MOBILE_FAB_LIST_CLEARANCE` entries. The trimmed lines replace them. The added lines are the trimmed imports and the three new imports, the module headers and imports, the hook signatures and parameter types, the `return` objects, and in `ObjectView.tsx` the three calls with their destructuring and two-line comments. ## Test edits None. No source reader of `ObjectView.tsx` names a moved line: the readers that mention `ViewTabBar`, `userActions` or `normalizeListViewSchema` read `plugin-view/src/ObjectView.tsx`, mock the module, or anchor on `fullSchema` inside `renderListView`, which stays. ## Seam table rows this PR changes (measured on `e4434f75`) The full table (regions A to Q) is in #26336. | # | Concern | Lines on `e4434f75` | Reads | Read by | Slice | |---|---|---|---|---|---| | N | View tab items, `ViewTabBar`, its own-row face | 1131–1206 | A, C, F (`savedViews`, `views`, `activeViewId`, `viewAccess`), I (view handlers) | O, Q | **9, this PR** | | P (schema) | Merged views, `userActions` toolbar policy, `ObjectViewSchema` | 1975–2034 | A, B (`viewDraft`), C, F | Q | **9, this PR** | | P (header chrome) | Create button, folded header actions, refused-view face | 2036–2146 | A, C (`listFavorite`), D, E, F (`viewAccess`), G, H, J (`actions`) | Q | **9, this PR** | ## Remaining slices (the last closes the card) - **Slice 10 — Q:** the JSX return's `PageHeader`, import wizard and `NavigationOverlay` blocks into sub-components with explicit props. - **Slice 11 — B + I + O + G-columns (closes the card):** the view-config and view-tab CRUD handlers, `renderListView` and the column flags only it reads. The `writeRefusalCensus-11583` rows, the `relayRungCensus-7559` read and the `check-i18n-call-site-keys.test.ts` `deleteViewConfirm` row are re-pointed (path and file-key changes only). ## Verification See the os-dev-report comment on the card for the full readings: app-shell `type-check` after rebuilding its dependency closure, every `ObjectView.*` test in `views/` (the view tab, header fold, mobile FAB, refused view and favorites tests among them), the `AppContent*` tests, every other test that reads `ObjectView.tsx` as source, eslint on the 4 touched files, the derived dispatch gates, and a Console build. ## Acceptance notes - eslint: 0 errors, no new warning. The four files report 113 warnings against 116 for the base `ObjectView.tsx` alone: three `react-hooks/preserve-manual-memoization` warnings are no longer raised, and the two `exhaustive-deps` warnings on `handleViewChange` only moved lines. Changeset: `.changeset/25992-objectview-tab-bar-header-chrome-split.md` (patch, `@object-ui/app-shell`). --- 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01QciHBvFJXnhZqXmdqpDtpz --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 411fc00 commit 08ed7e2

5 files changed

Lines changed: 518 additions & 257 deletions

File tree

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
'@object-ui/app-shell': patch
3+
---
4+
5+
refactor(app-shell): the Console `ObjectView`'s view tab strip, plugin schema and header chrome move into sibling hooks
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
Three concerns move verbatim out of `ObjectViewInner` in `views/ObjectView.tsx`. The view tab items, the `ViewTabBar` handed to the list toolbar and its own-row face move into `useObjectViewTabBar` in `objectViewTabBar.tsx`. The views with the open draft merged in and the `ObjectViewSchema` handed to the plugin `ObjectView` move into `useObjectViewPluginSchema` in `objectViewPluginSchema.ts`. The header's create button, its folded actions menu and the list area for a refused view move into `useObjectViewHeaderChrome` in `objectViewHeaderChrome.tsx`. The component passes every input in and reads the returned values. No logic, name or rendered output changes, and the package entry is unchanged.
11+
12+
What to do: nothing.

0 commit comments

Comments
 (0)