diff --git a/src/components/AnnouncementBanner/index.scss b/src/components/AnnouncementBanner/index.scss
new file mode 100644
index 000000000..bff42281f
--- /dev/null
+++ b/src/components/AnnouncementBanner/index.scss
@@ -0,0 +1,38 @@
+.announcementBanner {
+ width: 100%;
+ border-bottom: 1px solid var(--border-color);
+ background: #dce5f9;
+ color: var(--primary-color);
+}
+
+.announcementBanner__inner {
+ display: flex;
+ gap: 12px;
+ align-items: center;
+ justify-content: center;
+ padding-top: 10px;
+ padding-bottom: 10px;
+}
+
+.announcementBanner__content {
+ font-size: 15px;
+ line-height: 21px;
+ text-align: center;
+ flex: 1 1 auto;
+ font-weight: 500;
+ color: #4b5563;
+}
+
+.announcementBanner__link {
+ color: #1a73e8;
+ text-decoration: underline;
+ font-size: 15px;
+}
+
+@media screen and (max-width: 767px) {
+ .announcementBanner__inner {
+ flex-direction: column;
+ align-items: flex-start;
+ }
+}
+
diff --git a/src/components/AnnouncementBanner/index.tsx b/src/components/AnnouncementBanner/index.tsx
new file mode 100644
index 000000000..e88c22e38
--- /dev/null
+++ b/src/components/AnnouncementBanner/index.tsx
@@ -0,0 +1,24 @@
+import React from 'react';
+import './index.scss';
+
+type AnnouncementBannerProps = {
+ enabled?: boolean;
+ message: React.ReactNode;
+};
+
+const AnnouncementBanner = (props: AnnouncementBannerProps) => {
+ const { enabled = true, message } = props;
+
+ if (!enabled) return null;
+
+ return (
+
+ );
+};
+
+export default AnnouncementBanner;
+
diff --git a/src/components/DevDocTemplate/index.tsx b/src/components/DevDocTemplate/index.tsx
index be6ea8441..81fc0acff 100644
--- a/src/components/DevDocTemplate/index.tsx
+++ b/src/components/DevDocTemplate/index.tsx
@@ -23,6 +23,7 @@ import { getAlgoliaIndex } from '../../configs/algolia-search-config';
import RenderPlayGround from './playGround/RESTAPI';
import GraphQLPlayGround from './playGround/GraphQL';
import { AskDocs } from './askDocs';
+import AnnouncementBanner from '../AnnouncementBanner';
import {
TS_HOST_PARAM,
TS_ORIGIN_PARAM,
@@ -34,6 +35,7 @@ import {
DEFAULT_PREVIEW_HOST,
DEFAULT_APP_ROOT,
HOME_PAGE_ID,
+ HOME_ANNOUNCEMENT_BANNER,
CUSTOM_PAGE_ID,
BUILD_ENVS,
VERSION_DROPDOWN,
@@ -487,6 +489,36 @@ const DevDocTemplate: FC = (props) => {
return cName;
};
+ const getCloudLatestVersion = () => {
+ const cloudLatest = VERSION_DROPDOWN?.find(
+ (v) => v?.subLabel && v.subLabel.toLowerCase().includes('cloud (latest)'),
+ );
+ return cloudLatest?.label;
+ };
+
+ const extractVersionString = (text: string | undefined | null) => {
+ if (!text) return undefined;
+ // Matches versions like 26.2.0.cl or 10.15.0.cl / 10.10.0.sw
+ const match = text.match(/\b\d+\.\d+\.\d+\.(?:cl|sw)\b/i);
+ return match?.[0]?.toLowerCase();
+ };
+
+ const shouldShowAnnouncementBanner = () => {
+ if (!isPublicSiteOpen) return false;
+ if (!HOME_ANNOUNCEMENT_BANNER?.enabled) return false;
+
+ const cloudLatest = extractVersionString(getCloudLatestVersion());
+ const bannerVersion =
+ extractVersionString(HOME_ANNOUNCEMENT_BANNER?.linkText) ||
+ extractVersionString(HOME_ANNOUNCEMENT_BANNER?.message);
+
+ // Only hide when we can confidently compare and they match.
+ if (cloudLatest && bannerVersion && cloudLatest === bannerVersion) return false;
+ return true;
+ };
+
+ const isExternalLink = (href?: string) => /^https?:\/\//i.test(href || '');
+
return (
<>
@@ -511,6 +543,44 @@ const DevDocTemplate: FC = (props) => {
: { height: '0px' }
}
>
+ {shouldShowAnnouncementBanner() && (
+
+ {HOME_ANNOUNCEMENT_BANNER?.linkHref &&
+ HOME_ANNOUNCEMENT_BANNER?.linkText && (
+
+ {HOME_ANNOUNCEMENT_BANNER.linkText}
+
+ )}
+ {(HOME_ANNOUNCEMENT_BANNER?.linkHref &&
+ HOME_ANNOUNCEMENT_BANNER?.linkText) && ' '}
+ {HOME_ANNOUNCEMENT_BANNER?.message ||
+ (VERSION_DROPDOWN?.[0]?.label
+ ? `Version ${VERSION_DROPDOWN[0].label} is now available!`
+ : 'A new version is now available!')}
+
+ }
+ />
+ )}
}
diff --git a/src/configs/doc-configs.js b/src/configs/doc-configs.js
index 783645484..fddb5524d 100644
--- a/src/configs/doc-configs.js
+++ b/src/configs/doc-configs.js
@@ -13,6 +13,18 @@ module.exports = {
NOT_FOUND_PAGE_ID: '404-error',
HOME_PAGE_ID: 'introduction',
NOT_FOUND_GO_HOME_PAGE_ID: 'introduction',
+ HOME_ANNOUNCEMENT_BANNER: {
+ enabled: true,
+ message:
+ 'is now available. Read about the new features and enhancements.',
+ // Swap this between:
+ // - Pre-GA: release-specific URL (full http(s) URL), ex:
+ // 'https://developers.thoughtspot.com/docs/26.2.0.cl?pageid=whats-new'
+ // - GA: ' /docs/whats-new'
+ //linkHref: '/docs/whats-new',
+ linkHref: '/docs/26.2.0.cl?pageid=whats-new',
+ linkText: 'Version 26.2.0.cl',
+ },
TYPE_DOC_PREFIX: 'typedoc',
DEFAULT_HOST: 'https://try-everywhere.thoughtspot.cloud',
DEFAULT_PREVIEW_HOST: 'https://try-everywhere.thoughtspot.cloud/v2',
@@ -63,7 +75,12 @@ module.exports = {
subLabel: 'Software',
iframeUrl: 'https://visual-embed-sdk-10-1.vercel.app/docs/',
},
-
+ {
+ label: '26.2.0.cl',
+ link: '26.2.0.cl',
+ subLabel: 'Coming soon',
+ iframeUrl: 'https://developer-docs-26-2-0-cl.vercel.app/docs/',
+ },
],
CUSTOM_PAGE_ID: {
API_PLAYGROUND: 'restV2-playground',