From bff93eb0bcef0fee7226f42fc081bd206b0991e5 Mon Sep 17 00:00:00 2001 From: qiancai Date: Thu, 9 Jul 2026 17:09:00 +0800 Subject: [PATCH 1/7] Update LeftNavTree.tsx --- src/components/Layout/LeftNav/LeftNavTree.tsx | 50 ++++++++++++++----- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/src/components/Layout/LeftNav/LeftNavTree.tsx b/src/components/Layout/LeftNav/LeftNavTree.tsx index 5412d370..f724d7a4 100644 --- a/src/components/Layout/LeftNav/LeftNavTree.tsx +++ b/src/components/Layout/LeftNav/LeftNavTree.tsx @@ -7,6 +7,7 @@ import Stack from "@mui/material/Stack"; import Typography from "@mui/material/Typography"; import Divider from "@mui/material/Divider"; import { useTheme } from "@mui/material/styles"; +import { useTranslation } from "gatsby-plugin-react-i18next"; import { RepoNavLink, RepoNav } from "shared/interface"; import LinkComponent from "components/Link"; @@ -190,6 +191,7 @@ export default function ControlledTreeView(props: { }); const theme = useTheme(); + const { t } = useTranslation(); const [disableTransition, setDisableTransition] = React.useState(false); const previousUrlRef = React.useRef(null); @@ -313,7 +315,7 @@ export default function ControlledTreeView(props: { ) : ( )} - {generateItemLabel(item)} + {generateItemLabel(item, theme, t("navbar.badge.preview"))} ); }; @@ -389,9 +391,15 @@ export default function ControlledTreeView(props: { ); } -const generateItemLabel = ({ content: contents, tag }: RepoNavLink) => { +const generateItemLabel = ( + { content: contents, tag }: RepoNavLink, + theme: ReturnType, + previewBadgeLabel: string +) => { + const normalizedTagValue = tag?.value?.trim().toUpperCase(); + const isPreviewTag = normalizedTagValue === "PREVIEW"; const tagQuery = new URLSearchParams(tag?.query); - const tagColor = tagQuery.get("color"); + const tagColor = isPreviewTag ? null : tagQuery.get("color"); const tagColor02 = tagColor && alpha(tagColor, 0.2); return ( @@ -424,18 +432,36 @@ const generateItemLabel = ({ content: contents, tag }: RepoNavLink) => { {tag && ( )} From 1f64a6c1d9220777036adb9456bab1ab4e04a2ca Mon Sep 17 00:00:00 2001 From: qiancai Date: Thu, 9 Jul 2026 21:20:58 +0800 Subject: [PATCH 2/7] fix issues --- gatsby/__tests__/toc.test.ts | 71 +++++++++++++++++++ gatsby/toc.ts | 6 +- src/components/Layout/LeftNav/LeftNavTree.tsx | 14 +++- 3 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 gatsby/__tests__/toc.test.ts diff --git a/gatsby/__tests__/toc.test.ts b/gatsby/__tests__/toc.test.ts new file mode 100644 index 00000000..1c8ccf56 --- /dev/null +++ b/gatsby/__tests__/toc.test.ts @@ -0,0 +1,71 @@ +import { mdxAstToToc } from "../toc"; + +describe("mdxAstToToc tag query parsing", () => { + it("does not emit a bogus ?undefined query when the image URL has no query string", () => { + const toc = mdxAstToToc( + [ + { + type: "list", + children: [ + { + type: "listItem", + children: [ + { + type: "paragraph", + children: [ + { type: "text", value: "Data Service" }, + { + type: "image", + alt: "PREVIEW", + url: "/media/tidb-cloud/blank_transparent_placeholder.png", + }, + ], + }, + ], + }, + ], + }, + ] as any, + "en/tidbcloud/master/TOC" + ); + + expect(toc[0].tag).toEqual({ + value: "PREVIEW", + query: undefined, + }); + }); + + it("keeps tag query params when the image URL includes them", () => { + const toc = mdxAstToToc( + [ + { + type: "list", + children: [ + { + type: "listItem", + children: [ + { + type: "paragraph", + children: [ + { type: "text", value: "Beta Feature" }, + { + type: "image", + alt: "BETA", + url: "/media/tidb-cloud/blank_transparent_placeholder.png?color=%232d9cd2", + }, + ], + }, + ], + }, + ], + }, + ] as any, + "en/tidbcloud/master/TOC" + ); + + expect(toc[0].tag).toEqual({ + value: "BETA", + query: "?color=%232d9cd2", + }); + }); +}); diff --git a/gatsby/toc.ts b/gatsby/toc.ts index fef4f3d3..b84ea77c 100644 --- a/gatsby/toc.ts +++ b/gatsby/toc.ts @@ -2,6 +2,7 @@ import { ListItem, List, Link, + Image, Paragraph, Text, Content, @@ -157,10 +158,11 @@ function getContentFromLink( const child = content.children[0] as Link | Text; // use `image` as tag - const image = content.children.find((n) => n.type === "image"); + const image = content.children.find((n): n is Image => n.type === "image"); + const imageQuery = image?.url.split("?")[1]; const tag = image && { value: image.alt!, - query: `?${image.url.split("?")[1]}`, + query: imageQuery ? `?${imageQuery}` : undefined, }; if (child.type === "link") { diff --git a/src/components/Layout/LeftNav/LeftNavTree.tsx b/src/components/Layout/LeftNav/LeftNavTree.tsx index f724d7a4..a8bdc002 100644 --- a/src/components/Layout/LeftNav/LeftNavTree.tsx +++ b/src/components/Layout/LeftNav/LeftNavTree.tsx @@ -398,9 +398,15 @@ const generateItemLabel = ( ) => { const normalizedTagValue = tag?.value?.trim().toUpperCase(); const isPreviewTag = normalizedTagValue === "PREVIEW"; - const tagQuery = new URLSearchParams(tag?.query); - const tagColor = isPreviewTag ? null : tagQuery.get("color"); - const tagColor02 = tagColor && alpha(tagColor, 0.2); + let tagColor: string | null = null; + let tagColor02: string | null = null; + + if (!isPreviewTag) { + const tagQuery = new URLSearchParams(tag?.query); + tagColor = tagQuery.get("color"); + tagColor02 = tagColor ? alpha(tagColor, 0.2) : null; + } + return ( Date: Fri, 10 Jul 2026 15:54:42 +0800 Subject: [PATCH 3/7] fix(toc): guard missing image tag alt text Avoid creating invalid navigation tags for TOC images without alt text.\n\nAddresses review comments #3557222898 and #3557222909. --- gatsby/__tests__/toc.test.ts | 31 +++++++++++++++++++ gatsby/toc.ts | 10 +++--- src/components/Layout/LeftNav/LeftNavTree.tsx | 4 +-- 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/gatsby/__tests__/toc.test.ts b/gatsby/__tests__/toc.test.ts index 1c8ccf56..db3e9544 100644 --- a/gatsby/__tests__/toc.test.ts +++ b/gatsby/__tests__/toc.test.ts @@ -35,6 +35,37 @@ describe("mdxAstToToc tag query parsing", () => { }); }); + it("does not create a tag when the TOC image has no alt text", () => { + const toc = mdxAstToToc( + [ + { + type: "list", + children: [ + { + type: "listItem", + children: [ + { + type: "paragraph", + children: [ + { type: "text", value: "Data Service" }, + { + type: "image", + alt: null, + url: "/media/tidb-cloud/blank_transparent_placeholder.png", + }, + ], + }, + ], + }, + ], + }, + ] as any, + "en/tidbcloud/master/TOC" + ); + + expect(toc[0].tag).toBeUndefined(); + }); + it("keeps tag query params when the image URL includes them", () => { const toc = mdxAstToToc( [ diff --git a/gatsby/toc.ts b/gatsby/toc.ts index b84ea77c..c8c71f02 100644 --- a/gatsby/toc.ts +++ b/gatsby/toc.ts @@ -160,10 +160,12 @@ function getContentFromLink( // use `image` as tag const image = content.children.find((n): n is Image => n.type === "image"); const imageQuery = image?.url.split("?")[1]; - const tag = image && { - value: image.alt!, - query: imageQuery ? `?${imageQuery}` : undefined, - }; + const tag = image?.alt + ? { + value: image.alt, + query: imageQuery ? `?${imageQuery}` : undefined, + } + : undefined; if (child.type === "link") { if (child.children.length === 0) { diff --git a/src/components/Layout/LeftNav/LeftNavTree.tsx b/src/components/Layout/LeftNav/LeftNavTree.tsx index a8bdc002..73172770 100644 --- a/src/components/Layout/LeftNav/LeftNavTree.tsx +++ b/src/components/Layout/LeftNav/LeftNavTree.tsx @@ -401,8 +401,8 @@ const generateItemLabel = ( let tagColor: string | null = null; let tagColor02: string | null = null; - if (!isPreviewTag) { - const tagQuery = new URLSearchParams(tag?.query); + if (tag && !isPreviewTag) { + const tagQuery = new URLSearchParams(tag.query ?? ""); tagColor = tagQuery.get("color"); tagColor02 = tagColor ? alpha(tagColor, 0.2) : null; } From cb5a1422202dffa24199ff0094ccee37bfa8e5fa Mon Sep 17 00:00:00 2001 From: qiancai Date: Fri, 10 Jul 2026 17:04:10 +0800 Subject: [PATCH 4/7] fix(header-nav): mark TiDB for AI as preview Reuse the shared Preview badge for the TiDB for AI left navigation title and remove the now-unused Beta badge component and translations. --- locale/en/translation.json | 3 +-- locale/ja/translation.json | 3 +-- locale/zh/translation.json | 3 +-- .../Layout/Header/HeaderNavConfigData.tsx | 20 +------------------ 4 files changed, 4 insertions(+), 25 deletions(-) diff --git a/locale/en/translation.json b/locale/en/translation.json index df468a63..0d64a522 100644 --- a/locale/en/translation.json +++ b/locale/en/translation.json @@ -43,8 +43,7 @@ "tidbOperatorReleases": "TiDB Operator Releases", "tiupReleases": "TiUP Releases", "badge": { - "preview": "Preview", - "beta": "Beta" + "preview": "Preview" }, "appdev": "App Dev", "asktug": "Forum", diff --git a/locale/ja/translation.json b/locale/ja/translation.json index d716614d..b536c5d9 100644 --- a/locale/ja/translation.json +++ b/locale/ja/translation.json @@ -43,8 +43,7 @@ "tidbOperatorReleases": "TiDB Operator リリース", "tiupReleases": "TiUP リリース", "badge": { - "preview": "Preview", - "beta": "Beta" + "preview": "Preview" }, "appdev": "アプリ開発", "asktug": "Forum", diff --git a/locale/zh/translation.json b/locale/zh/translation.json index a5e09239..bc6794a1 100644 --- a/locale/zh/translation.json +++ b/locale/zh/translation.json @@ -41,8 +41,7 @@ "tidbOperatorReleases": "TiDB Operator 版本发布记录", "tiupReleases": "TiUP 版本发布记录", "badge": { - "preview": "Preview", - "beta": "Beta" + "preview": "Preview" }, "appdev": "开发指南", "asktug": "社区", diff --git a/src/components/Layout/Header/HeaderNavConfigData.tsx b/src/components/Layout/Header/HeaderNavConfigData.tsx index 80f3beae..65c7af84 100644 --- a/src/components/Layout/Header/HeaderNavConfigData.tsx +++ b/src/components/Layout/Header/HeaderNavConfigData.tsx @@ -32,24 +32,6 @@ const PreviewBadge = (props: { label: string }) => { ); }; -const BetaTagBadge = (props: { label: string }) => ( - -); - /** * Default navigation configuration */ @@ -167,7 +149,7 @@ const getDefaultNavConfig = ( leftNavLabel: ( <> {t("navbar.tidbForAI")} - + ), to: "/ai", From 73b15be1bc00e309ba4e3a6c5a6dcbbddd38757d Mon Sep 17 00:00:00 2001 From: qiancai Date: Fri, 10 Jul 2026 17:07:48 +0800 Subject: [PATCH 5/7] fix(nav): unify Preview badge styles Share one PreviewBadge component between directory titles and TOC entries so their visual treatment stays identical. --- src/components/Badge/PreviewBadge.tsx | 30 ++++++++++++ .../Layout/Header/HeaderNavConfigData.tsx | 27 +--------- src/components/Layout/LeftNav/LeftNavTree.tsx | 49 ++++++------------- 3 files changed, 47 insertions(+), 59 deletions(-) create mode 100644 src/components/Badge/PreviewBadge.tsx diff --git a/src/components/Badge/PreviewBadge.tsx b/src/components/Badge/PreviewBadge.tsx new file mode 100644 index 00000000..6a4e01e5 --- /dev/null +++ b/src/components/Badge/PreviewBadge.tsx @@ -0,0 +1,30 @@ +import Chip from "@mui/material/Chip"; +import { useTheme } from "@mui/material/styles"; + +const PreviewBadge = (props: { label: string }) => { + const theme = useTheme(); + + return ( + + ); +}; + +export default PreviewBadge; diff --git a/src/components/Layout/Header/HeaderNavConfigData.tsx b/src/components/Layout/Header/HeaderNavConfigData.tsx index 65c7af84..82701b8c 100644 --- a/src/components/Layout/Header/HeaderNavConfigData.tsx +++ b/src/components/Layout/Header/HeaderNavConfigData.tsx @@ -2,36 +2,11 @@ import { NavConfig } from "./HeaderNavConfigType"; import { CLOUD_MODE_KEY } from "shared/useCloudPlan"; import { CloudPlan, TOCNamespace } from "shared/interface"; import OpenInNewIcon from "@mui/icons-material/OpenInNew"; -import Chip from "@mui/material/Chip"; -import { useTheme } from "@mui/material/styles"; +import PreviewBadge from "components/Badge/PreviewBadge"; import TiDBCloudIcon from "media/icons/cloud-03.svg"; import TiDBIcon from "media/icons/layers-three-01.svg"; -const PreviewBadge = (props: { label: string }) => { - const theme = useTheme(); - return ( - - ); -}; - /** * Default navigation configuration */ diff --git a/src/components/Layout/LeftNav/LeftNavTree.tsx b/src/components/Layout/LeftNav/LeftNavTree.tsx index 73172770..38e5a625 100644 --- a/src/components/Layout/LeftNav/LeftNavTree.tsx +++ b/src/components/Layout/LeftNav/LeftNavTree.tsx @@ -11,6 +11,7 @@ import { useTranslation } from "gatsby-plugin-react-i18next"; import { RepoNavLink, RepoNav } from "shared/interface"; import LinkComponent from "components/Link"; +import PreviewBadge from "components/Badge/PreviewBadge"; import { scrollToElementIfInView } from "shared/utils"; import { alpha, Chip } from "@mui/material"; @@ -315,7 +316,7 @@ export default function ControlledTreeView(props: { ) : ( )} - {generateItemLabel(item, theme, t("navbar.badge.preview"))} + {generateItemLabel(item, t("navbar.badge.preview"))} ); }; @@ -393,7 +394,6 @@ export default function ControlledTreeView(props: { const generateItemLabel = ( { content: contents, tag }: RepoNavLink, - theme: ReturnType, previewBadgeLabel: string ) => { const normalizedTagValue = tag?.value?.trim().toUpperCase(); @@ -401,6 +401,7 @@ const generateItemLabel = ( let tagColor: string | null = null; let tagColor02: string | null = null; + // PREVIEW intentionally ignores source color overrides to match shared badges. if (tag && !isPreviewTag) { const tagQuery = new URLSearchParams(tag.query ?? ""); tagColor = tagQuery.get("color"); @@ -436,43 +437,25 @@ const generateItemLabel = ( ); })} - {tag && ( + {tag && isPreviewTag ? ( + + ) : tag ? ( - )} + ) : null} ); }; From 7642320fc2e95ef1f18f01f3b00db05e5960e61f Mon Sep 17 00:00:00 2001 From: qiancai Date: Fri, 10 Jul 2026 17:21:12 +0800 Subject: [PATCH 6/7] fix(nav): preserve Preview badge layout Remove the unintended flexShrink override from the shared badge and resolve the Preview translation once per left-nav render. --- src/components/Badge/PreviewBadge.tsx | 1 - src/components/Layout/LeftNav/LeftNavTree.tsx | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Badge/PreviewBadge.tsx b/src/components/Badge/PreviewBadge.tsx index 6a4e01e5..93470dfd 100644 --- a/src/components/Badge/PreviewBadge.tsx +++ b/src/components/Badge/PreviewBadge.tsx @@ -10,7 +10,6 @@ const PreviewBadge = (props: { label: string }) => { size="small" variant="outlined" sx={{ - flexShrink: 0, height: "20px", fontSize: "12px", fontWeight: 400, diff --git a/src/components/Layout/LeftNav/LeftNavTree.tsx b/src/components/Layout/LeftNav/LeftNavTree.tsx index 38e5a625..0766daac 100644 --- a/src/components/Layout/LeftNav/LeftNavTree.tsx +++ b/src/components/Layout/LeftNav/LeftNavTree.tsx @@ -193,6 +193,7 @@ export default function ControlledTreeView(props: { const theme = useTheme(); const { t } = useTranslation(); + const previewBadgeLabel = t("navbar.badge.preview"); const [disableTransition, setDisableTransition] = React.useState(false); const previousUrlRef = React.useRef(null); @@ -316,7 +317,7 @@ export default function ControlledTreeView(props: { ) : ( )} - {generateItemLabel(item, t("navbar.badge.preview"))} + {generateItemLabel(item, previewBadgeLabel)} ); }; From 2cf75794a1d750c1c4115cec782024d969ba8f64 Mon Sep 17 00:00:00 2001 From: qiancai Date: Mon, 13 Jul 2026 10:39:49 +0800 Subject: [PATCH 7/7] use the same style of PREVIEW as the cloud console --- src/components/Badge/PreviewBadge.tsx | 13 ++++++++----- .../Layout/VersionSelect/CloudVersionSelect.tsx | 13 +++++++++++-- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/components/Badge/PreviewBadge.tsx b/src/components/Badge/PreviewBadge.tsx index 93470dfd..7133dfde 100644 --- a/src/components/Badge/PreviewBadge.tsx +++ b/src/components/Badge/PreviewBadge.tsx @@ -10,15 +10,18 @@ const PreviewBadge = (props: { label: string }) => { size="small" variant="outlined" sx={{ - height: "20px", - fontSize: "12px", - fontWeight: 400, - borderRadius: "10px", + height: "18px", + fontSize: "10px", + fontWeight: 500, + borderRadius: "1000px", + borderColor: theme.palette.carbon[400], pointerEvents: "none", + textTransform: "uppercase", + letterSpacing: "0.25px", "& .MuiChip-label": { paddingLeft: "8px", paddingRight: "8px", - lineHeight: "20px", + lineHeight: "16px", color: theme.palette.carbon[700], }, }} diff --git a/src/components/Layout/VersionSelect/CloudVersionSelect.tsx b/src/components/Layout/VersionSelect/CloudVersionSelect.tsx index a5e991bf..b81ac500 100644 --- a/src/components/Layout/VersionSelect/CloudVersionSelect.tsx +++ b/src/components/Layout/VersionSelect/CloudVersionSelect.tsx @@ -42,11 +42,20 @@ const CLOUD_VERSIONS = [ variant="outlined" size="small" sx={{ - fontSize: "12px", - height: "20px", + fontSize: "10px", + fontWeight: 500, + height: "18px", + borderRadius: "1000px", pointerEvents: "none", borderColor: "#DCE3E5", color: "#6F787B", + textTransform: "uppercase", + letterSpacing: "0.25px", + "& .MuiChip-label": { + paddingLeft: "8px", + paddingRight: "8px", + lineHeight: "16px", + }, }} /> ),