From ef0175842e6d9b65fd9abb1572371cfd5ddf81aa Mon Sep 17 00:00:00 2001 From: Application-drop-up Date: Mon, 22 Jun 2026 20:29:20 +0900 Subject: [PATCH 1/4] feat: add Spinner component for loading states MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a centered spinning-circle component to replace the plain "Loading…" text currently shown across the top, detail, and search results pages. --- client/src/shared/uis/Spinner.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 client/src/shared/uis/Spinner.tsx diff --git a/client/src/shared/uis/Spinner.tsx b/client/src/shared/uis/Spinner.tsx new file mode 100644 index 0000000..a3d40f6 --- /dev/null +++ b/client/src/shared/uis/Spinner.tsx @@ -0,0 +1,11 @@ +export function Spinner({ className = "" }: { className?: string }) { + return ( +
+
+
+ ); +} From c0cdbbdb52bc41444aa523891b317b15f0cf73ad Mon Sep 17 00:00:00 2001 From: Application-drop-up Date: Mon, 22 Jun 2026 20:31:43 +0900 Subject: [PATCH 2/4] feat: use Spinner for detail page loading state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the plain-text "Loading…" paragraph with the Spinner component. --- .../top/containers/world-heritage-detail-container.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/app/features/top/containers/world-heritage-detail-container.tsx b/client/src/app/features/top/containers/world-heritage-detail-container.tsx index 0e44ddc..be39a22 100644 --- a/client/src/app/features/top/containers/world-heritage-detail-container.tsx +++ b/client/src/app/features/top/containers/world-heritage-detail-container.tsx @@ -3,6 +3,7 @@ import { useParams, useNavigate } from "react-router-dom"; import { useWorldHeritageDetail } from "../hooks/use-world-heritage-detail"; import { HeritageDetailLayout } from "../components/heritage-detail/HeritageDetailLayout"; import BreadcrumbContext from "@features/breadcrumbs/BreadCrumbProvider"; +import { Spinner } from "@shared/uis/Spinner.tsx"; export function WorldHeritageDetailContainer() { const { id } = useParams<{ id: string }>(); @@ -23,7 +24,7 @@ export function WorldHeritageDetailContainer() { setLabel("/heritages/:id", label); }, [setLabel, isLoading, isError, item?.name]); - if (isLoading) return

Loading…

; + if (isLoading) return ; if (isError) { return ( From 66445d970b64bfef0659eb4967239e65c852331f Mon Sep 17 00:00:00 2001 From: Application-drop-up Date: Mon, 22 Jun 2026 20:33:38 +0900 Subject: [PATCH 3/4] feat: use Spinner for top page loading state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the plain-text "Loading…" div with the Spinner component. --- client/src/app/features/top/containers/top-page-container.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/app/features/top/containers/top-page-container.tsx b/client/src/app/features/top/containers/top-page-container.tsx index 128d33b..f54cbb4 100644 --- a/client/src/app/features/top/containers/top-page-container.tsx +++ b/client/src/app/features/top/containers/top-page-container.tsx @@ -10,6 +10,7 @@ import { TopPagePagination } from "../components/TopPagePagination"; import type { IdSortOption } from "../../../../domain/types"; import { parseHeritageSearchParams } from "@features/search/mapper/search-heritages.params"; import { DEFAULT_HERITAGE_SEARCH_PARAMS as SEARCH_PARAMS } from "@features/search/mapper/search-heritage.types"; +import { Spinner } from "@shared/uis/Spinner.tsx"; const DEFAULT_TOP_PER_PAGE = 30; const DEFAULT_ORDER: IdSortOption = "asc"; @@ -94,7 +95,7 @@ export default function TopPageContainer(): React.ReactElement { <> {header}
-
Loading…
+
); From ea369b14e53d1864404138ef7ec1a52d506da658 Mon Sep 17 00:00:00 2001 From: Application-drop-up Date: Mon, 22 Jun 2026 20:34:39 +0900 Subject: [PATCH 4/4] feat: render Spinner standalone for search results loading state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously the loading state rendered the full SearchResultsPage shell with rangeText="Loading…", which could misleadingly show the "no sites found" empty state while a request was in flight. Render the Spinner standalone alongside the search header instead. --- .../containers/search-heritage-result-container.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/client/src/app/features/search/containers/search-heritage-result-container.tsx b/client/src/app/features/search/containers/search-heritage-result-container.tsx index 41a5c52..5a45dc3 100644 --- a/client/src/app/features/search/containers/search-heritage-result-container.tsx +++ b/client/src/app/features/search/containers/search-heritage-result-container.tsx @@ -19,6 +19,7 @@ import { toWorldHeritageListVm } from "@features/heritages/mappers/to-world-heri import { HeritageSubHeader } from "@features/top/components/HeritageSubHeader"; import { DEFAULT_HERITAGE_SEARCH_PARAMS as SEARCH_PARAMS } from "../mapper/search-heritage.types"; import { useLocale } from "@shared/locale/LocaleHooks"; +import { Spinner } from "@shared/uis/Spinner.tsx"; const fmtRangeText = (pagination: Pagination, count: number): string => { if (count === 0) { @@ -201,7 +202,12 @@ export function SearchHeritageResultsContainer(): React.ReactElement { }; if (isLoading) { - return ; + return ( +
+ {header} + +
+ ); } if (error) {