Skip to content

Commit 8270979

Browse files
fix(ui): align scan filters and actions (#12781)
1 parent 369f852 commit 8270979

10 files changed

Lines changed: 73 additions & 61 deletions
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Scans page filter widths and action button styling, with Launch Scan and Import Findings grouped beside the tabs and sized consistently with Configure Mutelist

ui/components/scans/import-findings-modal.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,9 @@ export function ImportFindingsModal() {
223223
<>
224224
<Button
225225
type="button"
226-
size="lg"
227-
variant="secondary"
226+
variant="outline"
228227
onClick={() => handleOpenChange(true)}
229-
className="w-full md:w-auto"
228+
className="w-full sm:w-auto"
230229
>
231230
Import Findings
232231
</Button>

ui/components/scans/scans-filter-bar.tsx

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ interface ScansFilterBarProps {
3131
onScanStatusChange: (value: string) => void;
3232
}
3333

34-
const filterItemClass = "w-full md:w-[calc(50%-0.375rem)] xl:w-60";
34+
const filterItemClass = "w-full sm:max-w-[240px] sm:min-w-[180px] sm:flex-1";
3535

3636
export function ScansFilterBar({
3737
providers,
@@ -67,33 +67,37 @@ export function ScansFilterBar({
6767
</div>
6868

6969
{showScheduleTypeFilter && (
70-
<Select value={scheduleType} onValueChange={onScheduleTypeChange}>
71-
<SelectTrigger aria-label="All Types" className={filterItemClass}>
72-
<SelectValue placeholder="All Types" />
73-
</SelectTrigger>
74-
<SelectContent>
75-
{triggerFilterOptions.map((option) => (
76-
<SelectItem key={option.value} value={option.value}>
77-
{option.label}
78-
</SelectItem>
79-
))}
80-
</SelectContent>
81-
</Select>
70+
<div className={filterItemClass}>
71+
<Select value={scheduleType} onValueChange={onScheduleTypeChange}>
72+
<SelectTrigger aria-label="All Types">
73+
<SelectValue placeholder="All Types" />
74+
</SelectTrigger>
75+
<SelectContent>
76+
{triggerFilterOptions.map((option) => (
77+
<SelectItem key={option.value} value={option.value}>
78+
{option.label}
79+
</SelectItem>
80+
))}
81+
</SelectContent>
82+
</Select>
83+
</div>
8284
)}
8385

8486
{showStatusFilter && (
85-
<Select value={scanStatus} onValueChange={onScanStatusChange}>
86-
<SelectTrigger aria-label="All Statuses" className={filterItemClass}>
87-
<SelectValue placeholder="All Statuses" />
88-
</SelectTrigger>
89-
<SelectContent>
90-
{statusFilterOptions.map((option) => (
91-
<SelectItem key={option.value} value={option.value}>
92-
{option.label}
93-
</SelectItem>
94-
))}
95-
</SelectContent>
96-
</Select>
87+
<div className={filterItemClass}>
88+
<Select value={scanStatus} onValueChange={onScanStatusChange}>
89+
<SelectTrigger aria-label="All Statuses">
90+
<SelectValue placeholder="All Statuses" />
91+
</SelectTrigger>
92+
<SelectContent>
93+
{statusFilterOptions.map((option) => (
94+
<SelectItem key={option.value} value={option.value}>
95+
{option.label}
96+
</SelectItem>
97+
))}
98+
</SelectContent>
99+
</Select>
100+
</div>
97101
)}
98102
</>
99103
);

ui/components/scans/scans-page-shell.test.tsx

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -336,26 +336,35 @@ describe("ScansPageShell", () => {
336336
expect(screen.queryByRole("alert")).not.toBeInTheDocument();
337337
});
338338

339-
it("keeps launch scan with filters and mutelist with tabs", () => {
340-
vi.stubEnv("UI_CLOUD_ENABLED", "false");
339+
it("keeps launch scan, import findings, and mutelist with tabs", () => {
340+
// Given
341+
vi.stubEnv("UI_CLOUD_ENABLED", "true");
341342

343+
// When
342344
render(
343-
<ScansPageShell providers={providers} hasManageScansPermission>
345+
<ScansPageShell
346+
providers={providers}
347+
hasManageScansPermission
348+
hasManageIngestionsPermission
349+
>
344350
<div>Scans table</div>
345351
</ScansPageShell>,
346352
);
347353

348-
expect(
349-
screen.getByRole("group", { name: /scan filters and actions/i }),
350-
).toContainElement(screen.getByRole("button", { name: /launch scan/i }));
351-
expect(
352-
screen.getByRole("group", { name: /scan filters and actions/i }),
353-
).not.toContainElement(
354-
screen.getByRole("link", { name: /configure mutelist/i }),
354+
// Then
355+
const tabs = screen.getByRole("group", { name: /scan tabs/i });
356+
expect(tabs).toContainElement(
357+
screen.getByRole("button", { name: /launch scan/i }),
355358
);
356-
expect(screen.getByRole("group", { name: /scan tabs/i })).toContainElement(
359+
expect(tabs).toContainElement(
360+
screen.getByRole("button", { name: /import findings/i }),
361+
);
362+
expect(tabs).toContainElement(
357363
screen.getByRole("link", { name: /configure mutelist/i }),
358364
);
365+
expect(
366+
screen.getByRole("group", { name: /scan filters/i }),
367+
).toContainElement(screen.getByText("Shared scan filters"));
359368
});
360369

361370
it("shows the active scans count in the in progress tab", () => {

ui/components/scans/scans-page-shell.tsx

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,8 @@ export function ScansPageShell({
135135
)}
136136
<div
137137
role="group"
138-
aria-label="Scan filters and actions"
139-
className="flex flex-wrap items-center gap-3"
138+
aria-label="Scan filters"
139+
className="flex flex-wrap items-center gap-4"
140140
>
141141
<ScansFilterBar
142142
providers={providers}
@@ -148,20 +148,6 @@ export function ScansPageShell({
148148
onScheduleTypeChange={filters.setScheduleType}
149149
onScanStatusChange={filters.setScanStatus}
150150
/>
151-
152-
<Button
153-
type="button"
154-
size="lg"
155-
onClick={() => handleLaunchOpenChange(true)}
156-
disabled={launchDisabled}
157-
className="w-full md:w-auto"
158-
data-tour-id="view-first-scan-launch"
159-
>
160-
Launch Scan
161-
</Button>
162-
{isCloudEnvironment && hasManageIngestionsPermission && (
163-
<ImportFindingsModal />
164-
)}
165151
</div>
166152

167153
{isCloudEnvironment && <CliImportBanner />}
@@ -174,10 +160,10 @@ export function ScansPageShell({
174160
<div
175161
role="group"
176162
aria-label="Scan tabs"
177-
className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between"
163+
className="flex flex-wrap items-center justify-between gap-3"
178164
>
179165
<TabsList
180-
className="overflow-x-auto"
166+
className="w-full overflow-x-auto sm:w-auto"
181167
data-tour-id="view-first-scan-tabs"
182168
>
183169
{Object.values(SCAN_JOBS_TAB).map((tab) => (
@@ -186,7 +172,19 @@ export function ScansPageShell({
186172
</TabsTrigger>
187173
))}
188174
</TabsList>
189-
<div className="shrink-0">
175+
<div className="ml-auto flex w-full flex-wrap items-center gap-3 sm:w-auto">
176+
<Button
177+
type="button"
178+
onClick={() => handleLaunchOpenChange(true)}
179+
disabled={launchDisabled}
180+
className="w-full sm:w-auto"
181+
data-tour-id="view-first-scan-launch"
182+
>
183+
Launch Scan
184+
</Button>
185+
{isCloudEnvironment && hasManageIngestionsPermission && (
186+
<ImportFindingsModal />
187+
)}
190188
<MutedFindingsConfigButton />
191189
</div>
192190
</div>
27.6 KB
Loading
23.6 KB
Loading
22.8 KB
Loading

ui/tests/scans/scans-page.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ export class ScansPage extends BasePage {
2727
// The sidebar exposes its own icon-button labeled "Launch Scan"
2828
// (aria-label, wrapped in a Tooltip), so scoping by accessible name
2929
// alone hits a strict-mode duplicate. Scope to the page-shell's
30-
// filters-and-actions group, which only contains the visible-text
30+
// tabs-and-actions group, which only contains the visible-text
3131
// Launch Scan button.
3232
this.launchScanButton = page
33-
.getByRole("group", { name: /scan filters and actions/i })
33+
.getByRole("group", { name: /scan tabs/i })
3434
.getByRole("button", { name: /^Launch Scan$/i });
3535
this.launchScanDialog = page.getByRole("dialog");
3636
// The modal renders the providers picker as the shared MultiSelect-based

ui/tests/scans/scans.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
### Flow Steps
2828

2929
1. Navigate to Scans page
30-
2. Click "Launch Scan" to open the launch scan modal
30+
2. Click "Launch Scan" beside the scan tabs to open the launch scan modal
3131
3. Open the Cloud Account selector and choose the entry whose text contains E2E_AWS_PROVIDER_ACCOUNT_ID
3232
4. Optionally fill Scan Note
3333
5. Click "Launch Scan" in the modal
@@ -46,6 +46,7 @@
4646

4747
- Scans page loads correctly
4848
- Launch Scan modal opens correctly
49+
- The page-level "Launch Scan" button is located in the "Scan tabs" group, distinct from the sidebar action
4950
- Cloud Account select is available and lists the configured provider UID
5051
- "Launch Scan" button is rendered and enabled when form is valid
5152
- Success toast message: "The scan was launched successfully."

0 commit comments

Comments
 (0)