Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
14bdf5d
feat(#2715): spike pull information from github
twjeffery May 13, 2025
3d89657
add a shared function for GitHub queries
bdfranck May 13, 2025
68ae5c6
Turn Patterns into Examples page
bdfranck May 14, 2025
cb0e3ff
updated Github query for examples page
twjeffery May 14, 2025
6cda6f4
add a shared function for fetching metadata
bdfranck May 14, 2025
09de96c
change /patterns route to /examples and add birthday example
bdfranck May 16, 2025
38392ad
add loading state to examples and components cards
bdfranck May 21, 2025
351c890
feat: added template page for examples files, and added integration t…
twjeffery May 23, 2025
11310e4
chore: renamed and moved all examples files
twjeffery May 28, 2025
8fb3f8d
chore: renamed and moved all examples files
twjeffery May 28, 2025
de16b38
build fix
twjeffery May 28, 2025
bb63c9e
update to navigation, combining content guidelines to foundations sec…
twjeffery May 28, 2025
b640916
update side menu to show pattern documentation
twjeffery May 30, 2025
67f990d
fix to home page content order, footer, and site max width
twjeffery May 30, 2025
322f8ac
update side menu to show form pattern documentation
twjeffery May 30, 2025
b4cdf9f
fix to home page content order, footer, and site max width
twjeffery May 30, 2025
fbcf8e1
Merge remote-tracking branch 'origin/thomasjeffery/examples-page' int…
twjeffery May 30, 2025
4fa6f1a
zebra striping on table
twjeffery May 30, 2025
aa43d64
added layout page to examples, skeleton loading for table, additional…
twjeffery Jun 3, 2025
517664d
v1 for filtering examples
twjeffery Jun 3, 2025
ae59263
cleanup of filter and search to not hit rate limit as quickly, cleanu…
twjeffery Jun 3, 2025
7ee080b
Trigger Netlify rebuild
twjeffery Jun 3, 2025
120da84
Refactor to include local caching
twjeffery Jul 7, 2025
03c42ac
Refactor to include local caching and resolve conflicts
twjeffery Jul 7, 2025
d36f5d2
Add a 24 hour expiration for cache
bdfranck Jul 7, 2025
1e3f6c3
Fix issue with outdated type
bdfranck Jul 7, 2025
f8b78cd
Remove console logs
bdfranck Jul 8, 2025
c663990
Fetch all issue counts in a single query
bdfranck Jul 8, 2025
deeae4b
Remove duplicate useEffect function
bdfranck Jul 8, 2025
d1be8f2
Use cached issue counts on single component page
bdfranck Jul 8, 2025
1d4b0f2
Use React Router link for "back" action on single example
bdfranck Jul 9, 2025
0faaa54
Updated all images, fixed examples, fixed header spacing on foundatio…
twjeffery Jul 14, 2025
9bda0fe
Updated Tab name for card view to align with components section
twjeffery Jul 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"octokit": "^4.0.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.13.0"
"react-router-dom": "^6.13.0",
"use-debounce": "^10.0.4"
},
"devDependencies": {
"@types/js-cookie": "^3.0.6",
Expand Down
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
Binary file added public/images/example-thumbnails/card-grid.png
Binary file added public/images/example-thumbnails/public-form.png
Binary file added public/images/example-thumbnails/result-page.png
Binary file added public/images/example-thumbnails/search.png
Binary file added public/images/example-thumbnails/start-page.png
36 changes: 20 additions & 16 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,18 @@ import ReportBugPage from "@routes/get-started/ReportBug";
import RoadmapPage from "@routes/get-started/Roadmap";
import SupportedBrowsersPage from "@routes/get-started/developers/SupportedBrowsers";
import UxDesignerPage from "@routes/get-started/designers/UxDesigner";
import { LtsPolicyPage } from "@routes/get-started/LtsPolicyPage.tsx";

// Content Pages
import ContentLayout from "@routes/content/ContentLayout";
import CapitalizationPage from "@routes/content/Capitalization.tsx";
import DateFormatPage from "@routes/content/DateFormat.tsx";
import ErrorMessagesPage from "@routes/content/ErrorMessages.tsx";
import HelperTextPage from "@routes/content/HelperText.tsx";
import UserExperienceGuidelinesPage from "@routes/get-started/UserExperienceGuidelines";
import { LtsPolicyPage } from "@routes/get-started/LtsPolicyPage.tsx";

// Examples Pages
import { VersionFromUrlProvider } from "@contexts/VersionFromUrlContext.tsx";
import { ComponentsRouter, PatternsRouter } from "./versioned-router";
import { ComponentsRouter } from "./versioned-router";
import ExamplePageTemplate from "@routes/examples/ExamplePageTemplate";
import ComponentNotFound from "@routes/not-found/NotFound.tsx";
import { LanguageVersionContext, LanguageVersionProvider } from "@contexts/LanguageVersionContext.tsx";
import DevelopersUpgradePage from "@routes/get-started/developers/upgrade-guide/DevelopersUpgrade.tsx";
import ExamplesLayout from "@routes/examples/ExamplesLayout.tsx";
import ExamplesOverviewPage from "@routes/examples/ExamplesOverview.tsx";

// Foundations Pages
import FoundationsLayout from "@routes/foundations/FoundationsLayout";
Expand All @@ -75,12 +72,20 @@ import ImagesPage from "@routes/foundations/Photography";
import LogoPage from "@routes/foundations/Logo";
import FoundationsTypographyPage from "@routes/foundations/Typography";
import FoundationsLayoutPage from "@routes/foundations/Layout";
import CapitalizationPage from "@routes/foundations/Capitalization.tsx";
import DateFormatPage from "@routes/foundations/DateFormat.tsx";
import ErrorMessagesPage from "@routes/foundations/ErrorMessages.tsx";
import HelperTextPage from "@routes/foundations/HelperText.tsx";

const router = createBrowserRouter(
createRoutesFromElements(
<Route path="/" element={<Root />}>
<Route path="/" element={<HomePage />} />

{/* Component Pages */}
<Route path="/components/*" element={<ComponentsRouter />} />

{/* Design tokens Pages */}
<Route path="design-tokens" element={<DesignTokens />} errorElement={<ComponentNotFound />}>
<Route index element={<DesignTokensOverviewPage />} />
<Route path="border-width" element={<BorderWidthPage />} />
Expand All @@ -93,6 +98,7 @@ const router = createBrowserRouter(
<Route path="typography" element={<TypographyPage />} />
</Route>

{/* Get started Pages */}
<Route path="get-started" element={<GetStartedLayout />}>
<Route index element={<GetStartedOverviewPage />} />
<Route path="designers" element={<UxDesignerPage />} />
Expand Down Expand Up @@ -126,6 +132,7 @@ const router = createBrowserRouter(
<Route path="user-experience-guidelines" element={<UserExperienceGuidelinesPage />} />
</Route>

{/* Foundations Pages */}
<Route path="foundations" element={<FoundationsLayout />}>
<Route index element={<DesignAtGoAPage />} />
<Route path="accessibility" element={<AccessibilityPage />} />
Expand All @@ -142,14 +149,11 @@ const router = createBrowserRouter(
<Route path="helper-text" element={<HelperTextPage />} />
</Route>

<Route path="content" element={<ContentLayout />}>
<Route path="/content/capitalization" element={<CapitalizationPage />} />
<Route path="/content/date-format" element={<DateFormatPage />} />
<Route path="/content/error-messages" element={<ErrorMessagesPage />} />
<Route path="/content/helper-text" element={<HelperTextPage />} />
{/* Examples Pages */}
<Route path="/examples" element={<ExamplesLayout />}>
<Route index element={<ExamplesOverviewPage />} />
</Route>

<Route path="/patterns/*" element={<PatternsRouter />}></Route>
<Route path="/examples/:slug" element={<ExamplePageTemplate />} />
</Route>
)
);
Expand Down
1 change: 0 additions & 1 deletion src/components/component-card/ComponentCard.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
}

.card-content a {
font-size: var(--goa-font-size-7);
display: flex;
}

Expand Down
89 changes: 56 additions & 33 deletions src/components/component-card/ComponentCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useState, useEffect } from "react";
export type ComponentStatus = "Published" | "Not Published" | "In Progress";

// Define allowed group options as a union type
type Group =
export type Group =
| "Content layout"
| "Feedback and alerts"
| "Inputs and actions"
Expand All @@ -17,50 +17,58 @@ import { useContext } from "react";
import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx";
import { ANGULAR_VERSIONS, REACT_VERSIONS } from "@components/version-language-switcher/version-language-constants.ts";

export interface Props {
export interface ComponentCardProps {
name: string;
description: string;
groups: Group[]; // Use the Group type here
tags?: string[];
status: ComponentStatus;
githubLink?: string;
openIssues?: number;
isNew?: boolean; // if true, show a badge on the component card to let users know the component is available in the latest version
designSystemUrl?: string;
designComponentFigmaUrl?: string;
designContributionFigmaUrl?: string;
imageFolder?: "component-thumbnails" | "example-thumbnails";
}

function dasherize(value: string): string {
return value.split(" ").join("-");
return value.toLowerCase().split(" ").join("-");
}

export function ComponentCard(props: Props) {
const [imageUrl, setImageUrl] = useState(`/images/${dasherize(props.name)}.png`);
function isRelativeUrl(url?: string): boolean {
return url !== undefined && !/^https?:\/\//i.test(url);
}

export function ComponentCard(props: ComponentCardProps) {
const folder = props.imageFolder ?? "components";
const [imageUrl, setImageUrl] = useState(`/images/${folder}/${dasherize(props.name)}.png`);

useEffect(() => {
const testImage = new Image();
testImage.src = imageUrl;
testImage.onerror = () => setImageUrl("/images/not-yet-available.png");
testImage.onerror = () => setImageUrl("/images/component-thumbnails/not-yet-available.png");
}, [imageUrl]);

const getBadgeType = (status: ComponentStatus) => {
switch (status) {
case "Published":
return null; // No badge for "Published"
case "Not Published":
return "information";
return "light";
case "In Progress":
return "important";
default:
return "information"; // Fallback for unknown status
}
};

const badgeType = getBadgeType(props.status);

getBadgeType(props.status);
const {language} = useContext(LanguageVersionContext);
return (

<div className="card">
{props.status === "Published" ? (
<Link to={toKebabCase(props.name)} tabIndex={-1}>
<Link to={isRelativeUrl(props.designSystemUrl) ? props.designSystemUrl! : toKebabCase(props.name)}
tabIndex={-1}>
<div
className="card-image"
style={{ backgroundImage: `url(${imageUrl})` }}
Expand All @@ -69,44 +77,59 @@ export function ComponentCard(props: Props) {
) : (
<div
className="card-image"
tabIndex={-1}
style={{ backgroundImage: `url(${imageUrl})` }}
/>
></div>
)}
<div className="card-content">
<div className="card-title-with-badge">
{badgeType && <GoabBadge mt="none" mb="m" type={badgeType} content={props.status} />}

{props.isNew && (
<GoabBadge
type="important"
mt="l"
content={
"Available in " +
(language === "angular"
? ANGULAR_VERSIONS.NEW.label.substring(0, 2).toUpperCase()
: REACT_VERSIONS.NEW.label.substring(0, 2).toUpperCase())
}
/>
)}
{props.status !== "Published" && (
<GoabBadge
mb="m"
type={
props.status === "In Progress"
? "important"
: "information"
}
content={props.status}
/>
)}
<h3 style={{ marginTop: 0, marginBottom: 12 }}>
{props.status === "Published" ? (

<Link to={toKebabCase(props.name)}>
{`${props.name.substring(0, 1).toUpperCase()}${props.name.substring(1)}`}
</Link>

<Link
to={isRelativeUrl(props.designSystemUrl) ? props.designSystemUrl! : toKebabCase(props.name)}>{props.name}</Link>
) : (

<GoabText size="body-l" mt="none" mb="none">
{`${props.name.substring(0, 1).toUpperCase()}${props.name.substring(1)}`}
</GoabText>

props.name
)}
</div>
<GoabText size="body-m" mt="m" mb="none">
</h3>
<GoabText size="body-m" mb="s">
{props.description}
</GoabText>


{props.status !== "Published" && props.githubLink && (
<GoabText size="body-s">
<GoabText tag="div" mt="m" size="body-s">
<a
href={props.githubLink}
target="_blank"
rel="noopener noreferrer"
className="github-link"
>
View issues{typeof props.openIssues === 'number' && ` (${props.openIssues})`}
{props.imageFolder === "example-thumbnails" ? "View issue" : "View open issues"}
{props.imageFolder === "example-thumbnails" ? "" : props.openIssues !== undefined ? ` (${props.openIssues})` : ""}
</a>
</GoabText>
)}
{props.isNew && <GoabBadge type="important" mt="l" content={"Available in " + (language === "angular" ? ANGULAR_VERSIONS.NEW.label.substring(0,2).toUpperCase() : REACT_VERSIONS.NEW.label.substring(0,2).toUpperCase())}/>}

</div>
</div>
);
Expand Down
6 changes: 4 additions & 2 deletions src/components/component-header/ComponentHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { GoabBadge, GoabBlock, GoabText } from "@abgov/react-components";
import "./ComponentHeader.css";
import { Link } from "react-router-dom";
import { useEffect, useState } from "react";
import { toSentenceCase, fetchIssueCount } from "../../utils";
import { toSentenceCase, fetchAllIssueCounts, fetchComponentMetadataFromProject } from "../../utils";

export enum Category {
CONTENT_AND_LAYOUT = "Content and layout",
Expand All @@ -29,7 +29,9 @@ export const ComponentHeader: React.FC<Props> = (props) => {

const getCount = async () => {
const label = toSentenceCase(props.githubLink!);
const count = await fetchIssueCount(label);
const metadata = await fetchComponentMetadataFromProject();
const Allcounts = await fetchAllIssueCounts("Components", metadata);
const count = Allcounts[label] || 0;
setIssueCount(count);
};

Expand Down
40 changes: 40 additions & 0 deletions src/components/example-card/ExampleCard.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
.card {
border: 1px solid var(--goa-color-greyscale-200);
border-radius: 4px;
overflow: hidden;
}

.card-image {
width: 100%;
height: 200px;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
border-bottom: 1px solid var(--goa-color-greyscale-200);
background-color: #F8F8F8;
}

.card-content {
padding: 1.5rem;
}

.card-content a {
display: flex;
}

.card-content a.github-link {
font: var(--goa-typography-body-s);
margin-top: 1rem;
margin-bottom: 0;
}

.card-content a:focus {
outline: none;
box-shadow: none;
background: none;
}

.card:focus-within {
outline: 3px solid var(--goa-color-interactive-focus);
border-radius: 4px;
}
Loading