Search UI Components
This page documents the React components available for customizing record search pages. For deposit form components, see Deposit Form Components. For search page configuration, see Search page.
Search App Configuration
The search page uses the react-searchkit library with custom layout and result components. The search is configured through the oarepo_ui.search module:
import {
parseSearchAppConfigs,
createSearchAppsInit,
} from "@js/oarepo_ui/search";
import ResultsListItem from "./ResultsListItem";
export const componentOverrides = {
// Override the default result list item
`${overridableIdPrefix}.ResultsList.item`: ResultsListItem,
};For more on search endpoint configuration, see Search page.
Components
ResultsList (Custom)
The ResultsList displays search results using customizable list items. You override the individual item component to control how each result appears.
The nrp-model-copier template provides a ResultsListItem component at the model’s search directory. This is the component you customize to match your record’s metadata:
import React from "react";
import PropTypes from "prop-types";
import _get from "lodash/get";
import _join from "lodash/join";
import { Grid, Item, Label } from "semantic-ui-react";
import { i18next } from "@translations/i18next";
export const ResultsListItem = ({ result, ...rest }) => {
const accessRights = _get(result, "ui.access_status", null);
const createdDate = _get(
result,
"ui.created_date_l10n_short",
"No creation date found."
);
const languages = _get(result, "metadata.languages", []);
const version = _get(result, "metadata.version", null);
const title = _get(result, "metadata.title", i18next.t("No title"));
return (
<Item key={result.id} data-testid="result-item">
<Item.Content>
<Grid>
<Grid.Row>
<Grid.Column className="results-list item-main">
<div className="justify-space-between flex">
<Item.Header as="h2">
<a href={result.links.self_html}>{title}</a>
</Item.Header>
<div className="item-access-rights">
{result.state && (
<Label title={result.state_timestamp}>{result.state}</Label>
)}
{accessRights && accessRights.id !== "open" && (
<Label title={`${accessRights.description_l10n}`}>
{accessRights.title_l10n}
</Label>
)}
</div>
</div>
<Item.Meta>
<Grid columns={1}>
<Grid.Column>
<Grid.Row className="ui separated">
<span
aria-label={i18next.t("Languages")}
title={i18next.t("Languages")}
>
{_join(languages.map((l) => l.title), ", ")}
</span>
</Grid.Row>
</Grid.Column>
</Grid>
</Item.Meta>
<Item.Extra>
<div>
<small>
<p>
{createdDate && (
<>
{i18next.t("Uploaded on")} <span>{createdDate}</span>{" "}
{version && `(${i18next.t("version")}: ${version})`}
</>
)}
</p>
</small>
</div>
</Item.Extra>
</Grid.Column>
</Grid.Row>
</Grid>
</Item.Content>
</Item>
);
};
ResultsListItem.propTypes = {
result: PropTypes.object.isRequired,
};
export default ResultsListItem;Source: Model-specific (via nrp-model-copier )
Based on: react-searchkit ResultsList item
Prop:
| Prop | Type | Required | Description |
|---|---|---|---|
result | object | yes | Search result object from API |
Result object structure:
| Path | Type | Description |
|---|---|---|
result.id | string | Record ID |
result.links.self_html | string | Link to record detail page |
result.state | string | Record state (e.g., “draft”, “published”) |
result.state_timestamp | string | State change timestamp |
result.ui.access_status | object | Access rights with id and title_l10n |
result.ui.created_date_l10n_short | string | Formatted creation date |
result.metadata.title | string | Record title |
result.metadata.languages | array | Array of language objects with title |
result.metadata.version | string | Record version |
Search Layout Components
Components from oarepo-ui/search for customizing search UI layout:
RecordsList
Container component that renders the list of search results with loading and empty states:
import { RecordsList } from "@js/oarepo_ui/search";
<RecordsList loading={loading} totalResults={totalResults}>
<YourCustomResultsItems />
</RecordsList>Source: oarepo-ui/RecordsList
ResultsList
Wrapper for search result items using react-overridable:
import { ResultsList } from "@js/oarepo_ui/search";
<ResultsList />Source: oarepo-ui/ResultsList
DynamicResultsListItem
Dynamic result item component that handles loading and error states:
import { DynamicResultsListItem } from "@js/oarepo_ui/search";
<DynamicResultsListItem result={result} loading={loading} error={error} />Source: oarepo-ui/DynamicResultsListItem
SearchAppLayout
Main layout component for the search page - contains facets and results:
import { SearchAppLayout } from "@js/oarepo_ui/search";
<SearchAppLayout>
<SearchAppFacets />
<SearchAppResults />
</SearchAppLayout>Source: oarepo-ui/SearchAppLayout
SearchAppLayoutWithSearchbar
Layout with integrated search bar at the top:
import { SearchAppLayoutWithSearchbar } from "@js/oarepo_ui/search";
<SearchAppLayoutWithSearchbar>
<YourSearchComponents />
</SearchAppLayoutWithSearchbar>Source: oarepo-ui/SearchAppLayoutWithSearchbar
SearchAppFacets
Facet/aggregation panel component for filters:
import { SearchAppFacets } from "@js/oarepo_ui/search";
<SearchAppFacets />Source: oarepo-ui/SearchAppFacets
BucketAggregationElement
Single bucket aggregation facet component:
import { BucketAggregationElement } from "@js/oarepo_ui/search";
<BucketAggregationElement title="Resource Type" bucketAggKey="resource_type" />Source: oarepo-ui/BucketAggregationElement
FoldableBucketAggregationElement
Foldable bucket aggregation for hierarchical facets:
import { FoldableBucketAggregationElement } from "@js/oarepo_ui/search";
<FoldableBucketAggregationElement title="Subject Categories" bucketAggKey="subject" />Source: oarepo-ui/FoldableBucketAggregationElement
SearchBar Components
SearchAppSearchbarContainer
Container for search bar component:
import { SearchAppSearchbarContainer } from "@js/oarepo_ui/search";
<SearchAppSearchbarContainer>
<YourSearchbar />
</SearchAppSearchbarContainer>Source: oarepo-ui/SearchAppSearchbarContainer
ClearableSearchbarElement
Single-line search bar with clear button:
import { ClearableSearchbarElement } from "@js/oarepo_ui/search";
<ClearableSearchbarElement
placeholder="Search records..."
queryHelperSchema={queryHelperSchema}
/>Source: oarepo-ui/ClearableSearchbarElement
MultilineSearchbarElement
Multi-line search bar for complex queries:
import { MultilineSearchbarElement } from "@js/oarepo_ui/search";
<MultilineSearchbarElement
placeholder="Search records..."
queryHelperSchema={queryHelperSchema}
/>Source: oarepo-ui/MultilineSearchbarElement
Result Controls
SearchAppSort
Sort control component:
import { SearchAppSort } from "@js/oarepo_ui/search";
<SearchAppSort />Source: oarepo-ui/SearchAppSort
SearchAppResults
Results container component:
import { SearchAppResults } from "@js/oarepo_ui/search";
<SearchAppResults>
<YourResultsComponents />
</SearchAppResults>Source: oarepo-ui/SearchAppResults
Filter Components
ActiveFiltersElement
Active filter tags display:
import { ActiveFiltersElement } from "@js/oarepo_ui/search";
<ActiveFiltersElement />Source: oarepo-ui/ActiveFiltersElement
ClearFiltersButton
Button to clear all filters:
import { ClearFiltersButton } from "@js/oarepo_ui/search";
<ClearFiltersButton />Source: oarepo-ui/ClearFiltersButton
State Components
EmptyResultsElement
Empty state component when no results found:
import { EmptyResultsElement } from "@js/oarepo_ui/search";
<EmptyResultsElement />Source: oarepo-ui/EmptyResultsElement
ErrorElement
Error state component for search failures:
import { ErrorElement } from "@js/oarepo_ui/search";
<ErrorElement />Source: oarepo-ui/ErrorElement
Pagination & Info Components
ResultCount
Result count display:
import { ResultCount } from "@js/oarepo_ui/search";
<ResultCount />Source: oarepo-ui/ResultCount
ResultsPerPageLabel
Results per page label:
import { ResultsPerPageLabel } from "@js/oarepo_ui/search";
<ResultsPerPageLabel />Source: oarepo-ui/ResultsPerPageLabel
SmallPagination
Pagination component:
import { SmallPagination } from "@js/oarepo_ui/search";
<SmallPagination />Source: oarepo-ui/SmallPagination