fix(ui): thème, textes et lisibilité restants de la revue
Les boutons suivent la couleur d’apparence, les libellés trop petits ou trop techniques sont clarifiés, et le catalogue des fournisseurs se met à jour tout seul. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
import { useLanguage } from '@/lib/i18n'
|
||||
import { DashboardWidgetTitleRow } from '@/components/dashboard-widget-title-row'
|
||||
import { MEMORY_ECHO_LEGACY_EN_FALLBACKS } from '@/lib/ai/memory-echo-i18n'
|
||||
import { pathNoteTitle } from '@/lib/dashboard/path-title'
|
||||
|
||||
// ─── Types ─────────────────────────────────────────────
|
||||
|
||||
@@ -104,14 +105,14 @@ function ConnectionDiagram({
|
||||
className="flex-1 min-w-0 p-2.5 rounded-xl border border-border/30 bg-white/80 dark:bg-zinc-900/60 text-start"
|
||||
style={{ borderColor: `${color}30` }}
|
||||
>
|
||||
<p className="text-[10px] font-semibold text-ink dark:text-dark-ink truncate leading-tight">
|
||||
<p className="text-sm font-semibold text-ink dark:text-dark-ink line-clamp-2 leading-tight" title={note1Title}>
|
||||
{note1Title}
|
||||
</p>
|
||||
</div>
|
||||
<div className="shrink-0 flex flex-col items-center gap-0.5 px-1">
|
||||
<div className="w-8 h-px" style={{ background: `linear-gradient(90deg, transparent, ${color}, transparent)` }} />
|
||||
<span
|
||||
className="text-[9px] font-mono font-bold px-2 py-0.5 rounded-full"
|
||||
className="text-[13px] font-medium px-2 py-0.5 rounded-full"
|
||||
style={{ color, backgroundColor: `${color}14`, border: `1px solid ${color}25` }}
|
||||
>
|
||||
{Math.round(score * 100)}%
|
||||
@@ -122,7 +123,7 @@ function ConnectionDiagram({
|
||||
className="flex-1 min-w-0 p-2.5 rounded-xl border border-border/30 bg-white/80 dark:bg-zinc-900/60 text-start"
|
||||
style={{ borderColor: `${color}30` }}
|
||||
>
|
||||
<p className="text-[10px] font-semibold text-ink dark:text-dark-ink truncate leading-tight">
|
||||
<p className="text-sm font-semibold text-ink dark:text-dark-ink line-clamp-2 leading-tight" title={note2Title}>
|
||||
{note2Title}
|
||||
</p>
|
||||
</div>
|
||||
@@ -153,6 +154,7 @@ export interface IntelligenceHubProps {
|
||||
dismissingInsightId: string | null
|
||||
actingBridgeSuggestionKey: string | null
|
||||
prefersReducedMotion: boolean
|
||||
excludeBridgeSuggestionKeys?: string[]
|
||||
}
|
||||
|
||||
// ─── Component ─────────────────────────────────────────
|
||||
@@ -178,6 +180,7 @@ export function IntelligenceHub({
|
||||
dismissingInsightId,
|
||||
actingBridgeSuggestionKey,
|
||||
prefersReducedMotion,
|
||||
excludeBridgeSuggestionKeys,
|
||||
}: IntelligenceHubProps) {
|
||||
const router = useRouter()
|
||||
const { t } = useLanguage()
|
||||
@@ -226,10 +229,13 @@ export function IntelligenceHub({
|
||||
})
|
||||
}
|
||||
|
||||
const hiddenSuggestions = new Set(excludeBridgeSuggestionKeys ?? [])
|
||||
for (const suggestion of bridgeSuggestions) {
|
||||
const key = `${suggestion.clusterAId}-${suggestion.clusterBId}`
|
||||
if (hiddenSuggestions.has(key)) continue
|
||||
items.push({
|
||||
kind: 'suggestion',
|
||||
id: `suggestion-${suggestion.clusterAId}-${suggestion.clusterBId}`,
|
||||
id: `suggestion-${key}`,
|
||||
priority: 80,
|
||||
suggestion,
|
||||
})
|
||||
@@ -245,7 +251,7 @@ export function IntelligenceHub({
|
||||
}
|
||||
|
||||
return items.sort((a, b) => b.priority - a.priority).slice(0, 10)
|
||||
}, [insights, bridgeNotes, bridgeSuggestions, agentActions])
|
||||
}, [insights, bridgeNotes, bridgeSuggestions, agentActions, excludeBridgeSuggestionKeys])
|
||||
|
||||
const counts = useMemo(() => ({
|
||||
all: allItems.length,
|
||||
@@ -302,32 +308,32 @@ export function IntelligenceHub({
|
||||
return (
|
||||
<div className="flex flex-col h-full">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<Sparkles size={12} className="text-indigo-500" />
|
||||
<span className="text-[9px] font-mono font-bold uppercase tracking-wider text-indigo-600 dark:text-indigo-400">
|
||||
<Sparkles size={12} className="text-brand-accent" />
|
||||
<span className="text-[13px] font-medium text-brand-accent">
|
||||
{t('homeDashboard.semanticConnection')}
|
||||
</span>
|
||||
{!insight.viewed && (
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-ochre animate-pulse" />
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-brand-accent animate-pulse" />
|
||||
)}
|
||||
</div>
|
||||
<ConnectionDiagram
|
||||
note1Title={insight.note1.title || t('homeDashboard.untitled')}
|
||||
note2Title={insight.note2.title || t('homeDashboard.untitled')}
|
||||
note1Title={pathNoteTitle(insight.note1.title, insight.note1Excerpt) || t('homeDashboard.untitled')}
|
||||
note2Title={pathNoteTitle(insight.note2.title, insight.note2Excerpt) || t('homeDashboard.untitled')}
|
||||
score={insight.score}
|
||||
/>
|
||||
<p className="text-[11px] text-ink/75 dark:text-dark-ink/75 font-serif italic leading-relaxed line-clamp-3 px-1">
|
||||
<p className="text-sm text-ink/75 dark:text-dark-ink/75 font-serif italic leading-relaxed line-clamp-3 px-1">
|
||||
« {text} »
|
||||
</p>
|
||||
{excerpt && (
|
||||
<p className="text-[9px] text-concrete/80 line-clamp-2 mt-2 px-1 border-s-2 border-indigo-500/20 ps-2">
|
||||
<p className="text-sm text-concrete/80 line-clamp-2 mt-2 px-1 border-s-2 border-brand-accent/20 ps-2">
|
||||
{excerpt}
|
||||
</p>
|
||||
)}
|
||||
<div className="flex items-center gap-1.5 mt-auto pt-3 flex-wrap">
|
||||
<div className="flex items-center gap-1.5 mt-auto pt-3 flex-wrap shrink-0">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onOpenInsightNote(insight, insight.note1.id)}
|
||||
className="inline-flex items-center gap-1 text-[8.5px] font-mono uppercase font-bold px-2.5 py-1.5 rounded-lg bg-indigo-600 text-white hover:bg-indigo-700 transition-colors"
|
||||
className="inline-flex items-center gap-1 text-[13px] font-medium px-2.5 py-1.5 rounded-lg bg-brand-accent text-white hover:bg-brand-accent/90 transition-colors"
|
||||
>
|
||||
<ExternalLink size={9} />
|
||||
{t('homeDashboard.intelOpenNote')}
|
||||
@@ -335,7 +341,7 @@ export function IntelligenceHub({
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onOpenInsightNote(insight, insight.note1.id, insight.note2.id)}
|
||||
className="inline-flex items-center gap-1 text-[8.5px] font-mono uppercase font-bold px-2.5 py-1.5 rounded-lg border border-border/40 hover:border-indigo-400/40 transition-colors"
|
||||
className="inline-flex items-center gap-1 text-[13px] font-medium px-2.5 py-1.5 rounded-lg border border-border/40 hover:border-brand-accent/40 transition-colors"
|
||||
>
|
||||
<GitCompare size={9} />
|
||||
{t('homeDashboard.intelCompare')}
|
||||
@@ -358,19 +364,19 @@ export function IntelligenceHub({
|
||||
|
||||
case 'bridge': {
|
||||
const { bridge } = item
|
||||
const title = bridge.note?.title || t('homeDashboard.untitled')
|
||||
const title = pathNoteTitle(bridge.note?.title, bridge.note?.content) || t('homeDashboard.untitled')
|
||||
const excerpt = bridge.note?.content ? stripHtml(bridge.note.content).slice(0, 160) : ''
|
||||
const names = bridge.clusterNames ?? []
|
||||
return (
|
||||
<div className="flex flex-col h-full">
|
||||
<div className="flex items-center justify-between gap-2 mb-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<Zap size={12} className="text-ochre" />
|
||||
<span className="text-[9px] font-mono font-bold uppercase tracking-wider text-ochre">
|
||||
<Zap size={12} className="text-brand-accent" />
|
||||
<span className="text-[13px] font-medium text-brand-accent">
|
||||
{t('homeDashboard.bridgeNote')}
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-[9px] font-mono font-bold text-ochre bg-ochre/10 px-2 py-0.5 rounded-full">
|
||||
<span className="text-[13px] font-medium text-brand-accent bg-brand-accent/10 px-2 py-0.5 rounded-full">
|
||||
{Math.round(bridge.bridgeScore * 100)}%
|
||||
</span>
|
||||
</div>
|
||||
@@ -379,11 +385,11 @@ export function IntelligenceHub({
|
||||
onClick={() => onNoteSelect(bridge.noteId)}
|
||||
className="text-start group flex-1"
|
||||
>
|
||||
<p className="text-sm font-semibold text-ink dark:text-dark-ink group-hover:text-ochre transition-colors mb-2 leading-snug">
|
||||
<p className="text-sm font-semibold text-ink dark:text-dark-ink group-hover:text-brand-accent transition-colors mb-2 leading-snug">
|
||||
{title}
|
||||
</p>
|
||||
{excerpt && (
|
||||
<p className="text-[10px] text-concrete leading-relaxed line-clamp-3 mb-3">{excerpt}</p>
|
||||
<p className="text-sm text-concrete leading-relaxed line-clamp-3 mb-3">{excerpt}</p>
|
||||
)}
|
||||
{names.length > 0 && (
|
||||
<div className="flex flex-wrap gap-1.5">
|
||||
@@ -396,7 +402,7 @@ export function IntelligenceHub({
|
||||
className="w-1.5 h-1.5 rounded-full"
|
||||
style={{ backgroundColor: CLUSTER_COLORS[i % CLUSTER_COLORS.length] }}
|
||||
/>
|
||||
<span className="text-[8px] font-mono uppercase text-concrete">{name}</span>
|
||||
<span className="text-[13px] text-concrete">{name}</span>
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
@@ -405,7 +411,7 @@ export function IntelligenceHub({
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onNoteSelect(bridge.noteId)}
|
||||
className="mt-3 inline-flex items-center gap-1 text-[8.5px] font-mono uppercase font-bold px-2.5 py-1.5 rounded-lg bg-ochre/90 text-white hover:bg-ochre transition-colors w-fit"
|
||||
className="mt-3 inline-flex items-center gap-1 text-[13px] font-medium px-2.5 py-1.5 rounded-lg bg-brand-accent/90 text-white hover:bg-brand-accent transition-colors w-fit"
|
||||
>
|
||||
<ExternalLink size={9} />
|
||||
{t('homeDashboard.intelOpenNote')}
|
||||
@@ -421,28 +427,28 @@ export function IntelligenceHub({
|
||||
return (
|
||||
<div className="flex flex-col h-full">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<Lightbulb size={12} className="text-violet-500" />
|
||||
<span className="text-[9px] font-mono font-bold uppercase tracking-wider text-violet-600 dark:text-violet-400 truncate">
|
||||
<Lightbulb size={12} className="text-brand-accent" />
|
||||
<span className="text-[13px] font-medium text-brand-accent truncate">
|
||||
{t('homeDashboard.intelMissingLink')}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<span className="px-2 py-1 rounded-lg bg-violet-500/10 text-[9px] font-mono font-bold text-violet-700 dark:text-violet-300 truncate max-w-[45%]">
|
||||
<span className="px-2 py-1 rounded-lg bg-brand-accent/10 text-[13px] font-medium text-brand-accent truncate max-w-[45%]" title={suggestion.clusterAName}>
|
||||
{suggestion.clusterAName}
|
||||
</span>
|
||||
<div className="flex-1 h-px bg-gradient-to-r from-violet-400/40 via-ochre/60 to-violet-400/40" />
|
||||
<span className="px-2 py-1 rounded-lg bg-ochre/10 text-[9px] font-mono font-bold text-ochre truncate max-w-[45%]">
|
||||
<div className="flex-1 h-px bg-gradient-to-r from-brand-accent/40 via-brand-accent/60 to-brand-accent/40" />
|
||||
<span className="px-2 py-1 rounded-lg bg-brand-accent/10 text-[13px] font-medium text-brand-accent truncate max-w-[45%]" title={suggestion.clusterBName}>
|
||||
{suggestion.clusterBName}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-sm font-semibold text-ink dark:text-dark-ink mb-1.5">{suggestion.suggestedTitle}</p>
|
||||
<p className="text-[10px] text-concrete leading-relaxed line-clamp-2 flex-1">{suggestion.suggestedContent}</p>
|
||||
<div className="flex items-center gap-1.5 mt-3 pt-3 border-t border-border/15">
|
||||
<p className="text-sm text-concrete leading-relaxed line-clamp-2 flex-1">{suggestion.suggestedContent}</p>
|
||||
<div className="flex items-center gap-1.5 mt-3 pt-3 border-t border-border/15 shrink-0">
|
||||
<button
|
||||
type="button"
|
||||
disabled={busy}
|
||||
onClick={() => onCreateBridgeSuggestion(suggestion)}
|
||||
className="inline-flex items-center gap-1 text-[8.5px] font-mono uppercase font-bold px-2.5 py-1.5 rounded-lg bg-violet-600 text-white hover:bg-violet-700 transition-colors disabled:opacity-40"
|
||||
className="inline-flex items-center gap-1 text-[13px] font-medium px-2.5 py-1.5 rounded-lg bg-brand-accent text-white hover:bg-brand-accent/90 transition-colors disabled:opacity-40"
|
||||
>
|
||||
{busy ? <Loader2 size={9} className="animate-spin" /> : <Link2 size={9} />}
|
||||
{t('homeDashboard.createBridgeNote')}
|
||||
@@ -451,7 +457,7 @@ export function IntelligenceHub({
|
||||
type="button"
|
||||
disabled={busy}
|
||||
onClick={() => onDismissBridgeSuggestion(suggestion)}
|
||||
className="text-[8.5px] font-mono uppercase px-2 py-1.5 rounded-lg border border-border/30 text-concrete hover:text-rose-500 disabled:opacity-40"
|
||||
className="text-[13px] font-medium px-2 py-1.5 rounded-lg border border-border/30 text-concrete hover:text-rose-500 disabled:opacity-40"
|
||||
>
|
||||
{t('homeDashboard.dismiss')}
|
||||
</button>
|
||||
@@ -465,25 +471,25 @@ export function IntelligenceHub({
|
||||
return (
|
||||
<div className="flex flex-col h-full">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<Bot size={12} className="text-ochre" />
|
||||
<span className="text-[9px] font-mono font-bold uppercase tracking-wider text-ochre">
|
||||
<Bot size={12} className="text-brand-accent" />
|
||||
<span className="text-[13px] font-medium text-brand-accent">
|
||||
{agent.agentName}
|
||||
</span>
|
||||
<span className="text-[8px] font-mono text-concrete/60 ms-auto">
|
||||
<span className="text-[13px] text-concrete/60 ms-auto">
|
||||
{formatRelativeTime(agent.createdAt, t)}
|
||||
</span>
|
||||
</div>
|
||||
{agent.result ? (
|
||||
<p className="text-[11px] text-concrete leading-relaxed line-clamp-4 flex-1">
|
||||
<p className="text-sm text-concrete leading-relaxed line-clamp-4 flex-1">
|
||||
{agent.result}
|
||||
</p>
|
||||
) : (
|
||||
<p className="text-[11px] text-concrete/60 italic flex-1">{t('homeDashboard.intelAgentNoResult')}</p>
|
||||
<p className="text-sm text-concrete/60 italic flex-1">{t('homeDashboard.intelAgentNoResult')}</p>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => router.push('/agents')}
|
||||
className="mt-3 inline-flex items-center gap-1 text-[8.5px] font-mono uppercase font-bold px-2.5 py-1.5 rounded-lg border border-ochre/30 text-ochre hover:bg-ochre/10 transition-colors w-fit"
|
||||
className="mt-3 inline-flex items-center gap-1 text-[13px] font-medium px-2.5 py-1.5 rounded-lg border border-brand-accent/30 text-brand-accent hover:bg-brand-accent/10 transition-colors w-fit"
|
||||
>
|
||||
{t('homeDashboard.intelViewAgent')}
|
||||
<ArrowRight size={9} />
|
||||
@@ -497,10 +503,10 @@ export function IntelligenceHub({
|
||||
const spotlightAccent = (item: IntelItem | null) => {
|
||||
if (!item) return 'from-stone-100/50 to-transparent border-border/30'
|
||||
switch (item.kind) {
|
||||
case 'insight': return 'from-indigo-500/[0.06] via-transparent to-transparent border-indigo-400/25'
|
||||
case 'bridge': return 'from-ochre/[0.06] via-transparent to-transparent border-ochre/25'
|
||||
case 'suggestion': return 'from-violet-500/[0.06] via-transparent to-transparent border-violet-400/25'
|
||||
case 'agent': return 'from-ochre/[0.04] via-transparent to-transparent border-border/30'
|
||||
case 'insight': return 'from-brand-accent/[0.06] via-transparent to-transparent border-brand-accent/25'
|
||||
case 'bridge': return 'from-brand-accent/[0.06] via-transparent to-transparent border-brand-accent/25'
|
||||
case 'suggestion': return 'from-brand-accent/[0.06] via-transparent to-transparent border-brand-accent/25'
|
||||
case 'agent': return 'from-brand-accent/[0.04] via-transparent to-transparent border-border/30'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -518,7 +524,7 @@ export function IntelligenceHub({
|
||||
actions={(
|
||||
<>
|
||||
{newCount > 0 && (
|
||||
<span className="text-[8px] font-mono font-bold text-brand-accent bg-brand-accent/10 px-2 py-0.5 rounded uppercase">
|
||||
<span className="text-[13px] font-medium text-brand-accent bg-brand-accent/10 px-2 py-0.5 rounded">
|
||||
{newCount} {t('homeDashboard.new')}
|
||||
</span>
|
||||
)}
|
||||
@@ -543,7 +549,7 @@ export function IntelligenceHub({
|
||||
<div className="h-[220px] rounded-2xl bg-stone-50 dark:bg-zinc-950/30 animate-pulse" />
|
||||
) : !aiActive ? (
|
||||
<div className="p-5 rounded-2xl border border-dashed border-border/40 bg-stone-50/50 dark:bg-zinc-950/30 text-center space-y-3 min-h-[180px] flex flex-col justify-center">
|
||||
<p className="text-xs text-concrete leading-relaxed">
|
||||
<p className="text-sm text-concrete leading-relaxed">
|
||||
{!hasAiConsent
|
||||
? t('homeDashboard.aiConsentRequired')
|
||||
: !providerReady
|
||||
@@ -554,7 +560,7 @@ export function IntelligenceHub({
|
||||
<button
|
||||
type="button"
|
||||
onClick={onEnableAi}
|
||||
className="text-[9px] font-mono uppercase font-bold px-3 py-1.5 rounded-lg bg-ink text-white dark:bg-white dark:text-black hover:opacity-90 transition-opacity mx-auto"
|
||||
className="text-[13px] font-medium px-3 py-1.5 rounded-lg bg-brand-accent text-white hover:bg-brand-accent/90 transition-colors mx-auto"
|
||||
>
|
||||
{t('homeDashboard.enableAi')}
|
||||
</button>
|
||||
@@ -563,12 +569,12 @@ export function IntelligenceHub({
|
||||
) : allItems.length === 0 ? (
|
||||
<div className="p-5 rounded-2xl border border-dashed border-border/40 bg-stone-50/50 dark:bg-zinc-950/30 text-center space-y-3 min-h-[180px] flex flex-col justify-center">
|
||||
<Brain size={22} className="mx-auto text-concrete/40" strokeWidth={1.25} />
|
||||
<p className="text-xs text-concrete leading-relaxed">{t('homeDashboard.noConnections')}</p>
|
||||
<p className="text-sm text-concrete leading-relaxed">{t('homeDashboard.noConnections')}</p>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onRefreshEcho}
|
||||
disabled={echoRefreshing}
|
||||
className="inline-flex items-center gap-1.5 text-[9px] font-mono uppercase font-bold px-3 py-1.5 rounded-lg border border-ochre/30 text-ochre hover:bg-ochre/10 transition-all disabled:opacity-40 mx-auto"
|
||||
className="inline-flex items-center gap-1.5 text-[13px] font-medium px-3 py-1.5 rounded-lg border border-brand-accent/30 text-brand-accent hover:bg-brand-accent/10 transition-all disabled:opacity-40 mx-auto"
|
||||
>
|
||||
{echoRefreshing ? <Loader2 size={11} className="animate-spin" /> : <Sparkles size={11} />}
|
||||
{t('homeDashboard.analyzeNotes')}
|
||||
@@ -587,15 +593,15 @@ export function IntelligenceHub({
|
||||
key={f.key}
|
||||
type="button"
|
||||
onClick={() => setFilter(f.key)}
|
||||
className={`shrink-0 inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-[8.5px] font-mono font-bold uppercase tracking-wider transition-all ${
|
||||
className={`shrink-0 inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-[13px] font-medium transition-all ${
|
||||
active
|
||||
? 'bg-ink text-white dark:bg-white dark:text-black shadow-sm'
|
||||
? 'bg-brand-accent text-white shadow-sm'
|
||||
: 'bg-stone-100 dark:bg-zinc-800 text-concrete hover:text-ink dark:hover:text-dark-ink'
|
||||
}`}
|
||||
>
|
||||
{f.label}
|
||||
{count > 0 && (
|
||||
<span className={`text-[7px] px-1 py-px rounded-full ${active ? 'bg-white/20' : 'bg-black/5 dark:bg-white/10'}`}>
|
||||
<span className={`text-[13px] px-1.5 py-0.5 rounded-full ${active ? 'bg-white/20' : 'bg-black/5 dark:bg-white/10'}`}>
|
||||
{count}
|
||||
</span>
|
||||
)}
|
||||
@@ -605,7 +611,7 @@ export function IntelligenceHub({
|
||||
</div>
|
||||
|
||||
{filteredItems.length === 0 ? (
|
||||
<p className="text-xs text-concrete italic text-center py-8">{t('homeDashboard.intelFilterEmpty')}</p>
|
||||
<p className="text-sm text-concrete italic text-center py-8">{t('homeDashboard.intelFilterEmpty')}</p>
|
||||
) : (
|
||||
<>
|
||||
{/* Spotlight carousel */}
|
||||
@@ -616,7 +622,7 @@ export function IntelligenceHub({
|
||||
type="button"
|
||||
onClick={goPrev}
|
||||
disabled={activeIndex === 0}
|
||||
className="absolute start-0 top-1/2 -translate-y-1/2 -translate-x-1 z-10 p-1 rounded-full border border-border/40 bg-white/90 dark:bg-zinc-900/90 shadow-sm disabled:opacity-25 hover:border-ochre/40 transition-all"
|
||||
className="absolute start-0 top-1/2 -translate-y-1/2 -translate-x-1 z-10 p-1 rounded-full border border-border/40 bg-white/90 dark:bg-zinc-900/90 shadow-sm disabled:opacity-25 hover:border-brand-accent/40 transition-all"
|
||||
aria-label={t('homeDashboard.intelPrev')}
|
||||
>
|
||||
<ChevronLeft size={14} />
|
||||
@@ -625,7 +631,7 @@ export function IntelligenceHub({
|
||||
type="button"
|
||||
onClick={goNext}
|
||||
disabled={activeIndex >= filteredItems.length - 1}
|
||||
className="absolute end-0 top-1/2 -translate-y-1/2 translate-x-1 z-10 p-1 rounded-full border border-border/40 bg-white/90 dark:bg-zinc-900/90 shadow-sm disabled:opacity-25 hover:border-ochre/40 transition-all"
|
||||
className="absolute end-0 top-1/2 -translate-y-1/2 translate-x-1 z-10 p-1 rounded-full border border-border/40 bg-white/90 dark:bg-zinc-900/90 shadow-sm disabled:opacity-25 hover:border-brand-accent/40 transition-all"
|
||||
aria-label={t('homeDashboard.intelNext')}
|
||||
>
|
||||
<ChevronRight size={14} />
|
||||
@@ -664,14 +670,14 @@ export function IntelligenceHub({
|
||||
onClick={() => setActiveIndex(idx)}
|
||||
className={`rounded-full transition-all ${
|
||||
idx === activeIndex
|
||||
? 'w-5 h-1.5 bg-ochre'
|
||||
? 'w-5 h-1.5 bg-brand-accent'
|
||||
: 'w-1.5 h-1.5 bg-concrete/25 hover:bg-concrete/50'
|
||||
}`}
|
||||
aria-label={t('homeDashboard.intelGoTo', { index: idx + 1 })}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<span className="text-[8px] font-mono text-concrete/60 uppercase">
|
||||
<span className="text-[13px] text-concrete/60">
|
||||
{t('homeDashboard.intelPosition', { current: activeIndex + 1, total: filteredItems.length })}
|
||||
</span>
|
||||
</div>
|
||||
@@ -684,37 +690,39 @@ export function IntelligenceHub({
|
||||
const isActive = idx === activeIndex
|
||||
let label = ''
|
||||
let Icon = Sparkles
|
||||
let accent = 'text-indigo-500'
|
||||
let accent = 'text-brand-accent'
|
||||
if (item.kind === 'insight') {
|
||||
label = item.insight.note1.title?.slice(0, 28) || t('homeDashboard.untitled')
|
||||
label = pathNoteTitle(item.insight.note1.title, item.insight.note1Excerpt) || t('homeDashboard.untitled')
|
||||
Icon = Sparkles
|
||||
accent = 'text-indigo-500'
|
||||
accent = 'text-brand-accent'
|
||||
} else if (item.kind === 'bridge') {
|
||||
label = item.bridge.note?.title?.slice(0, 28) || t('homeDashboard.untitled')
|
||||
label = pathNoteTitle(item.bridge.note?.title, item.bridge.note?.content) || t('homeDashboard.untitled')
|
||||
Icon = Zap
|
||||
accent = 'text-ochre'
|
||||
accent = 'text-brand-accent'
|
||||
} else if (item.kind === 'suggestion') {
|
||||
label = item.suggestion.suggestedTitle.slice(0, 28)
|
||||
label = item.suggestion.suggestedTitle
|
||||
Icon = Lightbulb
|
||||
accent = 'text-violet-500'
|
||||
accent = 'text-brand-accent'
|
||||
} else {
|
||||
label = item.agent.agentName
|
||||
Icon = Bot
|
||||
accent = 'text-ochre'
|
||||
accent = 'text-brand-accent'
|
||||
}
|
||||
return (
|
||||
<button
|
||||
key={item.id}
|
||||
type="button"
|
||||
onClick={() => setActiveIndex(idx)}
|
||||
className={`shrink-0 flex items-center gap-1.5 px-2 py-1.5 rounded-lg border text-start max-w-[130px] transition-all ${
|
||||
title={label}
|
||||
aria-label={label}
|
||||
className={`shrink-0 flex items-center gap-1.5 px-2 py-1.5 rounded-lg border text-start max-w-[180px] transition-all ${
|
||||
isActive
|
||||
? 'border-ochre/40 bg-ochre/5 shadow-sm'
|
||||
? 'border-brand-accent/40 bg-brand-accent/5 shadow-sm'
|
||||
: 'border-border/25 bg-stone-50/50 dark:bg-zinc-950/30 hover:border-border/50'
|
||||
}`}
|
||||
>
|
||||
<Icon size={9} className={`shrink-0 ${accent}`} />
|
||||
<span className="text-[8px] font-medium text-ink dark:text-dark-ink truncate">{label}</span>
|
||||
<span className="text-[13px] font-medium text-ink dark:text-dark-ink truncate">{label}</span>
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
|
||||
Reference in New Issue
Block a user