Skip to content

Commit 1df3727

Browse files
authored
Mobile follow-ups to Stirling-Tools#7518: tool-list search, and drop the empty overflow menu (Stirling-Tools#7660)
# Description of Changes Follow-up to Stirling-Tools#7518, picking up two mobile rough edges found while going over that branch. Two changes, one commit each. ## 1. Tool search back in the tool list (mobile) Tool search lives in the workbench bar's super search, which on mobile sits on the Workspace slide. So searching for a tool meant swiping off the tool list, typing, then swiping back. This puts a filter at the head of the tool panel on mobile. Reuses the existing `ToolSearch` component in `mode="filter"`, the same one the desktop fullscreen picker uses. Drives `setSearchQuery` on `ToolWorkflowContext`, so the query, filtering and grouped results are all existing paths. `ToolPanel` takes a new `showSearch` prop; `RightSidebar` passes `showSearch={isMobile}`. Desktop renders exactly as before. **To test:** - Open the editor at a phone-width viewport (under 1024px). - A "Search tools..." field should sit above Favourites / Recommended in the Tools pane. - Typing filters into grouped results. Clearing goes back to the compact list. - It hides once a tool is open, and comes back on the way out. - On desktop the field should not appear at all. ## 2. The mobile overflow menu opened with nothing in it `WorkbenchBarMobileActions` rendered its kebab trigger unconditionally. But every item inside is gated on `currentView === "viewer"` or `!isCustomView`. In a `custom:*` workbench both are false, so the dropdown was empty. `WorkbenchBarDesktopActions` renders nothing in that case, so this only showed on phones. Now returns `null` when neither group applies, with the two conditions named so the trigger and the items can't drift apart again. **To test:** - Phone-width viewport, load a PDF. - Open a tool with its own workbench view: Compare, Get Info report, Show JS, Validate Signature, Edit Table of Contents, or PDF Text Editor. - The kebab at the right of the workbench bar should be gone entirely, rather than opening an empty menu. - Back in the viewer or page editor it should still be there, with Print / Download / Save As / Close.
1 parent 5f0fe06 commit 1df3727

4 files changed

Lines changed: 53 additions & 6 deletions

File tree

