diff --git a/frontend/src/pages/CollectionDetailPage/index.tsx b/frontend/src/pages/CollectionDetailPage/index.tsx
index 088932c..683eb1e 100644
--- a/frontend/src/pages/CollectionDetailPage/index.tsx
+++ b/frontend/src/pages/CollectionDetailPage/index.tsx
@@ -139,7 +139,9 @@ export default function CollectionDetailPage({ theme, previewMode, onUnauthorize
{collection.description && (
{collection.description}
)}
-
+
+
+
{items.length ? (
diff --git a/frontend/src/pages/ModelsPage/CategoryBanner.tsx b/frontend/src/pages/ModelsPage/CategoryBanner.tsx
new file mode 100644
index 0000000..f789921
--- /dev/null
+++ b/frontend/src/pages/ModelsPage/CategoryBanner.tsx
@@ -0,0 +1,35 @@
+import Box from "@mui/material/Box";
+import Typography from "@mui/material/Typography";
+import { alpha } from "@mui/material/styles";
+import { type Folder } from "../../api/folders";
+
+type Props = {
+ folder: Folder;
+};
+
+/** The rounded title+description banner shown above the grid when the selected category has
+ * admin-set meta text (Folder.metaTitle/metaDescription, edited via CategoryMetaDialog) --
+ * mirrors MakerWorld's category banner, a light rounded box with the category's display title
+ * and blurb sitting above its model grid. Models page only: a plain Collection has no
+ * analogous meta text today. Renders nothing without a title -- the description alone isn't
+ * worth a banner. */
+export default function CategoryBanner({ folder }: Props) {
+ if (!folder.meta_title) return null;
+ return (
+ alpha(theme.palette.primary.main, 0.08),
+ }}
+ >
+ {folder.meta_title}
+ {folder.meta_description && (
+
+ {folder.meta_description}
+
+ )}
+
+ );
+}
diff --git a/frontend/src/pages/ModelsPage/SortTabs.tsx b/frontend/src/pages/ModelsPage/SortTabs.tsx
index 32881fc..f0d4e9b 100644
--- a/frontend/src/pages/ModelsPage/SortTabs.tsx
+++ b/frontend/src/pages/ModelsPage/SortTabs.tsx
@@ -25,7 +25,8 @@ export default function SortTabs({ value, onChange }: Props) {
onClick={() => onChange(mode)}
sx={{
cursor: "pointer",
- fontWeight: value === mode ? 700 : 400,
+ fontSize: 14,
+ fontWeight: value === mode ? 700 : 500,
color: value === mode ? "primary.main" : "text.secondary",
"&:hover": { color: "primary.main" },
}}
diff --git a/frontend/src/pages/ModelsPage/index.tsx b/frontend/src/pages/ModelsPage/index.tsx
index a79eafe..bad6005 100644
--- a/frontend/src/pages/ModelsPage/index.tsx
+++ b/frontend/src/pages/ModelsPage/index.tsx
@@ -13,6 +13,7 @@ import { type ResolvedTheme } from "../../constants/settingsOptions";
import { usePageHeader } from "../../components/Layout/PageHeaderContext";
import { useInfiniteScroll } from "../../hooks/useInfiniteScroll";
import CategoriesPanel from "./CategoriesPanel";
+import CategoryBanner from "./CategoryBanner";
import ModelCard from "./ModelCard";
import SortTabs from "./SortTabs";
@@ -185,58 +186,65 @@ export default function ModelsPage({ folderId, onSelectFolder, foldersVersion, o
};
return (
-
-
-
-
-
-
- {loading ? (
-
-
-
- ) : items.length ? (
-
-
- {items.map(item => (
- setItems(prev => prev.filter(i => i.id !== deletedId))}
- onFavoriteChange={updated => setItems(prev => prev.map(i => (i.id === updated.id ? updated : i)))}
- onUnauthorized={onUnauthorized}
- />
- ))}
-
- {hasMore && (
-
- {loadingMore && (
-
-
- {t("models:grid.loadingMore")}
-
- )}
-
- )}
-
- ) : (
-
- {t("models:grid.empty")}
-
- )}
+
+
+
+
+
+
+ {selectedFolder?.meta_title && (
+
+
+
+ )}
+ {loading ? (
+
+
+
+ ) : items.length ? (
+
+
+ {items.map(item => (
+ setItems(prev => prev.filter(i => i.id !== deletedId))}
+ onFavoriteChange={updated => setItems(prev => prev.map(i => (i.id === updated.id ? updated : i)))}
+ onUnauthorized={onUnauthorized}
+ />
+ ))}
+
+ {hasMore && (
+
+ {loadingMore && (
+
+
+ {t("models:grid.loadingMore")}
+
+ )}
+
+ )}
+
+ ) : (
+
+ {t("models:grid.empty")}
+
+ )}
+
+
);
}