Promote workload runtime filter to inline chip toggle

The Runtime axis was hidden inside the "+ Filter" combobox under a
"Properties" optgroup with at most two real choices (docker, podman),
sitting next to Status / Group by / Metric display which are already
chip toggles. Render it inline alongside Status so the binary axis is
one click instead of two, and hide the filter entirely when fewer than
two distinct runtimes are present so single-runtime deployments are not
shown a degenerate All/<one-runtime> control. The leftover "+ Filter"
select now carries only the Node scope.
This commit is contained in:
rcourtman
2026-05-20 10:33:17 +01:00
parent d141819795
commit 96fb624789
4 changed files with 26 additions and 8 deletions
@@ -179,6 +179,7 @@ export const WorkloadsFilter: Component<WorkloadsFilterProps> = (props) => {
id: runtimeFilter.id ?? 'workloads-runtime',
label: runtimeFilter.label ?? 'Runtime',
group: 'properties',
inline: true,
value: () => runtimeFilter.value,
setValue: runtimeFilter.onChange,
defaultValue: '',
@@ -269,6 +269,7 @@ describe('WorkloadsFilter', () => {
options: [
{ value: '', label: 'All runtimes' },
{ value: 'docker', label: 'docker' },
{ value: 'podman', label: 'podman' },
],
onChange: vi.fn(),
},
@@ -329,6 +330,7 @@ describe('WorkloadsFilter', () => {
options: [
{ value: '', label: 'All runtimes' },
{ value: 'docker', label: 'docker' },
{ value: 'podman', label: 'podman' },
],
onChange: runtimeOnChange,
},
@@ -522,7 +524,7 @@ describe('WorkloadsFilter', () => {
});
describe('container runtime filter', () => {
it('appears in the direct selector only when viewMode is a container variant and containerRuntimeFilter is provided', () => {
it('renders inline runtime chips when viewMode is a container variant and containerRuntimeFilter is provided', () => {
const props = makeProps({
viewMode: vi.fn(() => 'container' as const),
containerRuntimeFilter: {
@@ -530,15 +532,18 @@ describe('WorkloadsFilter', () => {
options: [
{ value: '', label: 'All runtimes' },
{ value: 'docker', label: 'docker' },
{ value: 'podman', label: 'podman' },
],
onChange: vi.fn(),
},
});
render(() => <WorkloadsFilter {...props} />);
expect(addFilterOption('Runtime', 'docker')).toBeInTheDocument();
const runtimeGroup = inlineFilterGroup('Runtime');
expect(within(runtimeGroup).getByRole('button', { name: 'docker' })).toBeInTheDocument();
expect(within(runtimeGroup).getByRole('button', { name: 'podman' })).toBeInTheDocument();
});
it('does not appear when viewMode is not a container variant', () => {
it('does not render when viewMode is not a container variant', () => {
const props = makeProps({
viewMode: vi.fn(() => 'vm' as const),
containerRuntimeFilter: {
@@ -546,15 +551,16 @@ describe('WorkloadsFilter', () => {
options: [
{ value: '', label: 'All runtimes' },
{ value: 'docker', label: 'docker' },
{ value: 'podman', label: 'podman' },
],
onChange: vi.fn(),
},
});
render(() => <WorkloadsFilter {...props} />);
expect(screen.queryByRole('combobox', { name: 'Filter' })).not.toBeInTheDocument();
expect(screen.queryByRole('group', { name: 'Runtime' })).not.toBeInTheDocument();
});
it('calls onChange when runtime selection changes through the direct selector', () => {
it('calls onChange when a runtime chip is clicked', () => {
const onChange = vi.fn();
render(() => (
<WorkloadsFilter
@@ -565,13 +571,14 @@ describe('WorkloadsFilter', () => {
options: [
{ value: '', label: 'All runtimes' },
{ value: 'docker', label: 'docker' },
{ value: 'podman', label: 'podman' },
],
onChange,
},
})}
/>
));
pickFromMenu('Runtime', 'docker');
pickInlineFilter('Runtime', 'docker');
expect(onChange).toHaveBeenCalledWith('docker');
});
});
@@ -46,6 +46,16 @@ describe('workloadFilterConfigModel', () => {
runtimeOptions: ['docker'],
onChange,
}),
).toBeUndefined();
expect(
buildWorkloadsContainerRuntimeFilterConfig({
isWorkloadsRoute: true,
viewMode: 'app-container',
containerRuntime: 'docker',
runtimeOptions: ['docker', 'podman'],
onChange,
}),
).toBeDefined();
expect(
@@ -53,7 +63,7 @@ describe('workloadFilterConfigModel', () => {
isWorkloadsRoute: true,
viewMode: 'vm',
containerRuntime: 'docker',
runtimeOptions: ['docker'],
runtimeOptions: ['docker', 'podman'],
onChange,
}),
).toBeUndefined();
@@ -45,7 +45,7 @@ export const buildWorkloadsContainerRuntimeFilterConfig = ({
}: WorkloadsContainerRuntimeFilterConfigOptions): WorkloadsToolbarFilterConfig | undefined => {
if (!isWorkloadsRoute && !allowEmbeddedScopeFilters) return undefined;
if (!isContainerWorkloadViewMode(viewMode)) return undefined;
if (runtimeOptions.length === 0) return undefined;
if (runtimeOptions.length < 2) return undefined;
return {
id: 'workloads-container-runtime-filter',