Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 3 additions & 8 deletions .github/workflows/lazurio-fork-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ jobs:
# design system's light look, root decision 0200, whose one stylesheet is
# apps/web/src/lazurio/theme.css), ChatView.tsx (update notice, Environment
# browser), RightPanelTabs.tsx and rightPanelStore.ts (Environment browser, Nová
# karta).
# karta), sidebar/SidebarChrome.tsx (the shell's column head under every sidebar's
# top row, and the name in the app).
apps/server/src/cli/config.ts
apps/server/src/config.ts
apps/server/src/environment/ServerEnvironment.ts
Expand All @@ -75,6 +76,7 @@ jobs:
apps/web/index.html
apps/web/src/components/ChatView.tsx
apps/web/src/components/RightPanelTabs.tsx
apps/web/src/components/sidebar/SidebarChrome.tsx
apps/web/src/main.tsx
apps/web/src/rightPanelStore.ts
# Hosted configuration: T3CODE_CLIENT_SESSION_TTL, T3CODE_EXTERNAL_ORIGIN (a
Expand Down Expand Up @@ -124,12 +126,6 @@ jobs:
# text across upstream's reload after pairing, and the chat layout opens it as an
# unsent draft.
apps/web/src/routes/_chat.tsx
# The Lazurio shell slot (issue #33): the loader, the rail, the padding and
# Buddy in index.html, and the column head at the top of the sidebar, measured
# with upstream's observeResize. The shell itself is served by the Environment's
# Launchpad; without it nothing renders. index.html also maps T3's sidebar tokens
# to the shell's colour roles.
apps/web/src/components/AppSidebarLayout.tsx
# The name in the app (root decision 0200): T3 Code (Lazurio), from the stage
# label of the distribution's builds (Lazurio where upstream says Beta), with the
# label beside the wordmark in the sidebar, the page title in index.html and the
Expand All @@ -139,7 +135,6 @@ jobs:
apps/web/src/branding.logic.ts
apps/web/src/branding.test.ts
apps/web/src/branding.ts
apps/web/src/components/sidebar/SidebarChrome.tsx
# The Environment browser (root decision 0191, plan DEV-6646, LazurioPlatform F47):
# a thread's agents get its agent-browser session, Codex's through the thread's
# config (CodexAdapterV2.ts, whose test expects it) and the others' through the
Expand Down
25 changes: 2 additions & 23 deletions apps/web/src/components/AppSidebarLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { useAtomValue } from "@effect/atom-react";
import * as Schema from "effect/Schema";
import {
createElement,
useCallback,
useEffect,
useState,
useSyncExternalStore,
Expand All @@ -21,7 +19,6 @@ import {
import { isEditableFocused } from "../lib/editableFocus";
import { isPreviewFocused } from "../lib/previewFocus";
import { isTerminalFocused } from "../lib/terminalFocus";
import { observeResize } from "../lib/observeResize";
import { isModelPickerOpen } from "../modelPickerVisibility";
import { selectActiveRightPanel, useRightPanelStore } from "../rightPanelStore";
import { selectThreadTerminalUiState, useTerminalUiStateStore } from "../terminalUiStateStore";
Expand Down Expand Up @@ -83,7 +80,7 @@ function readInitialThreadSidebarWidth(): number {
}
}

function SidebarControl({ lazurioColumnHeadHeight }: { lazurioColumnHeadHeight: number }) {
function SidebarControl() {
const usagePageOpen = useLocation({ select: (location) => location.pathname === "/usage" });
const keybindings = useAtomValue(primaryServerKeybindingsAtom);
const { toggleSidebar, isMobile, mobileSheetMounted } = useSidebar();
Expand Down Expand Up @@ -148,12 +145,6 @@ function SidebarControl({ lazurioColumnHeadHeight }: { lazurioColumnHeadHeight:
isMobile && mobileSheetMounted && "hidden",
)}
data-sidebar-control=""
// Lazurio shell: the open sidebar's top row sits below the column head, and so does its toggle.
style={
isSidebarVisible && !isMobile && lazurioColumnHeadHeight > 0
? { top: `calc(var(--workspace-controls-top) + ${lazurioColumnHeadHeight}px)` }
: undefined
}
>
<Tooltip>
<TooltipTrigger
Expand Down Expand Up @@ -266,16 +257,6 @@ export function AppSidebarLayout({ children }: { children: ReactNode }) {
}
setSidebarWidth(resolveInitialThreadSidebarWidth(null, viewportWidth));
};
// Lazurio shell: height of the column head, 0 while the shell is absent.
const [lazurioColumnHeadHeight, setLazurioColumnHeadHeight] = useState(0);
const observeLazurioColumnHead = useCallback((element: HTMLElement | null) => {
if (!element) return;
const stop = observeResize(element, () => setLazurioColumnHeadHeight(element.offsetHeight));
return () => {
stop();
setLazurioColumnHeadHeight(0);
};
}, []);
const [isWindowFullscreen, setIsWindowFullscreen] = useState(() => {
const getWindowFullscreenState = window.desktopBridge?.getWindowFullscreenState;
return isMacosDesktop && typeof getWindowFullscreenState === "function"
Expand Down Expand Up @@ -358,8 +339,6 @@ export function AppSidebarLayout({ children }: { children: ReactNode }) {
// The narrow-window sidebar is a sheet, portaled outside the provider's styles.
style={windowControlsInsetStyle}
>
{/* Lazurio shell (docs/operations/lazurio-fork-release.md): the Environment picker and the app switch, above the upstream top row. Undefined, it renders nothing. */}
{createElement("lazurio-column-head", { active: "chat", ref: observeLazurioColumnHead })}
{isOnSettings ? (
<>
<SidebarChromeHeader isElectron={isElectron} />
Expand All @@ -373,7 +352,7 @@ export function AppSidebarLayout({ children }: { children: ReactNode }) {
<SidebarRail onDoubleClick={resetSidebarWidth} />
</Sidebar>
{children}
<SidebarControl lazurioColumnHeadHeight={lazurioColumnHeadHeight} />
<SidebarControl />
<NavigationHistoryShortcuts />
<MainAppLocationTracker />
</SidebarProvider>
Expand Down
29 changes: 24 additions & 5 deletions apps/web/src/components/sidebar/SidebarChrome.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ArrowLeftIcon, ChartNoAxesColumnIcon, SettingsIcon } from "lucide-react";
import type { ReactNode } from "react";
import { memo, useCallback } from "react";
import { createElement, memo, useCallback } from "react";
import { Link, useLocation, useNavigate } from "@tanstack/react-router";

import { useEnvironmentIdentificationMode } from "../../hooks/useSettings";
Expand All @@ -14,6 +14,7 @@ import {
useEnvironmentStageLabel,
} from "../SidebarStageBackdrop";
import { Badge } from "../ui/badge";
import { LazurioBadge } from "../../lazurio/LazurioBadge";
import {
SidebarFooter,
SidebarMenu,
Expand All @@ -31,7 +32,7 @@ import { SidebarUpdateArchitectureWarning, SidebarUpdatePill } from "./SidebarUp
import { PullRequestGlyph } from "~/components/pullRequest/pullRequestIcons";
import { observeResize } from "~/lib/observeResize";

export const SidebarChromeHeader = memo(function SidebarChromeHeader({
const SidebarChromeTitlebar = memo(function SidebarChromeTitlebar({
isElectron,
}: {
isElectron: boolean;
Expand Down Expand Up @@ -74,16 +75,34 @@ export const SidebarChromeHeader = memo(function SidebarChromeHeader({
<SidebarBrand onBackdrop={backdropVariant !== null} />
{pillLabel ? (
<div className="ml-1 flex h-7 items-center">
<Badge data-environment-identification="pill" size="sm" variant="secondary">
{pillLabel}
</Badge>
{pillLabel === "Lazurio" ? (
<LazurioBadge />
) : (
<Badge data-environment-identification="pill" size="sm" variant="secondary">
{pillLabel}
</Badge>
)}
</div>
) : null}
</div>
</div>
);
});

// Lazurio shell (docs/operations/lazurio-fork-release.md): every sidebar's top row, with its toggle
// and the wordmark, has the column head under it: the Environment picker and the app switch.
// Undefined, the element renders nothing.
export const SidebarChromeHeader = memo(function SidebarChromeHeader(props: {
isElectron: boolean;
}) {
return (
<>
<SidebarChromeTitlebar {...props} />
{createElement("lazurio-column-head", { active: "chat" })}
</>
);
});

// Measures the brand at its titlebar inset, plus the header's right padding and the
// sidebar border, so the sidebar minimum follows font size, zoom and macOS window controls.
export function SidebarBrandWidthProbe({
Expand Down
22 changes: 22 additions & 0 deletions apps/web/src/lazurio/LazurioBadge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import symbol from "./brand/symbol-color.svg";
import symbolDark from "./brand/symbol-color-dark.svg";

/**
* Lazurio overlay (root decision 0200): the "Lazurio" label beside T3 Code's wordmark, with the
* approved Lazurio symbol before the word (the approved design of the left column, 2026-10-17).
* The symbol is the design system's whole asset, never redrawn, at its 16 px minimum (logo.md),
* so the label is taller than T3's small badge; on a dark look it is the dark rendition, as
* blue-500 vanishes on dark ground. The colours and the type are T3's secondary badge.
*/
export function LazurioBadge() {
return (
<span
data-environment-identification="pill"
className="inline-flex h-5 shrink-0 items-center gap-1 rounded-sm bg-secondary px-0.75 font-medium text-3xs text-secondary-foreground leading-none"
>
<img alt="" className="size-4 dark:hidden" height={16} src={symbol} width={16} />
<img alt="" className="hidden size-4 dark:block" height={16} src={symbolDark} width={16} />
Lazurio
</span>
);
}
7 changes: 7 additions & 0 deletions apps/web/src/lazurio/brand/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Lazurio brand assets

`symbol-color.svg` and `symbol-color-dark.svg` are the Lazurio symbol for light and dark ground,
copied unchanged from the Lazurio design system (`content/brand/logo/`, at `22265ef2`). The logo
manual allows only the whole approved asset: never edit, redraw or recolour these files. To update
them, copy the new approved files over these. LazurioPlatform vendors the same light symbol in
`src/shell/vendor/lazurio/`.
1 change: 1 addition & 0 deletions apps/web/src/lazurio/brand/symbol-color-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions apps/web/src/lazurio/brand/symbol-color.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading