feat(studio): reorder Terminal tab; move Private Alpha badge to sidebar header

- Terminal (disabled) now sits second to last: Overview / Logs / Terminal / Settings.
- Move the "Private Alpha" badge off the Workers list title and onto the product
  menu sidebar header, next to the "Workers" title. Threaded via an optional
  productMenuBadge/titleBadge prop through ProjectLayout → ProductMenuBar
  (additive, no change for other products).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XQ5b58nwfCGsifA7PCheQb
This commit is contained in:
Claude committed 2026-08-13 13:08:08 +00:00
1 parent 6a992de41a
commit 5bcd317ec6
5 files changed
+45 -30

No files matched your search

@@ -52,6 +52,9 @@ import {
type WorkerTab = 'overview' | 'logs' | 'settings'
const WORKER_TABS: WorkerTab[] = ['overview', 'logs', 'settings']
// Display order for the nav — Terminal is a disabled placeholder second to last.
const TAB_ORDER: Array<WorkerTab | 'terminal'> = ['overview', 'logs', 'terminal', 'settings']
const TAB_LABEL: Record<WorkerTab, string> = {
overview: 'Overview',
logs: 'Logs',
@@ -197,26 +200,29 @@ export const WorkerDetail = () => {
<PageHeaderNavigationTabs>
<NavMenu>
{WORKER_TABS.map((item) => (
<NavMenuItem key={item} active={tab === item}>
<button type="button" onClick={() => setTab(item)}>
{TAB_LABEL[item]}
</button>
</NavMenuItem>
))}
<NavMenuItem active={false}>
<Tooltip>
<TooltipTrigger asChild>
<span className="flex h-full cursor-not-allowed items-center gap-1.5 text-foreground-muted">
Terminal
<span className="rounded-full border border-strong px-1.5 py-0.5 text-[10px] uppercase tracking-wide text-foreground-lighter">
Soon
</span>
</span>
</TooltipTrigger>
<TooltipContent side="bottom">Coming soon in private alpha</TooltipContent>
</Tooltip>
</NavMenuItem>
{TAB_ORDER.map((item) =>
item === 'terminal' ? (
<NavMenuItem key="terminal" active={false}>
<Tooltip>
<TooltipTrigger asChild>
<span className="flex h-full cursor-not-allowed items-center gap-1.5 text-foreground-muted">
Terminal
<span className="rounded-full border border-strong px-1.5 py-0.5 text-[10px] uppercase tracking-wide text-foreground-lighter">
Soon
</span>
</span>
</TooltipTrigger>
<TooltipContent side="bottom">Coming soon in private alpha</TooltipContent>
</Tooltip>
</NavMenuItem>
) : (
<NavMenuItem key={item} active={tab === item}>
<button type="button" onClick={() => setTab(item)}>
{TAB_LABEL[item]}
</button>
</NavMenuItem>
)
)}
</NavMenu>
</PageHeaderNavigationTabs>
</PageHeader>
@@ -1,15 +1,18 @@
import { useFlag, useParams } from 'common'
import Link from 'next/link'
import { PropsWithChildren } from 'react'
import { PropsWithChildren, ReactNode } from 'react'
import { Button, cn } from 'ui'
interface ProductMenuBarProps {
title: string
/** Optional node rendered next to the title, e.g. a status badge. */
titleBadge?: ReactNode
className?: string
}
export const ProductMenuBar = ({
title,
titleBadge,
children,
className,
}: PropsWithChildren<ProductMenuBarProps>) => {
@@ -30,7 +33,10 @@ export const ProductMenuBar = ({
)}
>
<div className="border-default flex min-h-(--header-height) items-center border-b px-6 justify-between">
<h4 className="text-lg">{title}</h4>
<div className="flex items-center gap-2">
<h4 className="text-lg">{title}</h4>
{titleBadge}
</div>
{showExplorerCTA && (
<Button asChild variant="default">
<Link href={`/project/${ref}/explorer`}>Explorer</Link>
@@ -106,6 +106,8 @@ export interface ProjectLayoutProps {
isLoading?: boolean
isBlocking?: boolean
product?: string
/** Optional node rendered next to the product title in the menu bar header. */
productMenuBadge?: ReactNode
productMenu?: ReactNode
browserTitle?: {
entity?: string
@@ -124,6 +126,7 @@ export const ProjectLayout = forwardRef<HTMLDivElement, PropsWithChildren<Projec
isLoading = false,
isBlocking = true,
product = '',
productMenuBadge,
productMenu,
browserTitle,
children,
@@ -298,7 +301,11 @@ export const ProjectLayout = forwardRef<HTMLDivElement, PropsWithChildren<Projec
isBlocking={isBlocking}
productMenu={productMenu}
>
<ProductMenuBar title={product} className={productMenuClassName}>
<ProductMenuBar
title={product}
titleBadge={productMenuBadge}
className={productMenuClassName}
>
{productMenu}
</ProductMenuBar>
</MenuBarWrapper>
@@ -1,6 +1,7 @@
import { useParams } from 'common'
import { useRouter } from 'next/router'
import { useMemo, type PropsWithChildren } from 'react'
import { Badge } from 'ui'
import { ProjectLayout } from '../ProjectLayout'
import { ProductMenu } from '@/components/ui/ProductMenu'
@@ -43,6 +44,7 @@ const WorkersLayout = ({ children, title }: PropsWithChildren<WorkersLayoutProps
return (
<ProjectLayout
product="Workers"
productMenuBadge={<Badge variant="warning">Private Alpha</Badge>}
productMenu={<WorkersProductMenu />}
isBlocking={false}
browserTitle={{ entity: 'Workers', section: title }}
@@ -1,6 +1,5 @@
import { useParams } from 'common'
import { useEffect, useState } from 'react'
import { Badge } from 'ui'
import { PageContainer } from 'ui-patterns/PageContainer'
import {
PageHeader,
@@ -35,12 +34,7 @@ const WorkersPage: NextPageWithLayout = () => {
<PageHeader size="large">
<PageHeaderMeta>
<PageHeaderSummary>
<PageHeaderTitle>
<span className="flex items-center gap-3">
Workers
<Badge variant="warning">Private Alpha</Badge>
</span>
</PageHeaderTitle>
<PageHeaderTitle>Workers</PageHeaderTitle>
<PageHeaderDescription>
Run managed compute in microVMs next to your database
</PageHeaderDescription>