diff --git a/app/src/components/BottomTabBar.tsx b/app/src/components/BottomTabBar.tsx index 40072ca73..c87ed4d70 100644 --- a/app/src/components/BottomTabBar.tsx +++ b/app/src/components/BottomTabBar.tsx @@ -127,7 +127,6 @@ const makeTabs = (t: (key: string) => string) => [ const BottomTabBar = () => { const { t } = useT(); - const tabs = useMemo(() => makeTabs(t), [t]); const location = useLocation(); const navigate = useNavigate(); const { snapshot } = useCoreState(); @@ -142,6 +141,7 @@ const BottomTabBar = () => { // so an absent theme branch can't crash the bar. const tabBarLabels = useAppSelector(state => state.theme?.tabBarLabels ?? 'hover'); const labelsAlwaysVisible = tabBarLabels === 'always'; + const tabs = useMemo(() => makeTabs(t), [t]); const hiddenPaths = ['/', '/login']; if ( diff --git a/app/src/components/EmptyStateCard.tsx b/app/src/components/EmptyStateCard.tsx new file mode 100644 index 000000000..756cf1387 --- /dev/null +++ b/app/src/components/EmptyStateCard.tsx @@ -0,0 +1,54 @@ +import type { ReactNode } from 'react'; + +interface EmptyStateCardProps { + icon: ReactNode; + title: string; + description: string; + actionLabel?: string; + onAction?: () => void; + footer?: ReactNode; + className?: string; +} + +const EmptyStateCard = ({ + icon, + title, + description, + actionLabel, + onAction, + footer, + className = '', +}: EmptyStateCardProps) => { + return ( +
+ {description} +
+ {actionLabel && onAction ? ( + + ) : null} + {footer} ++ {t('settings.composio.modeDirect')} +
++ {t( + 'settings.composio.directOnlyDesc', + 'Managed Composio auth is unavailable here. Enter your own Composio API key or skip this for now.' + )} +
+{t('settings.search.description')}
+ {isLocalSession && ( +- {t('skills.mcpComingSoon.description')} -
- - {t('common.comingSoon')} - -- {t('skills.noResults')} -
)} + {!showLocalComposioApiKeyBanner && ( ++ {t('skills.noResults')} +
+ ))}+ {localLoginError} +
+ ) : null}