diff --git a/app/src/App.tsx b/app/src/App.tsx index 125555b1ee..f4b42bad9c 100644 --- a/app/src/App.tsx +++ b/app/src/App.tsx @@ -1,7 +1,12 @@ import * as Sentry from '@sentry/react'; -import { useEffect } from 'react'; +import { useEffect, useRef } from 'react'; import { Provider } from 'react-redux'; -import { HashRouter as Router, useLocation, useNavigate } from 'react-router-dom'; +import { + HashRouter as Router, + useLocation, + useNavigate, + useNavigationType, +} from 'react-router-dom'; import { PersistGate } from 'redux-persist/integration/react'; import AppRoutes from './AppRoutes'; @@ -200,11 +205,22 @@ function AppShellDesktop() { // the core is ready (once per boot). Extracted to a hook so it's testable. useNotchBootSync(isBootstrapping); + const scrollRef = useRef(null); + const navType = useNavigationType(); + + useEffect(() => { + if (navType !== 'POP') { + scrollRef.current?.scrollTo(0, 0); + } + }, [location.pathname, navType]); + return (
-
+
diff --git a/app/src/AppRoutes.tsx b/app/src/AppRoutes.tsx index ae47e152b4..cddfac0b39 100644 --- a/app/src/AppRoutes.tsx +++ b/app/src/AppRoutes.tsx @@ -7,7 +7,6 @@ import PublicRoute from './components/PublicRoute'; import HumanPage from './features/human/HumanPage'; import { getIsMobile } from './lib/platform'; import Accounts from './pages/Accounts'; -import Activity from './pages/Activity'; import Brain from './pages/Brain'; import AgentInsightsPreview from './pages/dev/AgentInsightsPreview'; import Home from './pages/Home'; @@ -88,20 +87,9 @@ const AppRoutes = () => { } /> - {/* Primary Activity surface — replaces /intelligence (Phase 3). */} - - - - } - /> - - {/* Back-compat: /intelligence → /activity (preserves ?tab= deep links). - Deep links such as ?tab=memory or ?tab=agents still resolve but fall - back to the tasks tab in prod (dev-only tabs are gated inside Activity). */} - } /> + {/* Back-compat: /activity and /intelligence → settings notifications hub. */} + } /> + } /> {/* Connections page lives at /connections (Phase 2 rename from /skills). The old /skills path is kept as a back-compat redirect so bookmarks @@ -177,7 +165,7 @@ const AppRoutes = () => { {/* Back-compat: /routines was an orphaned dead page (superseded by the Cron Jobs settings panel). Redirect to Activity → Automations so any surviving deep links land somewhere sensible. */} - } /> + } /> { } /> - {/* Workflows moved onto the Activity page (Automations tab). Keep the - old /workflows path working as a deep link into that tab. */} - } /> + } /> } /> diff --git a/app/src/components/BottomTabBar.tsx b/app/src/components/BottomTabBar.tsx index 3ef3202c2e..b81109433b 100644 --- a/app/src/components/BottomTabBar.tsx +++ b/app/src/components/BottomTabBar.tsx @@ -1,7 +1,7 @@ import { useEffect, useMemo, useRef, useState } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; -import { AVATAR_MENU_ITEMS, CENTER_TAB, NAV_TABS } from '../config/navConfig'; +import { AVATAR_MENU_ITEMS, NAV_TABS } from '../config/navConfig'; import { useT } from '../lib/i18n/I18nContext'; import { useCoreState } from '../providers/CoreStateProvider'; import { trackEvent } from '../services/analytics'; @@ -16,10 +16,8 @@ import { resolveUserName } from '../utils/userName'; // ── SVG icons, keyed by tab id ──────────────────────────────────────────────── -function TabIcon({ id, large = false }: { id: string; large?: boolean }) { - // Regular pill tabs render small (w-4); the raised center FAB renders large - // (w-6) so its glyph reads as the centerpiece. - const cls = large ? 'w-6 h-6' : 'w-4 h-4'; +function TabIcon({ id }: { id: string }) { + const cls = 'w-4 h-4'; switch (id) { case 'home': return ( @@ -95,8 +93,7 @@ function TabIcon({ id, large = false }: { id: string; large?: boolean }) { ); case 'brain': - // Two symmetric lobes — reads clearly as a brain. Rendered larger and - // white inside the raised center circle. + // Two symmetric lobes — reads clearly as a brain. return ( { ); }; - // The Assistant — a raised circular button rising out of the center of the - // bar. The bg-colored ring fakes a notch cut into the pill's top edge. - // `center-fab` marks the button (test/identification hook); it renders a - // static glow when active — no pulse. - // - // `-my-3` collapses the button's 48px (h-12) layout footprint so it no longer - // forces the nav row taller than the ~32px pill tabs — the bar height is - // driven by the tabs, while `-translate-y-4` still lifts the circle above the - // top edge. Without it the lower half of the raised circle left a dead band - // of empty bar height beneath the tabs. - const renderCenterButton = () => { - const active = isActive(CENTER_TAB.path); - const centerTab = { ...CENTER_TAB, label: t(CENTER_TAB.labelKey) }; - return ( - - ); - }; - - // Home is a normal pill tab now (no longer pinned/icon-only). The regular - // tabs split evenly around the centered Assistant button; only the avatar - // stays pinned to the far-right behind a divider: - // | home · human · brain ( 💬 ) connections · activity · settings | [ avatar ] - const leftTabs = tabs.slice(0, 3); - const rightTabs = tabs.slice(3); + // All tabs render as uniform pill buttons in a single row; the avatar + // stays pinned to the far-right behind a divider. return ( // pointer-events-none on the full-width shell so transparent areas (e.g. @@ -344,9 +306,7 @@ const BottomTabBar = () => { if (!e.currentTarget.contains(e.relatedTarget as Node)) setRevealed(false); }}>
diff --git a/app/src/components/__tests__/BottomTabBar.test.tsx b/app/src/components/__tests__/BottomTabBar.test.tsx index 118954efed..070dc8a604 100644 --- a/app/src/components/__tests__/BottomTabBar.test.tsx +++ b/app/src/components/__tests__/BottomTabBar.test.tsx @@ -1,14 +1,11 @@ /** * Tests for BottomTabBar — verifies that: - * - 6 tabs are rendered (no Rewards tab; Human restored), Activity label is present - * - Assistant tab is present (was "Chat", id stays 'chat', label now 'Assistant') - * - Walkthrough attributes reflect the new ids (tab-connections, tab-activity) + * - 6 tabs are rendered (no Rewards or Activity tab; Human restored; Chat is a regular tab) + * - Chat tab is present (id 'chat', label 'Chat') + * - Walkthrough attributes reflect the new ids (tab-connections) * - Avatar menu opens and shows Account / Billing / Rewards / Invites / Wallet * - Clicking an avatar menu item navigates or opens URL * - The bar is hidden on '/' and '/login' paths - * - * Human tab restored as a first-class entry (after the IA Phase 6 merge into - * Assistant); Chat keeps its "Assistant" label. */ import { configureStore } from '@reduxjs/toolkit'; import { fireEvent, render, screen } from '@testing-library/react'; @@ -167,14 +164,10 @@ describe('BottomTabBar', () => { agentProfilesApiMock.select.mockResolvedValue(testProfiles); }); - it('renders exactly 6 regular tab buttons (Assistant is rendered separately)', async () => { + it('renders exactly 6 regular tab buttons (Chat is a regular tab)', async () => { await renderBottomTabBar('/home'); - // Query only the regular pill tabs inside
)} - {/* Row 1: Textarea with inline ghost completion */} -
- {/* Ghost overlay for inline completion suffix */} -
- {inputValue} - {inlineCompletionSuffix} -
-