frontend/editor/src/core/components/shared/workbenchBar/WorkbenchBarMobileActions.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ export default function WorkbenchBarMobileActions({
2525
}: WorkbenchBarActionsProps) {
2626
const { t } = useTranslation();
2727
const exportDisabled = actionsDisabled || policyEnforcing;
28+
const showPrint = currentView === "viewer";
29+
const showFileActions = !isCustomView;
30+
31+
// Custom workbench views own their content, so none of these apply. The
32+
// desktop cluster renders nothing at all in that case; without this the
33+
// trigger would still be there, opening an empty dropdown.
34+
if (!showPrint && !showFileActions) return null;
2835

2936
return (
3037
<Menu shadow="md" width={230} position="bottom-end">
@@ -39,7 +46,7 @@ export default function WorkbenchBarMobileActions({
3946
</ActionIcon>
4047
</Menu.Target>
4148
<Menu.Dropdown>
42-
{currentView === "viewer" && (
49+
{showPrint && (
4350
<Menu.Item
4451
leftSection={<PrintIcon sx={{ fontSize: "1.1rem" }} />}
4552
disabled={exportDisabled}
@@ -48,7 +55,7 @@ export default function WorkbenchBarMobileActions({
4855
{t("workbenchBar.print", "Print PDF")}
4956
</Menu.Item>
5057
)}
51-
{!isCustomView && (
58+
{showFileActions && (
5259
<Menu.Item
5360
leftSection={
5461
<LocalIcon
@@ -63,7 +70,7 @@ export default function WorkbenchBarMobileActions({
6370
{downloadLabel}
6471
</Menu.Item>
6572
)}
66-
{!isCustomView && saveAsIconName && (
73+
{showFileActions && saveAsIconName && (
6774
<Menu.Item
6875
leftSection={
6976
<LocalIcon icon={saveAsIconName} width="1.1rem" height="1.1rem" />
@@ -74,7 +81,7 @@ export default function WorkbenchBarMobileActions({
7481
{t("workbenchBar.saveAs", "Save As")}
7582
</Menu.Item>
7683
)}
77-
{!isCustomView && (
84+
{showFileActions && (
7885
<>
7986
<Menu.Divider />
8087
<Menu.Item

frontend/editor/src/core/components/tools/RightSidebar.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,9 @@ export default function RightSidebar() {
282282
onShowAllTools={handleShowAllTools}
283283
onToolSelect={handleToolSelectWithTransition}
284284
compact={false}
285+
/* Mobile keeps the workbench bar - and with it the super search -
286+
on the other slide, so the list needs its own filter. */
287+
showSearch={isMobile}
285288
/>
286289
</>
287290
</div>

frontend/editor/src/core/components/tools/ToolPanel.css

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,17 @@
183183
}
184184
}
185185

186+
/* In-panel tool filter. Aligned with .tool-picker__compact's inline padding so
187+
the field lines up with the tool rows underneath it. */
188+
.tool-panel__search {
189+
flex-shrink: 0;
190+
padding: 0.5rem var(--mantine-spacing-sm) 0;
191+
}
192+
193+
.tool-panel__search .search-input-container {
194+
margin: 0;
195+
}
196+
186197
.tool-panel__compact-header-actions {
187198
display: flex;
188199
align-items: center;

frontend/editor/src/core/components/tools/ToolPanel.tsx

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { useToolWorkflow } from "@app/contexts/ToolWorkflowContext";
44
import ToolPicker from "@app/components/tools/ToolPicker";
55
import SearchResults from "@app/components/tools/SearchResults";
66
import ToolRenderer from "@app/components/tools/ToolRenderer";
7+
import ToolSearch from "@app/components/tools/toolPicker/ToolSearch";
78
import { ToolPanelViewerBar } from "@app/components/tools/ToolPanelViewerBar";
89
import { ToolId } from "@app/types/toolId";
910

@@ -20,6 +21,11 @@ interface ToolPanelProps {
2021
onToolSelect?: (id: ToolId) => void;
2122
/** Whether to render the compact (favourites + recommended only) view. */
2223
compact?: boolean;
24+
/**
25+
* Render a tool filter at the head of the panel. Set where the workbench
26+
* bar's super search is out of reach, so the list stays searchable in place.
27+
*/
28+
showSearch?: boolean;
2329
}
2430

2531
/** Tool list and renderer for the right rail; rail chrome lives in RightSidebar. */
@@ -28,24 +34,44 @@ export default function ToolPanel({
2834
onShowAllTools,
2935
onToolSelect,
3036
compact: compactProp,
37+
showSearch = false,
3138
}: ToolPanelProps) {
3239
const { t } = useTranslation();
3340
const {
3441
leftPanelView,
3542
searchQuery,
43+
setSearchQuery,
3644
filteredTools,
45+
toolRegistry,
3746
selectedToolKey,
3847
handleToolSelect,
3948
setPreviewFile,
4049
} = useToolWorkflow();
4150
const selectTool = onToolSelect ?? handleToolSelect;
4251

52+
// Only offer the filter over the list itself; once a tool is open the panel
53+
// belongs to that tool. Deriving the results branch from the same flag keeps
54+
// the input and what it filters from drifting apart.
55+
const panelSearch = showSearch && leftPanelView === "toolPicker";
56+
const searching = searchQuery.trim().length > 0;
57+
4358
return (
4459
<>
4560
{/* Viewer mode tools — annotate, redact, form fill */}
4661
<ToolPanelViewerBar />
4762

48-
{allToolsView && searchQuery.trim().length > 0 ? (
63+
{panelSearch && (
64+
<div className="tool-panel__search">
65+
<ToolSearch
66+
value={searchQuery}
67+
onChange={setSearchQuery}
68+
toolRegistry={toolRegistry}
69+
mode="filter"
70+
/>
71+
</div>
72+
)}
73+
74+
{searching && (allToolsView || panelSearch) ? (
4975
<div className="flex-1 flex flex-col overflow-y-auto">
5076
<SearchResults
5177
filteredTools={filteredTools}
@@ -59,7 +85,7 @@ export default function ToolPanel({
5985
selectedToolKey={selectedToolKey}
6086
onSelect={(id) => selectTool(id as ToolId)}
6187
filteredTools={filteredTools}
62-
isSearching={Boolean(searchQuery && searchQuery.trim().length > 0)}
88+
isSearching={searching}
6389
compact={compactProp ?? !allToolsView}
6490
onShowAllTools={onShowAllTools}
6591
/>

0 commit comments

Comments
 (0)