web: Fix table visibility checks, search params. (#21623)

Fix visibility check, search params.
This commit is contained in:
Teffen Ellis
2026-04-16 15:01:02 +02:00
committed by GitHub
parent 1b53426e2c
commit 4667deaefc
4 changed files with 33 additions and 58 deletions

View File

@@ -1,22 +0,0 @@
const isStyledVisible = ({ visibility, display }: CSSStyleDeclaration) =>
visibility !== "hidden" && display !== "none";
const isDisplayContents = ({ display }: CSSStyleDeclaration) => display === "contents";
function computedStyleIsVisible(element: HTMLElement) {
const computedStyle = window.getComputedStyle(element);
return (
isStyledVisible(computedStyle) &&
(isDisplayContents(computedStyle) ||
!!(element.offsetWidth || element.offsetHeight || element.getClientRects().length))
);
}
export function isVisible(element: HTMLElement) {
return (
element &&
element.isConnected &&
isStyledVisible(element.style) &&
computedStyleIsVisible(element)
);
}

View File

@@ -22,6 +22,7 @@ import { type TransclusionChildElement, TransclusionChildSymbol } from "#element
import { WithSession } from "#elements/mixins/session";
import { getURLParam, updateURLParams } from "#elements/router/RouteMatch";
import Styles from "#elements/table/Table.css";
import { TableSearchForm } from "#elements/table/TableSearch";
import { SlottedTemplateResult } from "#elements/types";
import { ifPresent } from "#elements/utils/attributes";
import { isInteractiveElement } from "#elements/utils/interactivity";
@@ -315,9 +316,20 @@ export abstract class Table<T extends object, D = T>
return this.selectedElements as unknown as D[];
}
public clearSearch = () => {
this.data = null;
this.searchInputRef.value?.reset();
this.requestUpdate("search");
return this.fetch();
};
//#endregion
//#region Lifecycle
#selectAllCheckboxRef = createRef<HTMLInputElement>();
protected selectAllCheckboxRef = createRef<HTMLInputElement>();
protected searchInputRef = createRef<TableSearchForm>();
protected refreshListener = (event?: Event) => {
this.logger.debug("Received refresh event:", event);
@@ -460,7 +472,7 @@ export abstract class Table<T extends object, D = T>
if (this.selectedMap.size) {
this.selectedMap = new Map();
const selectAllCheckbox = this.#selectAllCheckboxRef.value;
const selectAllCheckbox = this.selectAllCheckboxRef.value;
if (selectAllCheckbox) {
selectAllCheckbox.checked = false;
@@ -677,7 +689,7 @@ export abstract class Table<T extends object, D = T>
this.requestUpdate("selectedMap");
}
const selectAllCheckbox = this.#selectAllCheckboxRef.value;
const selectAllCheckbox = this.selectAllCheckboxRef.value;
const pageItemCount = this.data?.results?.length ?? 0;
const selectedCount = this.selectedMap.size;
@@ -868,9 +880,13 @@ export abstract class Table<T extends object, D = T>
#searchListener = (value: string) => {
this.search = value;
this.page = 1;
this.fetch();
return this.fetch();
};
/**
* Whether the search input should be rendered.
*/
protected searchEnabled = false;
protected renderSearch(): SlottedTemplateResult {
@@ -879,6 +895,7 @@ export abstract class Table<T extends object, D = T>
}
return html`<ak-table-search
${ref(this.searchInputRef)}
exportparts="input:toolbar-search-input"
class="pf-c-toolbar__item pf-m-search-filter ${this.supportsQL ? "ql" : ""}"
part="toolbar-search"
@@ -888,8 +905,7 @@ export abstract class Table<T extends object, D = T>
.onSearch=${this.#searchListener}
.supportsQL=${this.supportsQL}
.apiResponse=${this.data}
>
</ak-table-search>`;
></ak-table-search>`;
}
//#endregion
@@ -897,7 +913,7 @@ export abstract class Table<T extends object, D = T>
//#region Chips
#synchronizeCheckboxAll = () => {
const checkbox = this.#selectAllCheckboxRef.value;
const checkbox = this.selectAllCheckboxRef.value;
if (!checkbox) return;
@@ -935,7 +951,7 @@ export abstract class Table<T extends object, D = T>
return html`<th class="pf-c-table__check" role="presentation">
<input
${ref(this.#selectAllCheckboxRef)}
${ref(this.selectAllCheckboxRef)}
name="select-all"
type="checkbox"
aria-label=${msg(

View File

@@ -1,6 +1,5 @@
import "#elements/EmptyState";
import { updateURLParams } from "#elements/router/RouteMatch";
import { Table } from "#elements/table/Table";
import Styles from "#elements/table/TablePage.css";
import { SlottedTemplateResult } from "#elements/types";
@@ -84,22 +83,6 @@ export abstract class TablePage<T extends object> extends Table<T> {
//#endregion
//#region Protected methods
protected clearSearch = () => {
this.search = "";
this.requestUpdate();
updateURLParams({
search: "",
});
return this.fetch();
};
//#endregion
//#region Render methods
/**
@@ -125,15 +108,7 @@ export abstract class TablePage<T extends object> extends Table<T> {
if (!this.search) {
return nothing;
}
return html`<button
@click=${() => {
this.search = "";
this.requestUpdate();
this.fetch();
this.page = 1;
}}
class="pf-c-button pf-m-link"
>
return html`<button @click=${this.clearSearch} class="pf-c-button pf-m-link">
${msg("Clear search")}
</button>`;
}

View File

@@ -4,7 +4,9 @@ export const InteractiveElementsQuery =
export function isInteractiveElement(
target: EventTarget | Element | null | undefined,
): target is HTMLElement {
if (!target || !(target instanceof HTMLElement)) {
if (!target) return false;
if (!(target instanceof HTMLElement)) {
return false;
}
@@ -16,5 +18,9 @@ export function isInteractiveElement(
// so we fallback to assuming the element is visible.
const visible = target.checkVisibility?.() ?? true;
return visible && target.matches(InteractiveElementsQuery);
const { tabIndex } = target;
return (
visible && (tabIndex === 0 || tabIndex === -1 || target.matches(InteractiveElementsQuery))
);
}