Files
amc/dashboard/index.html
teernisse da08d7a588 refactor(dashboard): extract modular Preact component structure
Replace the monolithic single-file dashboards (dashboard.html,
dashboard-preact.html) with a proper modular directory structure:

  dashboard/
    index.html              - Entry point, loads main.js
    main.js                 - App bootstrap, mounts <App> to #root
    styles.css              - Global styles (dark theme, typography)
    components/
      App.js                - Root component, state management, polling
      Header.js             - Top bar with refresh/timing info
      Sidebar.js            - Project tree navigation
      SessionCard.js        - Individual session card with status/actions
      SessionGroup.js       - Group sessions by project path
      Modal.js              - Full conversation viewer overlay
      ChatMessages.js       - Message list with role styling
      MessageBubble.js      - Individual message with markdown
      QuestionBlock.js      - User question input with quick options
      EmptyState.js         - "No sessions" placeholder
      OptionButton.js       - Quick response button component
      SimpleInput.js        - Text input with send button
    lib/
      preact.js             - Preact + htm ESM bundle (CDN shim)
      markdown.js           - Lightweight markdown-to-HTML renderer
    utils/
      api.js                - fetch wrappers for /api/* endpoints
      formatting.js         - Time formatting, truncation helpers
      status.js             - Session status logic, action availability

This structure enables:
- Browser-native ES modules (no build step required)
- Component reuse and isolation
- Easier styling and theming
- IDE support for component navigation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-25 15:01:47 -05:00

108 lines
3.6 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Agent Mission Control</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&family=Space+Grotesk:wght@500;600;700&family=IBM+Plex+Mono:wght@400;500&family=IBM+Plex+Sans:wght@400;500;600&display=swap" rel="stylesheet">
<!-- Tailwind CDN -->
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
bg: '#01040b',
surface: '#070d18',
surface2: '#0d1830',
selection: '#223454',
fg: '#e0ebff',
bright: '#fbfdff',
dim: '#8ba3cc',
active: '#5fd0a4',
attention: '#e0b45e',
starting: '#7cb2ff',
done: '#e39a8c',
},
fontFamily: {
display: ['Space Grotesk', 'IBM Plex Sans', 'sans-serif'],
sans: ['IBM Plex Sans', 'system-ui', 'sans-serif'],
mono: ['IBM Plex Mono', 'SFMono-Regular', 'Menlo', 'monospace'],
chat: ['JetBrains Mono', 'IBM Plex Mono', 'monospace'],
},
fontSize: {
micro: ['clamp(0.68rem, 0.05vw + 0.66rem, 0.78rem)', { lineHeight: '1.35' }],
label: ['clamp(0.76rem, 0.07vw + 0.74rem, 0.86rem)', { lineHeight: '1.4' }],
ui: ['clamp(0.84rem, 0.09vw + 0.81rem, 0.94rem)', { lineHeight: '1.45' }],
body: ['clamp(0.88rem, 0.1vw + 0.85rem, 0.98rem)', { lineHeight: '1.55' }],
chat: ['clamp(0.92rem, 0.12vw + 0.89rem, 1.02rem)', { lineHeight: '1.6' }],
},
boxShadow: {
panel: '0 8px 18px rgba(10, 14, 20, 0.28)',
halo: '0 0 0 1px rgba(117, 138, 166, 0.12), 0 6px 14px rgba(10, 14, 20, 0.24)',
},
keyframes: {
float: {
'0%, 100%': { transform: 'translateY(0)' },
'50%': { transform: 'translateY(-4px)' },
},
fadeInUp: {
'0%': { opacity: '0', transform: 'translateY(10px)' },
'100%': { opacity: '1', transform: 'translateY(0)' },
},
},
animation: {
float: 'float 6s ease-in-out infinite',
'fade-in-up': 'fadeInUp 0.35s ease-out',
},
}
},
safelist: [
'bg-attention/30',
'bg-active/30',
'bg-starting/30',
'bg-done/30',
'bg-attention/18',
'bg-active/18',
'bg-starting/18',
'bg-done/18',
'bg-selection/80',
'border-attention/40',
'border-active/40',
'border-starting/40',
'border-done/40',
'border-l-attention',
'border-l-active',
'border-l-starting',
'border-l-done',
'text-attention',
'text-active',
'text-starting',
'text-done',
'border-emerald-500/30',
'bg-emerald-500/10',
'text-emerald-400',
'border-emerald-400/45',
'bg-emerald-500/14',
'text-emerald-300',
'border-violet-500/30',
'bg-violet-500/10',
'text-violet-400',
'border-violet-400/45',
'bg-violet-500/14',
'text-violet-300',
]
}
</script>
<link rel="stylesheet" href="styles.css">
</head>
<body class="min-h-screen text-fg antialiased">
<div id="app"></div>
<script type="module" src="main.js"></script>
</body>
</html>