diff --git a/src/App.tsx b/src/App.tsx
index cfda0d9e9..37ab0b039 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -12,12 +12,14 @@ import Root from "@routes/root";
import { DeviceWidthProvider } from "@contexts/DeviceWidthContext";
import "./index.css";
-// Support
+import {
+ VersionUpdateNotificationProvider
+} from "@components/version-language-switcher/VersionUpdateNotificationContext";
+import { SiteWideNotificationProvider } from "@contexts/SiteWideNotificationContext";
import HomePage from "@routes/home";
// Design Tokens
-
import DesignTokensOverviewPage from "@routes/design-tokens/overview/Overview";
import BorderRadiusPage from "@routes/design-tokens/border-radius/BorderRadius";
import BorderWidthPage from "@routes/design-tokens/border-width/BorderWidth";
@@ -30,7 +32,6 @@ import SpacingPage from "@routes/design-tokens/spacing/Spacing";
import TypographyPage from "@routes/design-tokens/typography/Typography";
// Get Started
-
import DevelopersOverviewPage from "@routes/get-started/developers/DevelopersOverview";
import DevelopersSetupPage from "@routes/get-started/developers/DevelopersSetup";
import DevelopersTechnologiesPage from "@routes/get-started/developers/DevelopersTechnologies";
@@ -50,18 +51,17 @@ 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";
-import DateFormatPage from "@routes/content/DateFormat";
-import ErrorMessagesPage from "@routes/content/ErrorMessages";
-import HelperTextPage from "@routes/content/HelperText";
+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 { VersionFromUrlProvider } from "@contexts/VersionFromUrlContext.tsx";
import { ComponentsRouter, PatternsRouter } from "./versioned-router";
import ComponentNotFound from "@routes/not-found/NotFound.tsx";
-import { LanguageVersionProvider } from "@contexts/LanguageVersionContext.tsx";
+import { LanguageVersionContext, LanguageVersionProvider } from "@contexts/LanguageVersionContext.tsx";
import DevelopersUpgradePage from "@routes/get-started/developers/upgrade-guide/DevelopersUpgrade.tsx";
// Foundations Pages
@@ -80,7 +80,7 @@ const router = createBrowserRouter(
createRoutesFromElements(
}>
} />
- }>
+ } />
} errorElement={}>
} />
} />
@@ -95,9 +95,7 @@ const router = createBrowserRouter(
}>
} />
-
- } />
-
+ } />
} />
} />
@@ -107,6 +105,7 @@ const router = createBrowserRouter(
} />
} />
+
} />
@@ -122,11 +121,12 @@ const router = createBrowserRouter(
} />
} />
+
} />
} />
- }>
+ }>
} />
} />
} />
@@ -136,17 +136,19 @@ const router = createBrowserRouter(
} />
} />
} />
-
-
- }>
-
- } />
-
+ } />
} />
} />
} />
+ }>
+ } />
+ } />
+ } />
+ } />
+
+
}>
)
@@ -157,9 +159,17 @@ ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
-
+
+ {({ version }) => (
+
+
+
+
+
+ )}
+
-);
+);
\ No newline at end of file
diff --git a/src/components/version-language-switcher/HelpButton.tsx b/src/components/version-language-switcher/HelpButton.tsx
new file mode 100644
index 000000000..60eb0424a
--- /dev/null
+++ b/src/components/version-language-switcher/HelpButton.tsx
@@ -0,0 +1,38 @@
+import { useContext } from "react";
+import { useLocation } from "react-router-dom";
+import { GoabIconButton, GoabTooltip } from "@abgov/react-components";
+
+import { useVersionUpdateNotification } from "@components/version-language-switcher/VersionUpdateNotificationContext";
+import { useSiteWideNotification } from "@contexts/SiteWideNotificationContext";
+import { LanguageVersionContext } from "@contexts/LanguageVersionContext";
+
+export function HelpButton() {
+ const { reset: resetVersion } = useVersionUpdateNotification();
+ const { reset: resetSiteWideNotification } = useSiteWideNotification();
+ useContext(LanguageVersionContext);
+ const location = useLocation();
+
+ const handleHelpClick = () => {
+ const isComponentOrExamplePage =
+ location.pathname.startsWith("/components") || location.pathname.startsWith("/examples");
+
+ if (isComponentOrExamplePage) {
+ resetVersion();
+ } else {
+ resetSiteWideNotification();
+ }
+ };
+
+ return (
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/components/version-language-switcher/SiteWideNotification.tsx b/src/components/version-language-switcher/SiteWideNotification.tsx
new file mode 100644
index 000000000..e97172d45
--- /dev/null
+++ b/src/components/version-language-switcher/SiteWideNotification.tsx
@@ -0,0 +1,23 @@
+import { GoabNotification } from "@abgov/react-components";
+import { useLocation } from "react-router-dom";
+import { useSiteWideNotification } from "@contexts/SiteWideNotificationContext";
+import { MAX_CONTENT_WIDTH } from "../../global-constants.ts";
+
+export function SiteWideNotification() {
+ const { isDismissed, dismiss } = useSiteWideNotification();
+ const location = useLocation();
+
+ const isComponentOrExamplePage =
+ location.pathname.startsWith("/components") || location.pathname.startsWith("/examples");
+
+ if (isComponentOrExamplePage || isDismissed) return null;
+
+ return (
+
+ Select your development framework to see all code in your development language. Change framework and version at
+ the top right of the screen.
+
+ );
+}
+
+export default SiteWideNotification;
\ No newline at end of file
diff --git a/src/components/version-language-switcher/VersionLanguageSwitcher.tsx b/src/components/version-language-switcher/VersionLanguageSwitcher.tsx
index 843b86f3d..eab1f6c55 100644
--- a/src/components/version-language-switcher/VersionLanguageSwitcher.tsx
+++ b/src/components/version-language-switcher/VersionLanguageSwitcher.tsx
@@ -1,6 +1,6 @@
import {
GoabIcon,
- GoabPopover,
+ GoabPopover, GoabTooltip
} from "@abgov/react-components";
import {
ANGULAR_VERSIONS, getVersionedUrlPath, Language, LanguageVersion,
@@ -103,6 +103,7 @@ export const VersionLanguageSwitcher = () => {
return (
<>
+ openLanguagePopOver(e)}>
@@ -118,7 +119,9 @@ export const VersionLanguageSwitcher = () => {
}
>
+
+ openVersionPopOver(e)}>
@@ -133,7 +136,7 @@ export const VersionLanguageSwitcher = () => {
))}
>
-
+
>
);
}
diff --git a/src/components/version-language-switcher/VersionUpdateNotification.tsx b/src/components/version-language-switcher/VersionUpdateNotification.tsx
new file mode 100644
index 000000000..a6156a5a6
--- /dev/null
+++ b/src/components/version-language-switcher/VersionUpdateNotification.tsx
@@ -0,0 +1,48 @@
+import { useEffect } from "react";
+import { GoabNotification } from "@abgov/react-components";
+import { MAX_CONTENT_WIDTH } from "../../global-constants";
+import { useVersionUpdateNotification } from "./VersionUpdateNotificationContext";
+import type { LanguageVersion } from "@components/version-language-switcher/version-language-constants";
+
+interface VersionUpdateNotificationProps {
+ version: LanguageVersion;
+}
+
+export function VersionUpdateNotification({ version }: VersionUpdateNotificationProps) {
+ const { isDismissed, dismiss, oldLinkRef, newLinkRef } = useVersionUpdateNotification();
+
+ useEffect(() => {
+ const el = document.querySelector("goa-notification");
+ if (!el) return;
+
+ const handleDismiss = () => dismiss();
+ el.addEventListener("_dismiss", handleDismiss as EventListener);
+
+ return () => el.removeEventListener("_dismiss", handleDismiss as EventListener);
+ }, [dismiss]);
+
+ if (isDismissed) return null;
+
+ return (
+
+ {version === "old" ? (
+ <>
+ Support for the Long Term Support (LTS) version of the Design system will be available until September
+ 2025.{" "}
+
+ View the upgrade guide
+
+ >
+ ) : (
+ <>
+ Upgrading to the latest version of the design system?{" "}
+
+ View the upgrade guide
+
+ >
+ )}
+
+ );
+}
+
+export default VersionUpdateNotification;
\ No newline at end of file
diff --git a/src/components/version-language-switcher/VersionUpdateNotificationContext.tsx b/src/components/version-language-switcher/VersionUpdateNotificationContext.tsx
new file mode 100644
index 000000000..315a68811
--- /dev/null
+++ b/src/components/version-language-switcher/VersionUpdateNotificationContext.tsx
@@ -0,0 +1,55 @@
+import { createContext, useContext, useEffect, useRef, useState } from "react";
+import type { LanguageVersion } from "@components/version-language-switcher/version-language-constants";
+
+interface VersionUpdateNotificationContextType {
+ isDismissed: boolean;
+ dismiss: () => void;
+ reset: () => void;
+ oldLinkRef: React.RefObject;
+ newLinkRef: React.RefObject;
+}
+
+const VersionUpdateNotificationContext = createContext(undefined);
+
+export const VersionUpdateNotificationProvider = ({
+ version,
+ children
+ }: {
+ version: LanguageVersion;
+ children: React.ReactNode;
+}) => {
+ const storageKey = `versionUpdateNotificationDismissed-${version}`;
+ const [isDismissed, setIsDismissed] = useState(false);
+
+ const oldLinkRef = useRef(null);
+ const newLinkRef = useRef(null);
+
+ useEffect(() => {
+ const storedValue = localStorage.getItem(storageKey);
+ setIsDismissed(storedValue === "true");
+ }, [version]);
+
+ const dismiss = () => {
+ localStorage.setItem(storageKey, "true");
+ setIsDismissed(true);
+ };
+
+ const reset = () => {
+ localStorage.removeItem(storageKey);
+ setIsDismissed(false);
+ };
+
+ return (
+
+ {children}
+
+ );
+};
+
+export const useVersionUpdateNotification = () => {
+ const context = useContext(VersionUpdateNotificationContext);
+ if (!context) {
+ throw new Error("useVersionUpdateNotification must be used within VersionUpdateNotificationProvider");
+ }
+ return context;
+};
\ No newline at end of file
diff --git a/src/contexts/LanguageVersionContext.tsx b/src/contexts/LanguageVersionContext.tsx
index 212edbf4f..6efeaf7fc 100644
--- a/src/contexts/LanguageVersionContext.tsx
+++ b/src/contexts/LanguageVersionContext.tsx
@@ -7,7 +7,7 @@ import {
} from "@components/version-language-switcher/version-language-constants.ts";
import { DEFAULT_LANGUAGE, DEFAULT_VERSION } from "../global-constants";
-interface LanguageVersionContextProps {
+export interface LanguageVersionContextProps {
language: Language;
version: LanguageVersion;
setLanguage: (lang: Language) => void;
diff --git a/src/contexts/SiteWideNotificationContext.tsx b/src/contexts/SiteWideNotificationContext.tsx
new file mode 100644
index 000000000..ff6ac6c7e
--- /dev/null
+++ b/src/contexts/SiteWideNotificationContext.tsx
@@ -0,0 +1,39 @@
+import { createContext, useContext, useState } from "react";
+
+interface SiteWideNotificationContextType {
+ isDismissed: boolean;
+ dismiss: () => void;
+ reset: () => void;
+}
+
+const SiteWideNotificationContext = createContext(undefined);
+
+export const SiteWideNotificationProvider = ({ children }: { children: React.ReactNode }) => {
+ const [isDismissed, setIsDismissed] = useState(() => {
+ const stored = localStorage.getItem("siteWideDismissed");
+ return stored === "true";
+ });
+ const dismiss = () => {
+ localStorage.setItem("siteWideDismissed", "true");
+ setIsDismissed(true);
+ };
+
+ const reset = () => {
+ localStorage.removeItem("siteWideDismissed");
+ setIsDismissed(false);
+ };
+
+ return (
+
+ {children}
+
+ );
+};
+
+export const useSiteWideNotification = () => {
+ const context = useContext(SiteWideNotificationContext);
+ if (!context) {
+ throw new Error("useSiteWideNotification must be used within SiteWideNotificationProvider");
+ }
+ return context;
+};
\ No newline at end of file
diff --git a/src/routes/components/Components.tsx b/src/routes/components/Components.tsx
index 7fa5fcc0f..197fe1405 100644
--- a/src/routes/components/Components.tsx
+++ b/src/routes/components/Components.tsx
@@ -1,7 +1,6 @@
import {
GoabBadge,
GoabBlock,
- GoabNotification,
GoabSideMenu,
GoabSideMenuGroup,
GoabSpacer
@@ -11,7 +10,7 @@ import { SupportInfo } from "@components/support-info/SupportInfo.tsx";
import { useContext } from "react";
import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx";
import { getVersionedUrlPath, ANGULAR_VERSIONS, REACT_VERSIONS } from "@components/version-language-switcher/version-language-constants.ts";
-import { MAX_CONTENT_WIDTH } from "../../global-constants.ts";
+
export function Components() {
const { language, version } = useContext(LanguageVersionContext);
@@ -39,18 +38,6 @@ export function Components() {
return (
<>
- {version === "old" && (
-
- Support for the Long Term Support (LTS) version of the Design system will be available until September
- 2025. View the upgrade guide
-
- )}
- {version === "new" && (
-
- Upgrading to the latest version of the design system?{" "}
- View the upgrade guide
-
- )}
diff --git a/src/routes/content/ErrorMessages.tsx b/src/routes/content/ErrorMessages.tsx
index 4d3ddd312..3a46c7525 100644
--- a/src/routes/content/ErrorMessages.tsx
+++ b/src/routes/content/ErrorMessages.tsx
@@ -46,8 +46,7 @@ export default function ErrorMessagesPage() {
diff --git a/src/routes/root.tsx b/src/routes/root.tsx
index 7102b8d85..fdc7fc4b0 100644
--- a/src/routes/root.tsx
+++ b/src/routes/root.tsx
@@ -3,20 +3,28 @@ import {
GoabAppFooterMetaSection,
GoabAppFooterNavSection,
GoabAppHeader,
- GoabMicrositeHeader, GoabNotification,
+ GoabMicrositeHeader,
GoabOneColumnLayout
} from "@abgov/react-components";
import { useEffect, useState } from "react";
-import { Link, Outlet } from "react-router-dom";
-import Cookies from "js-cookie";
+import { Link, Outlet, useLocation } from "react-router-dom";
import "./root.css";
-import { useLocation } from "react-router-dom";
import {
MAX_CONTENT_WIDTH,
} from "../global-constants.ts";
-import { VersionLanguageSwitcher } from "@components/version-language-switcher/VersionLanguageSwitcher.tsx";
+
+
+import VersionUpdateNotification from "@components/version-language-switcher/VersionUpdateNotification";
+import { HelpButton } from "@components/version-language-switcher/HelpButton";
+import {
+ VersionLanguageSwitcher
+} from "@components/version-language-switcher/VersionLanguageSwitcher";
+import { LanguageVersionContext } from "@contexts/LanguageVersionContext";
+import { useContext } from "react";
+import SiteWideNotification from "@components/version-language-switcher/SiteWideNotification";
+
function ScrollToTop() {
const { pathname } = useLocation();
@@ -29,7 +37,10 @@ function ScrollToTop() {
}
export default function Root() {
- const isFirstVisit = Cookies.get("hasVisited");
+ const { version } = useContext(LanguageVersionContext);
+ const location = useLocation();
+ const showNotification =
+ location.pathname.startsWith("/components") || location.pathname.startsWith("/examples");
const [visible, setVisibility] = useState(false);
@@ -39,12 +50,6 @@ export default function Root() {
}, 50);
});
- useEffect(() => {
- setTimeout(() => {
- Cookies.set("hasVisited", "true", {expires: 3650}); // increase the time everytime ppl land on so it won't expire
- }, 600); // update later
- }, []);
-
return (
@@ -54,9 +59,14 @@ export default function Root() {
type={"live"}
feedbackUrl="https://forms.microsoft.com/r/8Zp7zSJS6W"
maxContentWidth={MAX_CONTENT_WIDTH}
- version={}
- />
-
+ version={
+ <>
+
+
+ >
+ } />
+
Get started
Foundations
Patterns
@@ -65,13 +75,10 @@ export default function Root() {
Content
Get support
-
-
- {isFirstVisit == null &&
- Select your development framework to see all code in your development languages. You can change this in the top right of the screen.
- }
-
+ {showNotification && }
+
+