diff --git a/ui/components/app/perps/order-book/order-book-config-modal.tsx b/ui/components/app/perps/order-book/order-book-config-modal.tsx
index 6620020d59fe..2efda0eac07e 100644
--- a/ui/components/app/perps/order-book/order-book-config-modal.tsx
+++ b/ui/components/app/perps/order-book/order-book-config-modal.tsx
@@ -44,9 +44,10 @@ import type {
const PILL_BASE_CLASS =
'flex items-center justify-center rounded-full py-3 px-4 cursor-pointer transition-colors duration-150 border';
-const PILL_SELECTED_CLASS = 'bg-transparent border-muted';
+
+const PILL_SELECTED_CLASS = 'bg-muted border-transparent';
const PILL_UNSELECTED_CLASS =
- 'bg-muted border-transparent hover:bg-muted-hover';
+ 'bg-transparent border-muted hover:bg-muted-hover';
type PillProps = {
label: string;
diff --git a/ui/pages/perps/perps-order-entry-page.test.tsx b/ui/pages/perps/perps-order-entry-page.test.tsx
index 533b368f685e..9e9fcaef12f7 100644
--- a/ui/pages/perps/perps-order-entry-page.test.tsx
+++ b/ui/pages/perps/perps-order-entry-page.test.tsx
@@ -712,6 +712,43 @@ describe('PerpsOrderEntryPage', () => {
expect(divider).toHaveAttribute('aria-valuenow', '33');
});
+ it('mounts the order book already open when the persisted preference is expanded', () => {
+ const state = createMockState();
+ const store = mockStore({
+ ...state,
+ metamask: {
+ ...state.metamask,
+ proLayoutPreferences: { orderBookExpanded: true },
+ },
+ });
+ renderWithProvider(, store);
+
+ expect(screen.getByTestId('perps-order-book-toggle')).toHaveAttribute(
+ 'aria-pressed',
+ 'true',
+ );
+ expect(screen.getByTestId('perps-order-book')).toBeInTheDocument();
+ });
+
+ it('persists the open state when the order book is toggled', () => {
+ const store = mockStore(createMockState());
+ renderWithProvider(, store);
+
+ const toggle = screen.getByTestId('perps-order-book-toggle');
+
+ fireEvent.click(toggle);
+ expect(mockSubmitRequestToBackground).toHaveBeenCalledWith(
+ 'perpsSetProLayoutPreferences',
+ [{ orderBookExpanded: true }],
+ );
+
+ fireEvent.click(toggle);
+ expect(mockSubmitRequestToBackground).toHaveBeenCalledWith(
+ 'perpsSetProLayoutPreferences',
+ [{ orderBookExpanded: false }],
+ );
+ });
+
it('resizes the split within bounds using the keyboard', () => {
const store = mockStore(createMockStateWithOrderBookPosition('right'));
renderWithProvider(, store);
diff --git a/ui/pages/perps/perps-order-entry-page.tsx b/ui/pages/perps/perps-order-entry-page.tsx
index 7681588eaf53..684353aca8c7 100644
--- a/ui/pages/perps/perps-order-entry-page.tsx
+++ b/ui/pages/perps/perps-order-entry-page.tsx
@@ -72,6 +72,7 @@ import {
selectPerpsIsTestnet,
selectPerpsActiveProvider,
selectOrderBookPosition,
+ selectOrderBookExpanded,
} from '../../selectors/perps-controller';
import {
CandlePeriod,
@@ -301,7 +302,10 @@ const PerpsOrderEntryPage = () => {
const { buildTrackingData, buildTpslTrackingData, setFlowAttribution } =
usePerpsAttribution();
const [isGeoBlockModalOpen, setIsGeoBlockModalOpen] = useState(false);
- const [isOrderBookOpen, setIsOrderBookOpen] = useState(false);
+ const persistedOrderBookExpanded = useSelector(selectOrderBookExpanded);
+ const [isOrderBookOpen, setIsOrderBookOpen] = useState(
+ persistedOrderBookExpanded,
+ );
const [orderBookWidthPct, setOrderBookWidthPct] = useState(
ORDER_BOOK_DEFAULT_WIDTH_PCT,
);
@@ -1447,6 +1451,11 @@ const PerpsOrderEntryPage = () => {
const handleToggleOrderBook = useCallback(() => {
const next = !isOrderBookOpen;
setIsOrderBookOpen(next);
+ submitRequestToBackground('perpsSetProLayoutPreferences', [
+ { orderBookExpanded: next },
+ ]).catch((error) =>
+ console.error('Failed to persist order book open state', error),
+ );
// Tracking is a side effect and must run outside the state updater (updaters
// must be pure and may be invoked more than once). Specific open/close values
// keep dark-launch open-rate measurable (generic TAP cannot).
diff --git a/ui/selectors/perps-controller.test.ts b/ui/selectors/perps-controller.test.ts
index 1f7684302602..3f559c370bf8 100644
--- a/ui/selectors/perps-controller.test.ts
+++ b/ui/selectors/perps-controller.test.ts
@@ -31,6 +31,7 @@ import {
selectPerpsShouldShowDepositToast,
selectProLayoutPreferences,
selectOrderBookPosition,
+ selectOrderBookExpanded,
} from './perps-controller';
function buildState(overrides: Record = {}) {
@@ -855,4 +856,21 @@ describe('perps-controller selectors', () => {
).toBe('left');
});
});
+
+ describe('selectOrderBookExpanded', () => {
+ it('returns the persisted open state', () => {
+ expect(
+ selectOrderBookExpanded(
+ buildState({ proLayoutPreferences: { orderBookExpanded: true } }),
+ ),
+ ).toBe(true);
+ });
+
+ it('defaults to closed', () => {
+ expect(selectOrderBookExpanded(buildState())).toBe(false);
+ expect(
+ selectOrderBookExpanded(buildState({ proLayoutPreferences: {} })),
+ ).toBe(false);
+ });
+ });
});
diff --git a/ui/selectors/perps-controller.ts b/ui/selectors/perps-controller.ts
index aa07ca8f1081..9e616c421c95 100644
--- a/ui/selectors/perps-controller.ts
+++ b/ui/selectors/perps-controller.ts
@@ -239,5 +239,17 @@ export const selectOrderBookPosition = (state: PerpsState) =>
state.metamask.proLayoutPreferences?.orderBookPosition ??
DEFAULT_PRO_LAYOUT_PREFERENCES.orderBookPosition;
+/**
+ * Whether the order book panel was left open. Global across markets (the
+ * preference object is flat, not per-market), so the panel opens in the same
+ * state on every symbol.
+ *
+ * @param state - Perps controller state.
+ * @returns True when the panel should start open.
+ */
+export const selectOrderBookExpanded = (state: PerpsState) =>
+ state.metamask.proLayoutPreferences?.orderBookExpanded ??
+ DEFAULT_PRO_LAYOUT_PREFERENCES.orderBookExpanded;
+
export const selectPerpsTradeConfigurations = (state: PerpsState) =>
state.metamask.tradeConfigurations ?? EMPTY_TRADE_CONFIGURATIONS;