diff --git a/frontend/src/features/home/components/CardHeader.tsx b/frontend/src/features/home/components/CardHeader.tsx new file mode 100644 index 000000000..73618f791 --- /dev/null +++ b/frontend/src/features/home/components/CardHeader.tsx @@ -0,0 +1,28 @@ +import { Link } from 'react-router-dom' +import { type LucideIcon } from 'lucide-react' + +export function CardHeader({ + title, + icon: Icon, + iconClass, + action, +}: { + title: string + icon?: LucideIcon + iconClass?: string + action?: { label: string; href: string } +}) { + return ( +
+

+ {Icon && } + {title} +

+ {action && ( + + {action.label} + + )} +
+ ) +} diff --git a/frontend/src/features/home/components/ChatHero.tsx b/frontend/src/features/home/components/ChatHero.tsx new file mode 100644 index 000000000..b784d51ad --- /dev/null +++ b/frontend/src/features/home/components/ChatHero.tsx @@ -0,0 +1,81 @@ +import { useState } from 'react' +import { useTranslation } from 'react-i18next' +import { AtSign, Paperclip, Sparkles } from 'lucide-react' +import { useSocAi } from '@/features/soc-ai/SocAiProvider' +import { useSocAiConfigured } from '@/features/soc-ai/lib/useSocAiConfig' +import { IconBtn } from './IconBtn' + +const SUGGESTION_KEYS = ['threatHunt', 'observableTriage', 'writeRule', 'systemStatus'] as const + +export function ChatHero() { + const { t } = useTranslation() + const configured = useSocAiConfigured() + const { submit } = useSocAi() + const [value, setValue] = useState('') + + // Hidden entirely until SOC-AI has a provider configured — same gate the + // floating composer/panel use, so we never show a dead chat box. + if (!configured) return null + + const send = () => { + const text = value.trim() + if (!text) return + submit(text, { openPanel: false, scope: 'home' }) + setValue('') + } + + return ( +
+

{t('home.hero.title')}

+
+
+
+