diff --git a/src/features/catalogue/CatalogueBrowser.tsx b/src/features/catalogue/CatalogueBrowser.tsx index 00012d3..2b9ea37 100644 --- a/src/features/catalogue/CatalogueBrowser.tsx +++ b/src/features/catalogue/CatalogueBrowser.tsx @@ -1,4 +1,5 @@ import { useEffect, useMemo, useState, type ReactNode } from 'react'; +import { createPortal } from 'react-dom'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { Button } from '@astryxdesign/core/Button'; import { Switch } from '@astryxdesign/core/Switch'; @@ -60,6 +61,8 @@ export interface CatalogueBrowserProps { isReadOnly?: boolean; /** Why importing is unavailable, if it is. */ blockedReason?: string; + /** Whether to pull the search and filter controls up into the tab row. */ + alignWithTabs?: boolean; } /** @@ -87,6 +90,7 @@ export function CatalogueBrowser({ scope, blockedReason, isReadOnly, + alignWithTabs, }: CatalogueBrowserProps) { const client = useQueryClient(); @@ -132,6 +136,13 @@ export function CatalogueBrowser({ */ const [isFiltersOpen, setIsFiltersOpen] = useState(true); + const [portalTarget, setPortalTarget] = useState(null); + useEffect(() => { + if (alignWithTabs) { + setPortalTarget(document.getElementById('inventory-header-actions')); + } + }, [alignWithTabs]); + /** * 400ms, and it costs more than it looks to get wrong. * @@ -461,33 +472,56 @@ export function CatalogueBrowser({ of the row, matching where search sits on Sales, Reports and Products, rather than above the brand rail where they read as the rail's own controls instead of the whole catalogue's. */} - -
- } - variant={isFiltersOpen ? 'secondary' : 'ghost'} - size="sm" - onClick={() => setIsFiltersOpen((open) => !open)} - /> -
- -
-
+ {(() => { + const controls = ( + <> +
+ } + variant={isFiltersOpen ? 'secondary' : 'ghost'} + size="sm" + onClick={() => setIsFiltersOpen((open) => !open)} + /> +
+ +
+
- {activeFilters.map((filter) => ( - - ))} - {activeFilters.length > 1 ? ( -