519423cb0d
- landing/app/mira/wiki: tag=mira-wiki list now shows all wiki paragraphs (depends on KBDB tag filter exposed in matrix/kbdb commit, separate repo) - landing: app/mira hub + feed split + various WIP from prior sessions - registry/components: claude_api / kbdb_create_block / kbdb_get / km_writer / platform_crypto / auth_oauth2 contracts + main.go (accumulated) - .component-builds: pkg-lock updates + index.ts adjustments (WIP) - .agents/specs/arcrun/frontend-redesign: design notes - docs/test_credentials, docs/user_requirements/arcrun-landing-page: WIP docs - cypher-executor: auth-dispatcher / wasi-shim adjustments (WIP) Includes accumulated work from prior sessions plus the wiki UI tag-filter update that surfaces the AI-generated wiki paragraphs at /mira/wiki. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
93 lines
3.0 KiB
React
93 lines
3.0 KiB
React
// Top nav and sidebar
|
|
|
|
const TopNav = ({ onNav, current }) => {
|
|
const [scrolled, setScrolled] = React.useState(false);
|
|
React.useEffect(() => {
|
|
const onScroll = () => setScrolled(window.scrollY > 8);
|
|
window.addEventListener('scroll', onScroll);
|
|
return () => window.removeEventListener('scroll', onScroll);
|
|
}, []);
|
|
return (
|
|
<nav className={`topnav ${scrolled ? 'scrolled' : ''}`}>
|
|
<div className="flex gap-12" style={{alignItems: 'center'}}>
|
|
<Logo onClick={() => onNav('landing')} />
|
|
<div className="nav-links" style={{marginLeft: 20}}>
|
|
<a>Product</a>
|
|
<a>Docs</a>
|
|
<a>Pricing</a>
|
|
<a>Changelog</a>
|
|
</div>
|
|
</div>
|
|
<div className="flex gap-8" style={{alignItems: 'center'}}>
|
|
<button className="btn btn-ghost" onClick={() => onNav('auth')}>Log in</button>
|
|
<button className="btn btn-primary" onClick={() => onNav('auth')}>
|
|
Get started <Icon name="arrow_right" size={14} />
|
|
</button>
|
|
</div>
|
|
</nav>
|
|
);
|
|
};
|
|
|
|
const Footer = ({ onNav }) => (
|
|
<footer className="footer">
|
|
<div className="flex gap-12" style={{alignItems: 'center'}}>
|
|
<Logo size="sm" />
|
|
<span>© 2026 Arcrun Labs</span>
|
|
</div>
|
|
<div className="footer-links">
|
|
<a>Docs</a>
|
|
<a>Pricing</a>
|
|
<a>Changelog</a>
|
|
<a>Status</a>
|
|
<a>Privacy</a>
|
|
</div>
|
|
</footer>
|
|
);
|
|
|
|
// App shell with sidebar for logged-in screens
|
|
const Sidebar = ({ current, onNav }) => {
|
|
const items = [
|
|
{ id: 'dashboard', label: 'Dashboard', icon: 'home' },
|
|
{ id: 'apps', label: 'Apps', icon: 'grid', count: 6 },
|
|
{ id: 'workflows', label: 'Workflows', icon: 'workflow', count: 12 },
|
|
{ id: 'keys', label: 'API Keys', icon: 'key' },
|
|
{ id: 'docs', label: 'Docs', icon: 'book' },
|
|
];
|
|
const bottom = [
|
|
{ id: 'settings', label: 'Settings', icon: 'settings' },
|
|
];
|
|
return (
|
|
<aside className="sidebar">
|
|
<div className="sidebar-head">
|
|
<Logo size="md" onClick={() => onNav('landing')} />
|
|
</div>
|
|
<div className="sidebar-section">Workspace</div>
|
|
{items.map(it => (
|
|
<div key={it.id}
|
|
className={`sidebar-item ${current === it.id ? 'active' : ''}`}
|
|
onClick={() => onNav(it.id)}>
|
|
<span className="sb-ico"><Icon name={it.icon} size={15} /></span>
|
|
<span>{it.label}</span>
|
|
{it.count != null && <span className="sb-count">{it.count}</span>}
|
|
</div>
|
|
))}
|
|
<div style={{flex: 1}} />
|
|
{bottom.map(it => (
|
|
<div key={it.id} className="sidebar-item" onClick={() => onNav(it.id)}>
|
|
<span className="sb-ico"><Icon name={it.icon} size={15} /></span>
|
|
<span>{it.label}</span>
|
|
</div>
|
|
))}
|
|
<div className="sidebar-foot">
|
|
<div className="avatar-circ">MR</div>
|
|
<div className="meta">
|
|
<div className="name">Maya Rivera</div>
|
|
<div className="email">maya@northwind.co</div>
|
|
</div>
|
|
</div>
|
|
</aside>
|
|
);
|
|
};
|
|
|
|
Object.assign(window, { TopNav, Footer, Sidebar });
|