mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-19 10:33:29 +00:00
align Add filter controls
This commit is contained in:
parent
37dfdf95ad
commit
3afc8bda15
7 changed files with 69 additions and 21 deletions
|
|
@ -3898,6 +3898,11 @@ not need a feature-owned reset. Route-owned or multi-facet platform surfaces
|
|||
may supply one composite reset, which the toolbar delegates exactly once;
|
||||
otherwise the shared `FilterBar` fallback clears its search and inline status
|
||||
catalog without forcing every platform table to repeat reset plumbing.
|
||||
Platform table toolbars also use the compact Add filter variant: the visible
|
||||
uppercase field label and labelled-field shell stay hidden while the native
|
||||
select retains its accessible `Filter` name. Provider surfaces must inherit
|
||||
that treatment from `PlatformTableToolbar` instead of choosing different
|
||||
label and width chrome page by page.
|
||||
Primary filters with small, stable option sets should stay one-click controls
|
||||
inside that same `FilterDef[]` catalog by setting `inline: true`; `FilterBar`
|
||||
renders those as unlabeled compact segmented controls in the same second-row
|
||||
|
|
@ -3965,10 +3970,10 @@ The Add filter select and adjacent action/popover triggers share the canonical
|
|||
`filterToolbarControlClass` height. When the Add filter label is visually
|
||||
hidden, its `FormSelect` must also omit the labelled group's outer padded/ring
|
||||
shell so the native select does not become a double-framed, oversized control;
|
||||
its extra width remains intentional space for dynamic filter-value labels. The
|
||||
visible `Add filter` value is a disabled, hidden placeholder, not an actionable
|
||||
option repeated at the top of the opened native list; only real filter values
|
||||
belong in that choice list.
|
||||
the select uses one stable compact width instead of expanding to its longest
|
||||
hidden option. The visible `Add filter` value is a disabled, hidden
|
||||
placeholder, not an actionable option repeated at the top of the opened native
|
||||
list; only real filter values belong in that choice list.
|
||||
Counts or orientation strips presented as part of a filtered resource table
|
||||
must derive from that table's canonical filtered collection as well. They must
|
||||
not continue showing page-wide inventory totals after FilterBar state, saved
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
{
|
||||
"version": 1,
|
||||
"base_sha": "e3fdfc98b413db1b29b18cb65bb18bd10bdd3e18",
|
||||
"verified_at": "2026-08-03T13:09:09Z",
|
||||
"base_sha": "37dfdf95ad4d9136973133006b03e45a421884c1",
|
||||
"verified_at": "2026-08-03T13:38:29Z",
|
||||
"result": "passed",
|
||||
"changed_paths": [
|
||||
"frontend-modern/src/components/shared/FilterBar/AddFilterMenu.tsx",
|
||||
"frontend-modern/src/features/platformPage/sharedPlatformPage.tsx"
|
||||
],
|
||||
"content_sha256": {
|
||||
"frontend-modern/src/features/platformPage/sharedPlatformPage.tsx": "b94fdef76a18a9ef95f393f11445b8da613593064e03260c9349f804d39fb2fb"
|
||||
"frontend-modern/src/components/shared/FilterBar/AddFilterMenu.tsx": "b9be43892868440a5cd08a29e730f9ed67cf8f7bc0997d1af1b600d6a1d42bf8",
|
||||
"frontend-modern/src/features/platformPage/sharedPlatformPage.tsx": "42d877508eaac7af7b90c97ceac3cc279554cff019981518ab77e940b24ec2bd"
|
||||
},
|
||||
"routes": ["/truenas/overview", "/kubernetes/overview", "/vmware/networks"],
|
||||
"routes": ["/docker/overview", "/kubernetes/workloads"],
|
||||
"viewports": [
|
||||
{
|
||||
"width": 1280,
|
||||
|
|
@ -21,18 +23,18 @@
|
|||
}
|
||||
],
|
||||
"states": [
|
||||
"Desktop TrueNAS alert toolbar with default, search-only, and combined search/status state",
|
||||
"Phone-width TrueNAS alert toolbar with collapsed and expanded filter rails",
|
||||
"Desktop Kubernetes overview with URL-owned combined search/status state",
|
||||
"Desktop vSphere networks with table-local search state"
|
||||
"Desktop Docker container toolbar before and after applying its longest host filter",
|
||||
"Desktop Kubernetes workload toolbar with dynamic cluster and namespace filters available",
|
||||
"Phone-width Docker toolbar with the filter rail collapsed, expanded, and host-filtered",
|
||||
"Phone-width Kubernetes workload toolbar with the filter rail expanded"
|
||||
],
|
||||
"interactions": [
|
||||
"Entered TrueNAS alert search text and confirmed contextual Clear filters appeared without requiring table-specific reset plumbing",
|
||||
"Selected Warning with search active and confirmed one Clear filters action restored blank search and All status",
|
||||
"Expanded the phone-width TrueNAS filter rail and confirmed Clear filters and the result count aligned without clipping or overflow",
|
||||
"Cleared phone-width search state and confirmed the Clear action disappeared while the status default remained selected",
|
||||
"Loaded Kubernetes overview with ?q=payments&status=degraded, confirmed both controls hydrated, and verified its feature-owned composite reset returned the exact default route",
|
||||
"Entered and cleared vSphere network search text to confirm the shared fallback applies across another table-local platform consumer",
|
||||
"Read the browser console after the final cross-platform pass and confirmed no warnings or errors"
|
||||
"Measured Docker and Kubernetes Add filter controls at 120 by 28 pixels beside the 95 by 28 pixel Saved trigger instead of the previous 204-pixel content-expanded select",
|
||||
"Confirmed platform toolbars no longer render the redundant visible uppercase Filter label while the select retains its accessible Filter name",
|
||||
"Inspected the native filter option projection and confirmed the disabled Add filter placeholder is absent from its actionable option list",
|
||||
"Applied the longest Docker host option, confirmed the compact control gave way to a host chip, Clear filters, and the filtered 14 of 70 result count without overflow",
|
||||
"Cleared the Docker host filter and confirmed the chip and Clear action disappeared, the Add filter control returned, and the canonical route stayed unchanged",
|
||||
"Expanded the Docker and Kubernetes phone-width filter rails and confirmed Add filter, Saved, View, Clear filters, chips, and result counts wrapped without clipping",
|
||||
"Read the browser console after the final desktop and responsive pass and confirmed no warnings or errors"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ export const AddFilterMenu: Component<AddFilterMenuProps> = (props) => {
|
|||
fieldBaseClass={fieldBaseClass()}
|
||||
labelClass={props.showLabel === false ? 'sr-only' : filterLabelClass}
|
||||
selectBaseClass={`${filterToolbarControlClass} border border-transparent bg-surface-hover px-2 text-muted outline-none ring-1 ring-border-subtle transition-colors hover:bg-surface hover:text-base-content focus:border-blue-500`}
|
||||
selectClass="min-w-[7.5rem]"
|
||||
selectClass="w-[7.5rem]"
|
||||
value=""
|
||||
onChange={handleChange}
|
||||
aria-label="Filter"
|
||||
|
|
|
|||
|
|
@ -264,6 +264,8 @@ describe('FilterBar', () => {
|
|||
const label = document.querySelector(`label[for="${select.id}"]`);
|
||||
expect(label).toHaveClass('sr-only');
|
||||
expect(select).toHaveClass('h-7');
|
||||
expect(select).toHaveClass('w-[7.5rem]');
|
||||
expect(select).not.toHaveClass('min-w-[7.5rem]');
|
||||
expect(select.parentElement).not.toHaveClass('p-0.5');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -8185,7 +8185,8 @@ describe('shared primitive guardrails', () => {
|
|||
expect(addFilterMenuSource).toContain('option.value !== filter.defaultValue');
|
||||
expect(addFilterMenuSource).toContain('GROUP_ORDER');
|
||||
expect(addFilterMenuSource).toContain('filterGroupClass');
|
||||
expect(addFilterMenuSource).toContain('min-w-[7.5rem]');
|
||||
expect(addFilterMenuSource).toContain('selectClass="w-[7.5rem]"');
|
||||
expect(addFilterMenuSource).not.toContain('min-w-[7.5rem]');
|
||||
expect(addFilterMenuSource).toContain('bg-surface-hover');
|
||||
expect(addFilterMenuSource).toContain('ring-border-subtle');
|
||||
expect(addFilterMenuSource).toContain('aria-label="Filter"');
|
||||
|
|
@ -8249,6 +8250,7 @@ describe('shared primitive guardrails', () => {
|
|||
expect(filterBarSource).toContain('aria-label="Filter actions"');
|
||||
expect(sharedPlatformPageSource).toContain('viewOptions?: JSX.Element;');
|
||||
expect(sharedPlatformPageSource).toContain('viewOptions={props.viewOptions}');
|
||||
expect(sharedPlatformPageSource).toContain('showAddFilterLabel={false}');
|
||||
expect(sharedPlatformPageSource).toContain('trailingControls={');
|
||||
expect(sharedPlatformPageSource).not.toContain('ViewOptionsMenu');
|
||||
expect(sharedPlatformPageSource).toContain(
|
||||
|
|
|
|||
|
|
@ -281,6 +281,42 @@ describe('filterPlatformResources', () => {
|
|||
});
|
||||
|
||||
describe('PlatformTableToolbar', () => {
|
||||
it('keeps the Add filter control compact without losing its accessible label', () => {
|
||||
const [node, setNode] = createSignal('all');
|
||||
|
||||
render(() =>
|
||||
PlatformTableToolbar({
|
||||
search: () => '',
|
||||
onSearchChange: () => undefined,
|
||||
searchPlaceholder: 'Search rows',
|
||||
status: 'all',
|
||||
onStatusChange: () => undefined,
|
||||
statusOptions: [{ value: 'all', label: 'All' }],
|
||||
filters: [
|
||||
{
|
||||
id: 'node',
|
||||
label: 'Node',
|
||||
options: () => [
|
||||
{ value: 'all', label: 'All' },
|
||||
{ value: 'pve1', label: 'pve1' },
|
||||
],
|
||||
value: node,
|
||||
setValue: setNode,
|
||||
defaultValue: 'all',
|
||||
},
|
||||
],
|
||||
visible: 2,
|
||||
total: 3,
|
||||
rowNoun: 'rows',
|
||||
}),
|
||||
);
|
||||
|
||||
const select = screen.getByRole('combobox', { name: 'Filter' });
|
||||
const label = document.querySelector(`label[for="${select.id}"]`);
|
||||
expect(label).toHaveClass('sr-only');
|
||||
expect(select.parentElement).not.toHaveClass('p-0.5');
|
||||
});
|
||||
|
||||
it('shows and clears search-only state without requiring a custom reset owner', () => {
|
||||
const [search, setSearch] = createSignal('archive');
|
||||
|
||||
|
|
|
|||
|
|
@ -1058,6 +1058,7 @@ export function PlatformTableToolbar<T extends string | number>(props: {
|
|||
tips: props.searchTips,
|
||||
}}
|
||||
filters={allFilters}
|
||||
showAddFilterLabel={false}
|
||||
savedViewsKey={props.savedViewsKey}
|
||||
viewOptions={props.viewOptions}
|
||||
trailingControls={
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue