Explorer
Filter plus collection plus selected detail using shared parameter/selection state.
Use the web element directly without the semantic runtime.
Use this component directly or compose it in application code.
The standard recipe resolver does not select this component automatically.
Import and live example#
A people explorer combining authorized filters, a single-select record collection, and selected detail.
Interactive preview requires JavaScript.
View the complete example source
import {registerAeliqoElements} from "@varendo/web";
import {
AeliqoBreakdownElement,
AeliqoComparisonElement,
AeliqoExplorerElement,
AeliqoFormFlowElement,
AeliqoInvestigationElement,
AeliqoQualityPanelElement,
AeliqoRecordEditorElement,
AeliqoSearchResultsElement,
} from "@varendo/web/compound";
import {AeliqoDateRangeElement, AeliqoTextFieldElement} from "@varendo/web/inputs";
import type {ResultRef, Scalar} from "@varendo/core";
import type {VisualizationBindingContext, VisualizationSpec} from "@varendo/core/visualization";
import type {AeliqoDataColumn, AeliqoDataScope, AeliqoFieldOption} from "@varendo/web/data";
import type {VisualizationDataset} from "@varendo/web/visualization";
const catalogRef: ResultRef = {
id: "aeliqo-catalog-example",
revision: "1",
outputId: "people",
queryDigest: "catalog-query",
scopeDigest: "catalog-scope",
};
const catalogRows: readonly Readonly<Record<string, Scalar>>[] = [
{id: "ada", name: "Ada Lovelace", team: "Research", date: "2026-09-08", amount: 120},
{id: "lin", name: "Lin Chen", team: "Product", date: "2026-09-09", amount: 96},
{id: "grace", name: "Grace Hopper", team: "Research", date: "2026-09-10", amount: 144},
];
const catalogColumns: readonly AeliqoDataColumn[] = [
{key: "id", label: "ID", type: "text", sortable: true},
{key: "name", label: "Name", type: "text", sortable: true},
{key: "team", label: "Team", type: "text"},
{key: "date", label: "Date", type: "date", sortable: true},
{key: "amount", label: "Amount", type: "integer", align: "end"},
];
const catalogFields: readonly AeliqoFieldOption[] = [
{id: "name", label: "Name", type: "text"},
{id: "team", label: "Team", type: "text"},
{id: "amount", label: "Amount", type: "integer"},
];
const catalogScope: AeliqoDataScope = {loaded: catalogRows.length, filteredTotal: catalogRows.length, populationDigest: catalogRef.scopeDigest, kind: "filtered", label: "Authorized people"};
const catalogVisualizationContext: VisualizationBindingContext = {results: []};
const catalogVisualizationDataset: VisualizationDataset = {result: catalogRef, rows: catalogRows};
const catalogVisualizationSpecs: Readonly<Record<"trend", VisualizationSpec>> = {trend: {version: "1", view: "trend", plot: {version: "1", root: {kind: "unit", mark: "line", result: catalogRef, missing: "gap", encoding: {x: {field: "date", scale: "temporal"}, y: {field: "amount", scale: "linear"}}}}}};
registerAeliqoElements();
const host = document.querySelector<HTMLElement>("#aeliqo-example") ?? (() => {
const created = document.createElement("div");
created.id = "aeliqo-example";
(document.body ?? document.documentElement).append(created);
return created;
})();
function createCatalogRoot(container: HTMLElement): HTMLElement {
const root = document.createElement("div");
root.dataset.catalogSourceRoot = "true";
root.style.display = "grid";
root.style.gap = "12px";
container.append(root);
return root;
}
function createCatalogElement<T extends HTMLElement>(tagName: string, container: HTMLElement): T {
const element = document.createElement(tagName) as T;
element.setAttribute("data-aeliqo-theme", "light");
container.append(element);
return element;
}
function appendSlottedText(root: HTMLElement, slot: string, textContent: string): void {
const content = document.createElement("span");
content.slot = slot;
content.textContent = textContent;
root.append(content);
}
const root = createCatalogRoot(host);
(((root) => {
const element = createCatalogElement<AeliqoExplorerElement>("aeliqo-explorer", root);
element.fields = catalogFields;
element.rows = catalogRows;
element.columns = catalogColumns;
element.identity = ["id"];
element.entity = "person";
element.selectedKey = "string:3:ada";
element.detailRecord = catalogRows[0];
element.detailFields = catalogColumns;
element.result = catalogRef;
element.scope = catalogScope;
element.selection = "single";
}))(root);
Purpose#
Explorer combines a filter bar, record list, and detail pane into one view with shared scope. Use it when browsing and inspecting records belong on the same screen.
When to use it#
- A record collection needs filter controls and a detail pane sharing one selection.
- Choosing a row should reveal its detail in place instead of navigating away.
- Filter and selection changes must reach the host as proposals, not silent mutations.
- The host owns rows, selection, and detail; the panels only coordinate them.
When to use a different component#
- Use RecordList alone when the view needs no filters or detail pane.
- Use Table when users scan many rows instead of inspecting one record.
- Use separate FilterBuilder, RecordList, and Detail when the app already owns panel layout.
Properties and defaults#
Filter and selection requests retain result lineage and scope; persistence, navigation, and query execution remain with the host.
| Property | Use and ownership | Declared type | Initial value |
|---|---|---|---|
fields | Defines the fields available to this control, including stable IDs, labels, and declared types. | readonly AeliqoFieldOption[] | [] |
predicate | Supplies the validated filter predicate represented by the current control state. | AeliqoFilterPredicate | undefined | undefined |
rows | Supplies the bounded records to render. The component never fetches or widens this set. | readonly AeliqoDataRecord[] | [] |
columns | Defines ordered visible fields, labels, formatting, alignment, and supported column interactions. | readonly AeliqoDataColumn[] | [] |
identity | Lists stable identity fields used for selection, detail targeting, and state transfer. | readonly string[] | [] |
entity | Names the catalog entity whose records and identities are displayed. | string | 'record' |
selectedKey | Controls the current record selection by stable encoded identity. | string | '' |
detailRecord | Supplies detail record to the component as application-owned input. | AeliqoDataRecord | undefined | undefined |
detailFields | Supplies the bounded ordered detail fields collection used by this component. | readonly AeliqoDataColumn[] | [] |
result | Supplies the Result reference that binds displayed data to its query and scope evidence. | ResultRef | undefined | undefined |
scope | Supplies the visible authorization and population scope associated with the displayed value or rows. | AeliqoDataScope | undefined | undefined |
status | Supplies the explicit ready, loading, empty, partial, stale, or error state. | AeliqoCompoundStatus | 'ready' |
message | Provides the user-facing status, error, or recovery message. | string | '' |
title | Provides the visible title for the current data or compound surface. | string | 'Explore' |
filterLabel | Provides the visible text for the filter control or section. | string | 'Filter' |
collectionLabel | Provides the visible text for the collection control or section. | string | 'Records' |
detailLabel | Provides the visible text for the detail control or section. | string | 'Selected detail' |
selection | Chooses none, single, or multiple selection behavior. | 'none' | 'single' | 'multiple' | 'single' |
Events#
| Event | Payload | Emitted | Application responsibility |
|---|---|---|---|
aeliqo-explorer-filter | The proposed validated predicate. | After the explorer filter is applied. | Evaluate the predicate in the host and replace rows/result evidence. |
aeliqo-explorer-selection | The selected stable identity key. | After explorer selection changes. | Load authorized detail evidence and update controlled selection. |
Events cross the component boundary as user proposals. Validate their detail and current authority before applying a business effect.
Listen for aeliqo-explorer-filter
const element = document.querySelector('aeliqo-explorer');<p>element?.addEventListener('aeliqo-explorer-filter', (event) => {
const proposal = (event as CustomEvent<unknown>).detail;
// Validate the proposal, update host state, then assign controlled properties.
applyProposal(proposal);
});Listen for aeliqo-explorer-selection
const element = document.querySelector('aeliqo-explorer');</p>
<p>element?.addEventListener('aeliqo-explorer-selection', (event) => {
const proposal = (event as CustomEvent<unknown>).detail;
// Validate the proposal, update host state, then assign controlled properties.
applyProposal(proposal);
});States and failure handling#
Relevant states:
- ready
- loading
- empty
- partial
- stale
- error
Expected result: The three panels share one scope and stable identity while emitting typed filter and selection requests.
Keyboard, focus, and accessibility#
Keyboard behavior:
- Tab
- Arrow keys in child controls
- Enter or Space
- focus follows stable identity
Exposed semantics:
- aria-label
- role
- section
Responsive behavior#
Stack filters, records, and detail in reading order on narrow hosts. Preserve the shared scope and selected identity when panels move.
Style hooks#
- Shadow parts:
collection,detail,filter,header,panels,root,scope,status - Varendo design tokens referenced:
--aeliqo-space-24
Related components#
Generated TypeScript declaration#
View generated declaration
export declare class AeliqoExplorerElement extends AeliqoCompoundElement {
static readonly properties: {
fields: {
attribute: boolean;
};
predicate: {
attribute: boolean;
};
rows: {
attribute: boolean;
};
columns: {
attribute: boolean;
};
identity: {
attribute: boolean;
};
entity: {
type: StringConstructor;
};
selectedKey: {
attribute: string;
type: StringConstructor;
};
detailRecord: {
attribute: boolean;
};
detailFields: {
attribute: boolean;
};
result: {
attribute: boolean;
};
scope: {
attribute: boolean;
};
status: {
type: StringConstructor;
};
message: {
type: StringConstructor;
};
title: {
type: StringConstructor;
};
filterLabel: {
attribute: string;
type: StringConstructor;
};
collectionLabel: {
attribute: string;
type: StringConstructor;
};
detailLabel: {
attribute: string;
type: StringConstructor;
};
selection: {
type: StringConstructor;
};
};
static readonly styles: import("lit").CSSResult[];
fields: readonly AeliqoFieldOption[];
predicate: AeliqoFilterPredicate | undefined;
rows: readonly AeliqoDataRecord[];
columns: readonly AeliqoDataColumn[];
identity: readonly string[];
entity: string;
selectedKey: string;
detailRecord: AeliqoDataRecord | undefined;
detailFields: readonly AeliqoDataColumn[];
result: ResultRef | undefined;
scope: AeliqoDataScope | undefined;
status: AeliqoCompoundStatus;
message: string;
title: string;
filterLabel: string;
collectionLabel: string;
detailLabel: string;
selection: 'none' | 'single' | 'multiple';
protected render(): import("lit").TemplateResult<1>;
private rowKey;
private readonly forwardFilter;
private readonly forwardSelection;
}Version#
This page documents the Varendo 0.6 component contract.
