diff --git a/apps/app/.ladle/settings-story-fixtures.tsx b/apps/app/.ladle/settings-story-fixtures.tsx
index d81d02fd2e..d1aac8fbd8 100644
--- a/apps/app/.ladle/settings-story-fixtures.tsx
+++ b/apps/app/.ladle/settings-story-fixtures.tsx
@@ -1,7 +1,7 @@
import { useState, type ReactNode } from "react";
import { useNavigate } from "react-router-dom";
import { QueryClientProvider } from "@tanstack/react-query";
-import { PERSONAL_PROJECT_ID } from "@bb/domain";
+import { PERSONAL_PROJECT_ID, type ProviderInfo } from "@bb/domain";
import { UPDATE_ACTION_ICON } from "@bb/domain/update-state";
import type {
SidebarBootstrapResponse,
@@ -15,6 +15,7 @@ import {
pluginMarketplacesQueryKey,
sidebarNavigationQueryKey,
systemConfigQueryKey,
+ systemProvidersQueryKey,
systemVersionQueryKey,
} from "../src/hooks/queries/query-keys";
import {
@@ -23,6 +24,7 @@ import {
} from "../src/hooks/useUpdateInventory";
import { createAppQueryClient } from "../src/lib/query-client";
import { makeSystemConfig } from "../src/test/fixtures/system-config";
+import { makeProviderInfo } from "../src/test/provider-info-fixture";
import { getSettingsRoutePath } from "../src/lib/route-paths";
import {
BbAppUpdateRows,
@@ -39,6 +41,9 @@ import {
makeProject,
makeProviderCliStatus,
} from "./story-fixtures";
+import codexLogoUrl from "../../../plugins/provider-codex/icons/codex.svg";
+import claudeCodeLogoUrl from "../../../plugins/provider-claude-code/icons/claude-code.svg";
+import cursorLogoUrl from "../../../plugins/provider-acp/icons/cursor.svg";
const SETTINGS_STORY_NOW = Date.parse("2026-08-19T08:00:00.000Z");
@@ -140,6 +145,24 @@ const systemVersion = {
upgradeCommand: "npx bb-app@latest",
} satisfies SystemVersionResponse;
+const systemProviders = [
+ makeProviderInfo({
+ id: "codex",
+ displayName: "Codex",
+ logoUrl: codexLogoUrl,
+ }),
+ makeProviderInfo({
+ id: "claude-code",
+ displayName: "Claude Code",
+ logoUrl: claudeCodeLogoUrl,
+ }),
+ makeProviderInfo({
+ id: "acp-cursor",
+ displayName: "Cursor",
+ logoUrl: cursorLogoUrl,
+ }),
+] satisfies ProviderInfo[];
+
const settingsUpdateMachine = {
host: SETTINGS_STORY_PRIMARY_HOST,
isPrimary: true,
@@ -167,7 +190,6 @@ export function SettingsUpdatesStory() {
label="Update all 1 CLI tool"
tooltipLabel="Update all"
icon={UPDATE_ACTION_ICON}
- iconPosition="end"
visibleLabel="Update all"
variant="default"
onClick={noop}
@@ -208,6 +230,7 @@ function createSettingsStoryQueryClient() {
});
queryClient.setQueryData(hostsQueryKey(), SETTINGS_STORY_HOSTS);
queryClient.setQueryData(systemConfigQueryKey(), systemConfig);
+ queryClient.setQueryData(systemProvidersQueryKey(), systemProviders);
queryClient.setQueryData(systemVersionQueryKey(), systemVersion);
queryClient.setQueryData(sidebarNavigationQueryKey(), sidebarNavigation);
queryClient.setQueryData(pluginMarketplacesQueryKey(), []);
diff --git a/apps/app/src/components/dialogs/EnvironmentRenameDialog.stories.tsx b/apps/app/src/components/dialogs/EnvironmentRenameDialog.stories.tsx
index 8b97c87fe0..2b021239be 100644
--- a/apps/app/src/components/dialogs/EnvironmentRenameDialog.stories.tsx
+++ b/apps/app/src/components/dialogs/EnvironmentRenameDialog.stories.tsx
@@ -26,11 +26,37 @@ const customNameTarget: EnvironmentRenameDialogTarget = {
canClearName: true,
};
+export function BranchContext() {
+ const inputRef = useRef
{displayedErrorMessage}
) : null} diff --git a/apps/app/src/components/pickers/ModelReasoningPicker.test.tsx b/apps/app/src/components/pickers/ModelReasoningPicker.test.tsx index 0722fd60b9..b60acad123 100644 --- a/apps/app/src/components/pickers/ModelReasoningPicker.test.tsx +++ b/apps/app/src/components/pickers/ModelReasoningPicker.test.tsx @@ -159,6 +159,7 @@ function renderPicker({ modelLoadError = null, compact = false, splitPane = false, + muted = false, }: { onSelectedProviderChange?: ((value: string) => void) | null; onModelChange?: (value: string) => void; @@ -176,6 +177,7 @@ function renderPicker({ modelLoadError?: SystemExecutionOptionsModelLoadError | null; compact?: boolean; splitPane?: boolean; + muted?: boolean; } = {}) { const { queryClient, wrapper } = createQueryClientTestHarness(); queryClient.setQueryData( @@ -215,6 +217,7 @@ function renderPicker({ fastModeEnabled={false} onFastModeChange={vi.fn()} showFastModeToggle={false} + muted={muted} modal={false} /> @@ -248,6 +251,18 @@ afterEach(() => { }); describe("ModelReasoningPicker", () => { + it("uses the lower-emphasis chrome token for the composer caret", () => { + renderPicker({ muted: true }); + + const trigger = screen.getByRole("button", { + name: "Provider, model and reasoning", + }); + expect( + trigger.querySelector('[data-icon="ChevronDown"]')?.classList, + ).toContain("text-subtle-foreground/75"); + expect(trigger.classList).toContain("font-normal"); + }); + it("gives a non-SVG provider mark the same 16px trigger size as button SVGs", () => { renderPicker({ pickerProviderOptions: [ diff --git a/apps/app/src/components/pickers/ModelReasoningPicker.tsx b/apps/app/src/components/pickers/ModelReasoningPicker.tsx index 08f99cfb71..ec25beaeb7 100644 --- a/apps/app/src/components/pickers/ModelReasoningPicker.tsx +++ b/apps/app/src/components/pickers/ModelReasoningPicker.tsx @@ -790,6 +790,7 @@ export function ModelReasoningPicker({ OPTION_INTERACTIVE_CLASS_NAME, LIST_HOVER_TRANSITION, muted && OPTION_MUTED_CLASS_NAME, + muted && "font-normal", disabled && "cursor-default disabled:opacity-100", className, )} @@ -855,7 +856,10 @@ export function ModelReasoningPicker({ {disabled ? null : (