From b2fe33e7fdd36e8d4f276b28275da993845c55da Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 21 Jul 2025 12:07:18 +0100 Subject: [PATCH] Automatic version number Signed-off-by: Charles de Dreuille --- docs-ui/package.json | 1 + docs-ui/src/app/layout.tsx | 24 +++++++++++++-- .../src/components/Sidebar/Sidebar.module.css | 29 ++++++++++++++++++- docs-ui/src/components/Sidebar/index.tsx | 21 +++++++++++++- docs-ui/yarn.lock | 10 +++++++ 5 files changed, 81 insertions(+), 4 deletions(-) diff --git a/docs-ui/package.json b/docs-ui/package.json index 74c5d59075..6fd29e0678 100644 --- a/docs-ui/package.json +++ b/docs-ui/package.json @@ -22,6 +22,7 @@ "@mdx-js/loader": "^3.1.0", "@mdx-js/react": "^3.1.0", "@next/mdx": "15.3.4", + "@remixicon/react": "^4.6.0", "@storybook/react": "^8.6.8", "@uiw/codemirror-themes": "^4.23.7", "@uiw/react-codemirror": "^4.23.7", diff --git a/docs-ui/src/app/layout.tsx b/docs-ui/src/app/layout.tsx index 7ee30ddfa0..697f990587 100644 --- a/docs-ui/src/app/layout.tsx +++ b/docs-ui/src/app/layout.tsx @@ -15,11 +15,31 @@ export const metadata: Metadata = { metadataBase: new URL('https://ui.backstage.io'), }; -export default function RootLayout({ +async function getLatestPackageVersion(): Promise { + try { + const response = await fetch('https://registry.npmjs.org/@backstage/ui', { + next: { revalidate: 3600 }, // Cache for 1 hour + }); + + if (!response.ok) { + throw new Error('Failed to fetch package info'); + } + + const data = await response.json(); + return data['dist-tags']?.latest; + } catch (error) { + console.error('Error fetching package version:', error); + return '0.0.0'; + } +} + +export default async function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { + const packageVersion = await getLatestPackageVersion(); + return ( - +
{children}
diff --git a/docs-ui/src/components/Sidebar/Sidebar.module.css b/docs-ui/src/components/Sidebar/Sidebar.module.css index b658255b32..2b88945c47 100644 --- a/docs-ui/src/components/Sidebar/Sidebar.module.css +++ b/docs-ui/src/components/Sidebar/Sidebar.module.css @@ -15,6 +15,33 @@ } } +.version { + font-size: 0.875rem; + font-weight: 500; + color: var(--secondary); + margin-inline: 32px; + border-bottom: 1px solid var(--border); + padding-bottom: 12px; + display: flex; + align-items: center; + justify-content: space-between; +} + +.versionLinks { + display: flex; + align-items: center; + gap: 8px; + + a { + color: var(--secondary); + transition: color 0.2s ease-in-out; + + &:hover { + color: var(--primary); + } + } +} + .root { height: 100%; } @@ -56,7 +83,7 @@ } .content { - padding: 0 20px 48px; + padding: 0 20px 64px; } .menu { diff --git a/docs-ui/src/components/Sidebar/index.tsx b/docs-ui/src/components/Sidebar/index.tsx index 02308001d6..4d86398ef7 100644 --- a/docs-ui/src/components/Sidebar/index.tsx +++ b/docs-ui/src/components/Sidebar/index.tsx @@ -7,6 +7,7 @@ import Link from 'next/link'; import { usePathname } from 'next/navigation'; import { motion } from 'motion/react'; import { Fragment } from 'react'; +import { RiGithubLine, RiNpmjsLine } from '@remixicon/react'; const data = [ { @@ -31,12 +32,30 @@ const data = [ }, ]; -export const Sidebar = () => { +interface SidebarProps { + version: string; +} + +export const Sidebar = ({ version }: SidebarProps) => { const pathname = usePathname(); const isPlayground = pathname.includes('/playground'); return (
+
+ Version {version} + +
diff --git a/docs-ui/yarn.lock b/docs-ui/yarn.lock index 56895e3b7b..22531f1a3b 100644 --- a/docs-ui/yarn.lock +++ b/docs-ui/yarn.lock @@ -907,6 +907,15 @@ __metadata: languageName: node linkType: hard +"@remixicon/react@npm:^4.6.0": + version: 4.6.0 + resolution: "@remixicon/react@npm:4.6.0" + peerDependencies: + react: ">=18.2.0" + checksum: 10/d92c8131734062fca8d82d55dd8f3f4e28cb72c5eefda528c8aba5f3298f0c847342eecdbd7787d6da5af21b699d735f6cf27f151f0c982c1c9f06a78b235c94 + languageName: node + linkType: hard + "@rtsao/scc@npm:^1.1.0": version: 1.1.0 resolution: "@rtsao/scc@npm:1.1.0" @@ -2302,6 +2311,7 @@ __metadata: "@mdx-js/loader": "npm:^3.1.0" "@mdx-js/react": "npm:^3.1.0" "@next/mdx": "npm:15.3.4" + "@remixicon/react": "npm:^4.6.0" "@storybook/react": "npm:^8.6.8" "@types/mdx": "npm:^2.0.13" "@types/node": "npm:^20"