feat: Extracted catSlug to shared utility; added category accent border…
- "frontend/src/utils/catSlug.ts" - "frontend/src/pages/TopicsBrowse.tsx" - "frontend/src/pages/SubTopicPage.tsx" - "frontend/src/pages/SearchResults.tsx" - "frontend/src/App.css" GSD-Task: S03/T01
This commit is contained in:
parent
c481bafc7b
commit
cf0205bd5c
6 changed files with 26 additions and 9 deletions
|
|
@ -2334,6 +2334,8 @@ a.app-footer__repo:hover {
|
||||||
max-width: 56rem;
|
max-width: 56rem;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 1rem 0;
|
padding: 1rem 0;
|
||||||
|
border-left: 4px solid transparent;
|
||||||
|
padding-left: 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.subtopic-page__title {
|
.subtopic-page__title {
|
||||||
|
|
@ -2347,6 +2349,13 @@ a.app-footer__repo:hover {
|
||||||
font-size: 0.95rem;
|
font-size: 0.95rem;
|
||||||
color: var(--color-text-secondary);
|
color: var(--color-text-secondary);
|
||||||
margin: 0 0 2rem;
|
margin: 0 0 2rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtopic-page__subtitle-sep {
|
||||||
|
color: var(--color-text-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
.subtopic-groups {
|
.subtopic-groups {
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
import { useCallback, useEffect, useRef, useState } from "react";
|
import { useCallback, useEffect, useRef, useState } from "react";
|
||||||
import { Link, useSearchParams, useNavigate } from "react-router-dom";
|
import { Link, useSearchParams, useNavigate } from "react-router-dom";
|
||||||
import { searchApi, type SearchResultItem } from "../api/public-client";
|
import { searchApi, type SearchResultItem } from "../api/public-client";
|
||||||
|
import { catSlug } from "../utils/catSlug";
|
||||||
|
|
||||||
export default function SearchResults() {
|
export default function SearchResults() {
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
|
|
@ -167,7 +168,7 @@ function SearchResultCard({ item }: { item: SearchResultItem }) {
|
||||||
{item.topic_category && (
|
{item.topic_category && (
|
||||||
<>
|
<>
|
||||||
<span className="queue-card__separator">·</span>
|
<span className="queue-card__separator">·</span>
|
||||||
<span>{item.topic_category}</span>
|
<span className={`badge badge--cat-${catSlug(item.topic_category)}`}>{item.topic_category}</span>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{item.topic_tags.length > 0 && (
|
{item.topic_tags.length > 0 && (
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import {
|
||||||
fetchSubTopicTechniques,
|
fetchSubTopicTechniques,
|
||||||
type TechniqueListItem,
|
type TechniqueListItem,
|
||||||
} from "../api/public-client";
|
} from "../api/public-client";
|
||||||
|
import { catSlug } from "../utils/catSlug";
|
||||||
|
|
||||||
/** Convert a URL slug to a display name: replace hyphens with spaces, title-case. */
|
/** Convert a URL slug to a display name: replace hyphens with spaces, title-case. */
|
||||||
function slugToDisplayName(slug: string): string {
|
function slugToDisplayName(slug: string): string {
|
||||||
|
|
@ -91,9 +92,13 @@ export default function SubTopicPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const groups = groupByCreator(techniques);
|
const groups = groupByCreator(techniques);
|
||||||
|
const slug = category ? catSlug(categoryDisplay) : "";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="subtopic-page">
|
<div
|
||||||
|
className="subtopic-page"
|
||||||
|
style={slug ? { borderLeftColor: `var(--color-badge-cat-${slug}-text)` } : undefined}
|
||||||
|
>
|
||||||
{/* Breadcrumbs */}
|
{/* Breadcrumbs */}
|
||||||
<nav className="breadcrumbs" aria-label="Breadcrumb">
|
<nav className="breadcrumbs" aria-label="Breadcrumb">
|
||||||
<Link to="/topics" className="breadcrumbs__link">Topics</Link>
|
<Link to="/topics" className="breadcrumbs__link">Topics</Link>
|
||||||
|
|
@ -105,7 +110,9 @@ export default function SubTopicPage() {
|
||||||
|
|
||||||
<h2 className="subtopic-page__title">{subtopicDisplay}</h2>
|
<h2 className="subtopic-page__title">{subtopicDisplay}</h2>
|
||||||
<p className="subtopic-page__subtitle">
|
<p className="subtopic-page__subtitle">
|
||||||
{techniques.length} technique{techniques.length !== 1 ? "s" : ""} in {categoryDisplay}
|
<span className={`badge badge--cat-${slug}`}>{categoryDisplay}</span>
|
||||||
|
<span className="subtopic-page__subtitle-sep">·</span>
|
||||||
|
{techniques.length} technique{techniques.length !== 1 ? "s" : ""}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{techniques.length === 0 ? (
|
{techniques.length === 0 ? (
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,7 @@ import { useEffect, useState } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { fetchTopics, type TopicCategory } from "../api/public-client";
|
import { fetchTopics, type TopicCategory } from "../api/public-client";
|
||||||
import { CATEGORY_ICON } from "../components/CategoryIcons";
|
import { CATEGORY_ICON } from "../components/CategoryIcons";
|
||||||
|
import { catSlug } from "../utils/catSlug";
|
||||||
/** Derive the badge CSS slug from a category name. */
|
|
||||||
function catSlug(name: string): string {
|
|
||||||
return name.toLowerCase().replace(/\s+/g, "-");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
4
frontend/src/utils/catSlug.ts
Normal file
4
frontend/src/utils/catSlug.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
/** Derive the badge CSS slug from a category name. */
|
||||||
|
export function catSlug(name: string): string {
|
||||||
|
return name.toLowerCase().replace(/\s+/g, "-");
|
||||||
|
}
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"root":["./src/App.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/api/public-client.ts","./src/components/AdminDropdown.tsx","./src/components/AppFooter.tsx","./src/components/CategoryIcons.tsx","./src/components/CopyLinkButton.tsx","./src/components/CreatorAvatar.tsx","./src/components/ReportIssueModal.tsx","./src/pages/About.tsx","./src/pages/AdminPipeline.tsx","./src/pages/AdminReports.tsx","./src/pages/CreatorDetail.tsx","./src/pages/CreatorsBrowse.tsx","./src/pages/Home.tsx","./src/pages/SearchResults.tsx","./src/pages/SubTopicPage.tsx","./src/pages/TechniquePage.tsx","./src/pages/TopicsBrowse.tsx"],"version":"5.6.3"}
|
{"root":["./src/App.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/api/public-client.ts","./src/components/AdminDropdown.tsx","./src/components/AppFooter.tsx","./src/components/CategoryIcons.tsx","./src/components/CopyLinkButton.tsx","./src/components/CreatorAvatar.tsx","./src/components/ReportIssueModal.tsx","./src/pages/About.tsx","./src/pages/AdminPipeline.tsx","./src/pages/AdminReports.tsx","./src/pages/CreatorDetail.tsx","./src/pages/CreatorsBrowse.tsx","./src/pages/Home.tsx","./src/pages/SearchResults.tsx","./src/pages/SubTopicPage.tsx","./src/pages/TechniquePage.tsx","./src/pages/TopicsBrowse.tsx","./src/utils/catSlug.ts"],"version":"5.6.3"}
|
||||||
Loading…
Add table
Reference in a new issue