mirror of
https://github.com/davidkaya/aryx.git
synced 2026-07-24 05:28:46 +02:00
Complete visual overhaul of the Aryx application with the Luminous Depth design language — blue-tinted dark surfaces, brand gradient accents, glass-morphism effects, and refined typography. Design Foundation: - New color system with CSS custom properties for all surfaces, borders, text, accents, and status colors - Typography: Outfit (display), DM Sans (body), JetBrains Mono (code) - Animations: accent-flow, thinking-wave, ambient-glow - Utility classes: glass-surface, glow-border, brand-gradient-bg/text - Light theme with cool-tinted whites and blue-tinted shadows Components Updated: - UI primitives (TextInput, SelectInput, ToggleSwitch, FormField, etc.) - AppShell with ambient glow background - Sidebar with brand gradient selection and accent-flow running bars - ChatPane with semantic phase tinting and gradient user avatars - WelcomePane with nebula background and motion entrance animations - All chat banners (Approval, UserInput, PlanReview, MCP Auth, etc.) - ActivityPanel and RunTimeline with glass-surface cards - Settings panels, modals, and editor shells - TerminalPanel with harmonized ANSI palette - PatternGraph nodes with glass-surface styling - MarkdownComposer toolbar Zero hardcoded zinc/indigo color classes remain in renderer components. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
122 lines
4.8 KiB
TypeScript
122 lines
4.8 KiB
TypeScript
import { memo } from 'react';
|
|
import { Handle, Position, type NodeProps } from '@xyflow/react';
|
|
import { CircleUser, Shuffle, Layers, Radio, Bot } from 'lucide-react';
|
|
|
|
import type { GraphNodeData } from '@renderer/lib/patternGraph';
|
|
import type { PatternGraphNodeKind } from '@shared/domain/pattern';
|
|
import { ProviderIcon } from '@renderer/components/ProviderIcons';
|
|
|
|
const kindIcons: Record<PatternGraphNodeKind, typeof CircleUser> = {
|
|
'user-input': CircleUser,
|
|
'user-output': CircleUser,
|
|
agent: Bot, // fallback when no provider is resolved
|
|
distributor: Shuffle,
|
|
collector: Layers,
|
|
orchestrator: Radio,
|
|
};
|
|
|
|
const kindColors: Record<PatternGraphNodeKind, { bg: string; border: string; text: string }> = {
|
|
'user-input': { bg: 'bg-[var(--color-accent)]/10', border: 'border-[var(--color-accent)]/30', text: 'text-[var(--color-accent-sky)]' },
|
|
'user-output': { bg: 'bg-[var(--color-accent)]/10', border: 'border-[var(--color-accent)]/30', text: 'text-[var(--color-accent-sky)]' },
|
|
agent: { bg: 'bg-[var(--color-surface-2)]/80', border: 'border-[var(--color-border)]/40', text: 'text-[var(--color-text-primary)]' },
|
|
distributor: { bg: 'bg-amber-500/10', border: 'border-amber-500/30', text: 'text-amber-400' },
|
|
collector: { bg: 'bg-amber-500/10', border: 'border-amber-500/30', text: 'text-amber-400' },
|
|
orchestrator: { bg: 'bg-emerald-500/10', border: 'border-emerald-500/30', text: 'text-emerald-400' },
|
|
};
|
|
|
|
function GraphNodeContent({ data, selected }: { data: GraphNodeData; selected: boolean }) {
|
|
const colors = kindColors[data.kind] ?? kindColors.agent;
|
|
const isAgent = data.kind === 'agent';
|
|
|
|
const renderIcon = () => {
|
|
if (isAgent && data.provider) {
|
|
return <ProviderIcon provider={data.provider} className="size-4 shrink-0" />;
|
|
}
|
|
const FallbackIcon = kindIcons[data.kind] ?? Bot;
|
|
return <FallbackIcon className={`size-4 shrink-0 ${colors.text}`} />;
|
|
};
|
|
|
|
return (
|
|
<div
|
|
className={`flex min-w-[120px] items-center gap-2 rounded-xl border px-3 py-2 shadow-md backdrop-blur-sm transition ${
|
|
colors.bg
|
|
} ${selected ? 'ring-2 ring-[var(--color-accent)]/50' : ''} ${colors.border}`}
|
|
>
|
|
{renderIcon()}
|
|
<div className="min-w-0 flex-1">
|
|
<div className={`truncate text-[12px] font-semibold ${colors.text}`}>
|
|
{data.label}
|
|
</div>
|
|
{isAgent && data.modelLabel && (
|
|
<div className="truncate text-[10px] text-[var(--color-text-muted)]">{data.modelLabel}</div>
|
|
)}
|
|
</div>
|
|
{data.readOnly && (
|
|
<span className="ml-1 rounded bg-[var(--color-surface-3)]/50 px-1 py-0.5 text-[8px] font-medium text-[var(--color-text-muted)]">
|
|
SYS
|
|
</span>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const handleStyles = {
|
|
system: '!size-2 !border-[var(--color-border)] !bg-[var(--color-text-secondary)]',
|
|
agent: '!size-2 !border-[var(--color-accent-sky)] !bg-[var(--color-accent)]',
|
|
hidden: '!size-0 !border-0 !bg-transparent !min-w-0 !min-h-0',
|
|
};
|
|
|
|
/* user-input: source only (no incoming handle)
|
|
user-output: target only (no outgoing handle) */
|
|
|
|
export const UserInputNode = memo(function UserInputNode({ data, selected }: NodeProps) {
|
|
const nodeData = data as unknown as GraphNodeData;
|
|
return (
|
|
<>
|
|
<Handle type="target" position={Position.Left} className={handleStyles.hidden} />
|
|
<GraphNodeContent data={nodeData} selected={selected ?? false} />
|
|
<Handle type="source" position={Position.Right} className={handleStyles.system} />
|
|
</>
|
|
);
|
|
});
|
|
|
|
export const UserOutputNode = memo(function UserOutputNode({ data, selected }: NodeProps) {
|
|
const nodeData = data as unknown as GraphNodeData;
|
|
return (
|
|
<>
|
|
<Handle type="target" position={Position.Left} className={handleStyles.system} />
|
|
<GraphNodeContent data={nodeData} selected={selected ?? false} />
|
|
<Handle type="source" position={Position.Right} className={handleStyles.hidden} />
|
|
</>
|
|
);
|
|
});
|
|
|
|
export const SystemNode = memo(function SystemNode({ data, selected }: NodeProps) {
|
|
const nodeData = data as unknown as GraphNodeData;
|
|
return (
|
|
<>
|
|
<Handle type="target" position={Position.Left} className={handleStyles.system} />
|
|
<GraphNodeContent data={nodeData} selected={selected ?? false} />
|
|
<Handle type="source" position={Position.Right} className={handleStyles.system} />
|
|
</>
|
|
);
|
|
});
|
|
|
|
export const AgentNode = memo(function AgentNode({ data, selected }: NodeProps) {
|
|
const nodeData = data as unknown as GraphNodeData;
|
|
return (
|
|
<>
|
|
<Handle type="target" position={Position.Left} className={handleStyles.agent} />
|
|
<GraphNodeContent data={nodeData} selected={selected ?? false} />
|
|
<Handle type="source" position={Position.Right} className={handleStyles.agent} />
|
|
</>
|
|
);
|
|
});
|
|
|
|
export const graphNodeTypes = {
|
|
userInputNode: UserInputNode,
|
|
userOutputNode: UserOutputNode,
|
|
systemNode: SystemNode,
|
|
agentNode: AgentNode,
|
|
};
|