mirror of
https://github.com/crabwise-ai/crabwalk.git
synced 2026-08-14 00:57:52 +00:00
Refactor styles and enhance ActionGraph, ActionNode, and SettingsPanel components
- Simplified styles in the ActionGraph and ActionNode components by removing unnecessary border styles for a cleaner look. - Updated ActionNode to improve text sizing for better readability and consistency. - Enhanced SettingsPanel by streamlining button styles and removing redundant border properties, improving overall UI consistency. - Adjusted layout properties in the SessionList component to enhance responsiveness and visual appeal.
This commit is contained in:
@@ -600,7 +600,9 @@ function ActionGraphInner({
|
||||
proOptions={{ hideAttribution: true }}
|
||||
>
|
||||
<Background color="#252535" gap={24} size={1} />
|
||||
<Controls />
|
||||
<Controls
|
||||
className="bg-shell-900! border-shell-700! shadow-lg! [&>button]:bg-shell-800! [&>button]:border-shell-700! [&>button]:text-gray-300! [&>button:hover]:bg-shell-700! [&>button>svg]:fill-gray-300!"
|
||||
/>
|
||||
<MiniMap
|
||||
nodeColor={(node) => {
|
||||
if (node.type === 'crab') return '#ef4444'
|
||||
@@ -609,6 +611,8 @@ function ActionGraphInner({
|
||||
return '#52526e'
|
||||
}}
|
||||
maskColor="rgba(10, 10, 15, 0.8)"
|
||||
className="bg-shell-900! border-shell-700!"
|
||||
style={{ backgroundColor: '#0a0a0f' }}
|
||||
/>
|
||||
</ReactFlow>
|
||||
</div>
|
||||
|
||||
@@ -159,7 +159,7 @@ export const ActionNode = memo(function ActionNode({
|
||||
{/* Header: Event type + state */}
|
||||
<div className="flex items-center gap-2 mb-1.5">
|
||||
<EventIcon size={12} className="text-shell-500" />
|
||||
<span className="font-display text-[10px] font-medium text-gray-300 uppercase tracking-wide">
|
||||
<span className="font-display text-xs font-medium text-gray-300 uppercase tracking-wide">
|
||||
{eventInfo.label}
|
||||
</span>
|
||||
<StateIcon
|
||||
@@ -169,13 +169,13 @@ export const ActionNode = memo(function ActionNode({
|
||||
</div>
|
||||
|
||||
{/* Timestamp */}
|
||||
<div className="font-console text-[11px] text-shell-500 mb-1.5">
|
||||
<div className="font-console text-xs text-shell-500 mb-1.5">
|
||||
<span className="text-crab-600">></span> {formatTime(data.timestamp)}
|
||||
</div>
|
||||
|
||||
{/* Metadata for complete nodes */}
|
||||
{hasMetadata && (
|
||||
<div className="font-console text-[10px] text-shell-400 mb-1.5 flex gap-2 flex-wrap">
|
||||
<div className="font-console text-xs text-shell-400 mb-1.5 flex gap-2 flex-wrap">
|
||||
{data.duration && (
|
||||
<span className="text-neon-cyan">{formatDuration(data.duration)}</span>
|
||||
)}
|
||||
@@ -197,24 +197,22 @@ export const ActionNode = memo(function ActionNode({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Content - truncated preview or full markdown */}
|
||||
{expanded && fullContent ? (
|
||||
<div className="prose prose-invert prose-sm max-w-none text-gray-300 overflow-auto max-h-[400px]
|
||||
prose-headings:text-gray-200 prose-headings:font-display prose-headings:text-sm
|
||||
prose-p:text-[12px] prose-p:leading-relaxed prose-p:my-1
|
||||
prose-code:text-neon-cyan prose-code:bg-shell-950 prose-code:px-1 prose-code:rounded prose-code:text-[11px]
|
||||
prose-pre:bg-shell-950 prose-pre:border prose-pre:border-shell-800 prose-pre:text-[11px]
|
||||
{/* Content - markdown for both preview and expanded */}
|
||||
{(expanded ? fullContent : truncatedContent) && (
|
||||
<div className={`
|
||||
prose prose-invert prose-sm max-w-none text-gray-300
|
||||
prose-headings:text-gray-200 prose-headings:font-display prose-headings:text-sm prose-headings:my-1
|
||||
prose-p:text-xs prose-p:leading-relaxed prose-p:my-1
|
||||
prose-code:text-neon-cyan prose-code:bg-shell-950 prose-code:px-1 prose-code:rounded prose-code:text-xs
|
||||
prose-pre:bg-shell-950 prose-pre:border prose-pre:border-shell-800 prose-pre:text-xs prose-pre:my-1
|
||||
prose-a:text-neon-lavender prose-a:no-underline hover:prose-a:underline
|
||||
prose-li:text-[12px] prose-li:my-0.5
|
||||
prose-li:text-xs prose-li:my-0.5
|
||||
prose-strong:text-gray-200
|
||||
">
|
||||
<Markdown>{fullContent}</Markdown>
|
||||
${expanded ? 'overflow-auto max-h-[400px]' : 'overflow-hidden max-h-[60px]'}
|
||||
`}>
|
||||
<Markdown>{expanded ? fullContent! : truncatedContent!}</Markdown>
|
||||
</div>
|
||||
) : truncatedContent ? (
|
||||
<div className="font-console text-[10px] text-gray-400 leading-relaxed whitespace-pre-wrap">
|
||||
{truncatedContent}
|
||||
</div>
|
||||
) : null}
|
||||
)}
|
||||
|
||||
{expanded && data.toolArgs != null && (
|
||||
<pre className="mt-2 font-console text-[11px] text-shell-500 bg-shell-950 p-2 rounded border border-shell-800 overflow-auto max-h-32">
|
||||
|
||||
@@ -72,7 +72,7 @@ export function SessionList({
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
className="flex flex-col h-full bg-shell-900 border-r-2 border-shell-700 relative"
|
||||
className="flex flex-col h-full bg-shell-900 relative"
|
||||
initial={false}
|
||||
animate={{ width: collapsed ? 56 : 288 }}
|
||||
transition={{ duration: 0.2, ease: "easeInOut" }}
|
||||
@@ -81,7 +81,7 @@ export function SessionList({
|
||||
<div className="absolute inset-0 texture-scanlines pointer-events-none opacity-50" />
|
||||
|
||||
{/* Header */}
|
||||
<div className="relative p-3 border-b-2 border-shell-700 bg-shell-950/50">
|
||||
<div className="relative p-3 bg-shell-950/50">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
{!collapsed && (
|
||||
<h2 className="font-mono uppercase text-sm text-crab-400 glow-red tracking-wider ml-1">
|
||||
@@ -216,7 +216,7 @@ export function SessionList({
|
||||
</div>
|
||||
|
||||
{/* Footer */}
|
||||
<div className="relative p-2.5 border-t-2 border-shell-700 bg-shell-950/50">
|
||||
<div className="relative p-2.5 bg-shell-950/50">
|
||||
<div
|
||||
className={`font-console text-xs text-shell-500 text-center flex items-center justify-center ${collapsed ? "flex-col gap-3" : "gap-4"}`}
|
||||
>
|
||||
|
||||
@@ -39,9 +39,9 @@ export function SettingsPanel({
|
||||
<>
|
||||
<button
|
||||
onClick={() => setOpen(true)}
|
||||
className="p-2.5 bg-shell-800 hover:bg-shell-700 rounded-lg border-2 border-shell-700 hover:border-shell-600 transition-all group"
|
||||
className="p-2 bg-shell-800 hover:bg-shell-700 rounded-lg transition-all group"
|
||||
>
|
||||
<Settings size={16} className="text-gray-400 group-hover:text-crab-400 transition-colors" />
|
||||
<Settings size={14} className="text-gray-400 group-hover:text-crab-400 transition-colors" />
|
||||
</button>
|
||||
|
||||
<AnimatePresence>
|
||||
@@ -62,7 +62,7 @@ export function SettingsPanel({
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
exit={{ opacity: 0, x: 300 }}
|
||||
transition={{ type: 'spring', damping: 30, stiffness: 300 }}
|
||||
className="fixed right-0 top-0 h-full w-80 bg-shell-900 border-l-2 border-shell-700 z-50 p-5 overflow-y-auto"
|
||||
className="fixed right-0 top-0 h-full w-80 bg-shell-900 z-50 p-5 overflow-y-auto"
|
||||
>
|
||||
{/* Texture overlay */}
|
||||
<div className="absolute inset-0 texture-scanlines pointer-events-none opacity-30" />
|
||||
@@ -74,7 +74,7 @@ export function SettingsPanel({
|
||||
</h2>
|
||||
<button
|
||||
onClick={() => setOpen(false)}
|
||||
className="p-2 hover:bg-shell-800 rounded-lg border border-transparent hover:border-shell-600 transition-all"
|
||||
className="p-2 hover:bg-shell-800 rounded-lg transition-all"
|
||||
>
|
||||
<X size={18} className="text-gray-400" />
|
||||
</button>
|
||||
@@ -98,7 +98,7 @@ export function SettingsPanel({
|
||||
{connected ? (
|
||||
<button
|
||||
onClick={onDisconnect}
|
||||
className="flex-1 px-4 py-2 font-display text-xs uppercase tracking-wide bg-crab-600 hover:bg-crab-500 border-2 border-crab-500 rounded-lg transition-all"
|
||||
className="flex-1 px-4 py-2 font-display text-xs uppercase tracking-wide bg-crab-600 hover:bg-crab-500 rounded-lg transition-all"
|
||||
style={{ boxShadow: '0 2px 0 0 #991b1b' }}
|
||||
>
|
||||
Disconnect
|
||||
@@ -106,7 +106,7 @@ export function SettingsPanel({
|
||||
) : (
|
||||
<button
|
||||
onClick={onConnect}
|
||||
className="flex-1 px-4 py-2 font-display text-xs uppercase tracking-wide bg-neon-mint/20 hover:bg-neon-mint/30 border-2 border-neon-mint/50 text-neon-mint rounded-lg transition-all"
|
||||
className="flex-1 px-4 py-2 font-display text-xs uppercase tracking-wide bg-neon-mint/20 hover:bg-neon-mint/30 text-neon-mint rounded-lg transition-all"
|
||||
>
|
||||
Connect
|
||||
</button>
|
||||
@@ -114,7 +114,7 @@ export function SettingsPanel({
|
||||
<button
|
||||
onClick={onRefresh}
|
||||
disabled={!connected}
|
||||
className="px-3 py-2 bg-shell-800 hover:bg-shell-700 border-2 border-shell-700 rounded-lg transition-all disabled:opacity-40 disabled:cursor-not-allowed"
|
||||
className="px-3 py-2 bg-shell-800 hover:bg-shell-700 rounded-lg transition-all disabled:opacity-40 disabled:cursor-not-allowed"
|
||||
>
|
||||
<RefreshCw size={14} className="text-gray-400" />
|
||||
</button>
|
||||
@@ -136,10 +136,10 @@ export function SettingsPanel({
|
||||
|
||||
<button
|
||||
onClick={() => onHistoricalModeChange(!historicalMode)}
|
||||
className={`w-full px-4 py-2 font-display text-xs uppercase tracking-wide rounded-lg border-2 transition-all ${
|
||||
className={`w-full px-4 py-2 font-display text-xs uppercase tracking-wide rounded-lg transition-all ${
|
||||
historicalMode
|
||||
? 'bg-crab-600 border-crab-500 text-white box-glow-red'
|
||||
: 'bg-shell-800 border-shell-700 text-gray-400 hover:border-shell-600'
|
||||
? 'bg-crab-600 text-white box-glow-red'
|
||||
: 'bg-shell-800 text-gray-400 hover:bg-shell-700'
|
||||
}`}
|
||||
>
|
||||
{historicalMode ? 'Enabled' : 'Disabled'}
|
||||
@@ -161,10 +161,10 @@ export function SettingsPanel({
|
||||
|
||||
<button
|
||||
onClick={() => onDebugModeChange(!debugMode)}
|
||||
className={`w-full px-4 py-2 font-display text-xs uppercase tracking-wide rounded-lg border-2 transition-all ${
|
||||
className={`w-full px-4 py-2 font-display text-xs uppercase tracking-wide rounded-lg transition-all ${
|
||||
debugMode
|
||||
? 'bg-neon-lavender/30 border-neon-lavender/50 text-neon-lavender'
|
||||
: 'bg-shell-800 border-shell-700 text-gray-400 hover:border-shell-600'
|
||||
? 'bg-neon-lavender/30 text-neon-lavender'
|
||||
: 'bg-shell-800 text-gray-400 hover:bg-shell-700'
|
||||
}`}
|
||||
>
|
||||
{debugMode ? 'Enabled' : 'Disabled'}
|
||||
@@ -192,10 +192,10 @@ export function SettingsPanel({
|
||||
|
||||
<button
|
||||
onClick={() => onLogCollectionChange(!logCollection)}
|
||||
className={`w-full px-4 py-2 font-display text-xs uppercase tracking-wide rounded-lg border-2 transition-all mb-2 ${
|
||||
className={`w-full px-4 py-2 font-display text-xs uppercase tracking-wide rounded-lg transition-all mb-2 ${
|
||||
logCollection
|
||||
? 'bg-neon-mint/20 border-neon-mint/50 text-neon-mint'
|
||||
: 'bg-shell-800 border-shell-700 text-gray-400 hover:border-shell-600'
|
||||
? 'bg-neon-mint/20 text-neon-mint'
|
||||
: 'bg-shell-800 text-gray-400 hover:bg-shell-700'
|
||||
}`}
|
||||
>
|
||||
{logCollection ? 'Recording...' : 'Start Recording'}
|
||||
@@ -205,7 +205,7 @@ export function SettingsPanel({
|
||||
<button
|
||||
onClick={onDownloadLogs}
|
||||
disabled={logCount === 0}
|
||||
className="flex-1 flex items-center justify-center gap-2 px-3 py-2 font-display text-xs uppercase tracking-wide bg-shell-800 hover:bg-shell-700 border-2 border-shell-700 rounded-lg transition-all disabled:opacity-40 disabled:cursor-not-allowed"
|
||||
className="flex-1 flex items-center justify-center gap-2 px-3 py-2 font-display text-xs uppercase tracking-wide bg-shell-800 hover:bg-shell-700 rounded-lg transition-all disabled:opacity-40 disabled:cursor-not-allowed"
|
||||
>
|
||||
<Download size={12} />
|
||||
Save
|
||||
@@ -213,7 +213,7 @@ export function SettingsPanel({
|
||||
<button
|
||||
onClick={onClearLogs}
|
||||
disabled={logCount === 0}
|
||||
className="flex-1 flex items-center justify-center gap-2 px-3 py-2 font-display text-xs uppercase tracking-wide bg-shell-800 hover:bg-crab-900/50 border-2 border-shell-700 hover:border-crab-700 rounded-lg transition-all disabled:opacity-40 disabled:cursor-not-allowed"
|
||||
className="flex-1 flex items-center justify-center gap-2 px-3 py-2 font-display text-xs uppercase tracking-wide bg-shell-800 hover:bg-crab-900/50 rounded-lg transition-all disabled:opacity-40 disabled:cursor-not-allowed"
|
||||
>
|
||||
<Trash2 size={12} />
|
||||
Clear
|
||||
|
||||
@@ -24,9 +24,6 @@ export const Route = createFileRoute('/monitor/')({
|
||||
component: MonitorPageWrapper,
|
||||
})
|
||||
|
||||
// Mobile breakpoint
|
||||
const MOBILE_BREAKPOINT = 768
|
||||
|
||||
// Wrapper to ensure client-only rendering (useLiveQuery needs client)
|
||||
function MonitorPageWrapper() {
|
||||
const [mounted, setMounted] = useState(false)
|
||||
@@ -67,13 +64,8 @@ function MonitorPage() {
|
||||
const [logCount, setLogCount] = useState(0)
|
||||
const [selectedSession, setSelectedSession] = useState<string | null>(null)
|
||||
|
||||
// Sidebar collapse state - default to collapsed on mobile
|
||||
const [sidebarCollapsed, setSidebarCollapsed] = useState(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
return window.innerWidth < MOBILE_BREAKPOINT
|
||||
}
|
||||
return false
|
||||
})
|
||||
// Sidebar collapse state - default to collapsed
|
||||
const [sidebarCollapsed, setSidebarCollapsed] = useState(true)
|
||||
|
||||
// Live queries from TanStack DB collections
|
||||
const sessionsQuery = useLiveQuery(sessionsCollection)
|
||||
@@ -82,16 +74,6 @@ function MonitorPage() {
|
||||
const sessions = sessionsQuery.data ?? []
|
||||
const actions = actionsQuery.data ?? []
|
||||
|
||||
// Auto-collapse sidebar on mobile resize
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
const isMobile = window.innerWidth < MOBILE_BREAKPOINT
|
||||
setSidebarCollapsed(isMobile)
|
||||
}
|
||||
|
||||
window.addEventListener('resize', handleResize)
|
||||
return () => window.removeEventListener('resize', handleResize)
|
||||
}, [])
|
||||
|
||||
// Check connection status on mount
|
||||
useEffect(() => {
|
||||
@@ -266,7 +248,7 @@ function MonitorPage() {
|
||||
return (
|
||||
<div className="h-screen flex flex-col bg-shell-950 text-white overflow-hidden">
|
||||
{/* Header */}
|
||||
<header className="flex items-center justify-between px-4 py-3 bg-shell-900 border-b-2 border-shell-700 relative">
|
||||
<header className="flex items-center justify-between px-4 py-3 bg-shell-900 relative">
|
||||
{/* Gradient accent */}
|
||||
<div className="absolute inset-0 bg-linear-to-r from-crab-950/20 via-transparent to-transparent pointer-events-none" />
|
||||
|
||||
@@ -311,7 +293,7 @@ function MonitorPage() {
|
||||
)}
|
||||
|
||||
{/* Stats display */}
|
||||
<div className="hidden sm:flex items-center gap-3 px-3 py-1.5 bg-shell-800/50 border border-shell-700 rounded-lg">
|
||||
<div className="hidden sm:flex items-center gap-3 px-3 py-1.5 bg-shell-800/50 rounded-lg">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="font-console text-[10px] text-shell-500 uppercase">Sessions</span>
|
||||
<span className="font-display text-sm text-neon-mint">{sessions.length}</span>
|
||||
|
||||
+2
-2
@@ -268,14 +268,14 @@ code, pre {
|
||||
RETRO PANELS & CARDS
|
||||
============================================================================= */
|
||||
.panel-retro {
|
||||
@apply bg-shell-900 border-2 border-shell-700 rounded-lg;
|
||||
@apply bg-shell-900 rounded-lg;
|
||||
box-shadow:
|
||||
0 4px 20px rgba(0, 0, 0, 0.4),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.03);
|
||||
}
|
||||
|
||||
.panel-crab {
|
||||
@apply bg-linear-to-br from-shell-900 to-shell-950 border-2 border-crab-900/50 rounded-lg;
|
||||
@apply bg-linear-to-br from-shell-900 to-shell-950 rounded-lg;
|
||||
box-shadow:
|
||||
0 0 30px rgba(239, 68, 68, 0.1),
|
||||
0 4px 20px rgba(0, 0, 0, 0.4),
|
||||
|
||||
Reference in New Issue
Block a user