jettypod 4.4.118 → 4.4.121
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env +4 -3
- package/Cargo.lock +6450 -0
- package/Cargo.toml +35 -0
- package/README.md +5 -1
- package/TAURI-MIGRATION-PLAN.md +840 -0
- package/apps/dashboard/app/connect-claude/page.tsx +5 -6
- package/apps/dashboard/app/decision/[id]/page.tsx +63 -58
- package/apps/dashboard/app/demo/gates/page.tsx +43 -45
- package/apps/dashboard/app/design-system/page.tsx +868 -0
- package/apps/dashboard/app/globals.css +80 -4
- package/apps/dashboard/app/install-claude/page.tsx +4 -6
- package/apps/dashboard/app/login/page.tsx +72 -54
- package/apps/dashboard/app/page.tsx +101 -48
- package/apps/dashboard/app/settings/page.tsx +61 -13
- package/apps/dashboard/app/signup/page.tsx +242 -0
- package/apps/dashboard/app/subscribe/page.tsx +0 -2
- package/apps/dashboard/app/tests/page.tsx +37 -4
- package/apps/dashboard/app/welcome/page.tsx +13 -16
- package/apps/dashboard/app/work/[id]/page.tsx +117 -118
- package/apps/dashboard/app/work/[id]/proof/page.tsx +1489 -0
- package/apps/dashboard/components/AppShell.tsx +92 -85
- package/apps/dashboard/components/CardMenu.tsx +45 -12
- package/apps/dashboard/components/ClaudePanel.tsx +771 -850
- package/apps/dashboard/components/ClaudePanelInput.tsx +43 -15
- package/apps/dashboard/components/ConnectClaudeScreen.tsx +17 -34
- package/apps/dashboard/components/CopyableId.tsx +3 -4
- package/apps/dashboard/components/DetailReviewActions.tsx +100 -0
- package/apps/dashboard/components/DragContext.tsx +134 -63
- package/apps/dashboard/components/DraggableCard.tsx +3 -5
- package/apps/dashboard/components/DropZone.tsx +6 -7
- package/apps/dashboard/components/EditableDetailDescription.tsx +7 -13
- package/apps/dashboard/components/EditableDetailTitle.tsx +6 -13
- package/apps/dashboard/components/EditableTitle.tsx +26 -7
- package/apps/dashboard/components/ElapsedTimer.tsx +66 -0
- package/apps/dashboard/components/EpicGroup.tsx +359 -0
- package/apps/dashboard/components/GateCard.tsx +79 -17
- package/apps/dashboard/components/GateChoiceCard.tsx +15 -18
- package/apps/dashboard/components/InstallClaudeScreen.tsx +15 -32
- package/apps/dashboard/components/JettyLoader.tsx +37 -0
- package/apps/dashboard/components/KanbanBoard.tsx +368 -958
- package/apps/dashboard/components/KanbanCard.tsx +740 -0
- package/apps/dashboard/components/LazyCard.tsx +62 -0
- package/apps/dashboard/components/LazyMarkdown.tsx +11 -0
- package/apps/dashboard/components/MainNav.tsx +38 -73
- package/apps/dashboard/components/MessageBlock.tsx +468 -0
- package/apps/dashboard/components/ModeStartCard.tsx +15 -16
- package/apps/dashboard/components/OnboardingWelcome.tsx +213 -0
- package/apps/dashboard/components/PlaceholderCard.tsx +3 -4
- package/apps/dashboard/components/ProjectSwitcher.tsx +30 -30
- package/apps/dashboard/components/PrototypeTimeline.tsx +72 -51
- package/apps/dashboard/components/RealTimeKanbanWrapper.tsx +406 -388
- package/apps/dashboard/components/RealTimeTestsWrapper.tsx +373 -235
- package/apps/dashboard/components/ReviewFooter.tsx +139 -0
- package/apps/dashboard/components/SessionList.tsx +19 -19
- package/apps/dashboard/components/SubscribeContent.tsx +91 -47
- package/apps/dashboard/components/TestTree.tsx +16 -16
- package/apps/dashboard/components/TipCard.tsx +16 -17
- package/apps/dashboard/components/Toast.tsx +5 -6
- package/apps/dashboard/components/TypeIcon.tsx +55 -0
- package/apps/dashboard/components/ViewModeToolbar.tsx +104 -0
- package/apps/dashboard/components/WaveCompletionAnimation.tsx +52 -65
- package/apps/dashboard/components/WelcomeScreen.tsx +19 -35
- package/apps/dashboard/components/WorkItemHeader.tsx +4 -5
- package/apps/dashboard/components/WorkItemTree.tsx +11 -32
- package/apps/dashboard/components/settings/AccountSection.tsx +55 -35
- package/apps/dashboard/components/settings/AiContextSection.tsx +89 -0
- package/apps/dashboard/components/settings/ContextDocumentsSection.tsx +317 -0
- package/apps/dashboard/components/settings/EnvVarsSection.tsx +74 -152
- package/apps/dashboard/components/settings/GeneralSection.tsx +162 -56
- package/apps/dashboard/components/settings/ProjectStackSection.tsx +948 -0
- package/apps/dashboard/components/settings/SettingsLayout.tsx +4 -5
- package/apps/dashboard/components/ui/Button.tsx +104 -0
- package/apps/dashboard/components/ui/Input.tsx +78 -0
- package/apps/dashboard/components.json +1 -1
- package/apps/dashboard/contexts/ClaudeSessionContext.tsx +711 -418
- package/apps/dashboard/contexts/ConnectionStatusContext.tsx +25 -5
- package/apps/dashboard/contexts/UsageContext.tsx +87 -32
- package/apps/dashboard/dev.sh +35 -0
- package/apps/dashboard/eslint.config.mjs +9 -9
- package/apps/dashboard/hooks/useKanbanAnimation.ts +29 -0
- package/apps/dashboard/hooks/useKanbanUndo.ts +83 -0
- package/apps/dashboard/hooks/useWebSocket.ts +138 -83
- package/apps/dashboard/index.html +73 -0
- package/apps/dashboard/lib/constants.ts +43 -0
- package/apps/dashboard/lib/data-bridge.ts +722 -0
- package/apps/dashboard/lib/db.ts +69 -1265
- package/apps/dashboard/lib/environment-config.ts +173 -0
- package/apps/dashboard/lib/environment-verification.ts +119 -0
- package/apps/dashboard/lib/kanban-utils.ts +270 -0
- package/apps/dashboard/lib/proof-run.ts +495 -0
- package/apps/dashboard/lib/proof-scenario-runner.ts +346 -0
- package/apps/dashboard/lib/run-migrations.js +27 -2
- package/apps/dashboard/lib/service-recovery.ts +326 -0
- package/apps/dashboard/lib/session-state-machine.ts +1 -0
- package/apps/dashboard/lib/session-state-utils.ts +0 -164
- package/apps/dashboard/lib/session-stream-manager.ts +308 -134
- package/apps/dashboard/lib/shadows.ts +7 -0
- package/apps/dashboard/lib/stream-manager-registry.ts +46 -6
- package/apps/dashboard/lib/tauri-bridge.ts +102 -0
- package/apps/dashboard/lib/tauri.ts +106 -0
- package/apps/dashboard/lib/utils.ts +6 -0
- package/apps/dashboard/next-env.d.ts +1 -1
- package/apps/dashboard/package.json +21 -32
- package/apps/dashboard/public/bug-icon.png +0 -0
- package/apps/dashboard/public/buoy-icon.png +0 -0
- package/apps/dashboard/public/fonts/Satoshi-Variable.woff2 +0 -0
- package/apps/dashboard/public/fonts/Satoshi-VariableItalic.woff2 +0 -0
- package/apps/dashboard/public/in-flight-seagull.png +0 -0
- package/apps/dashboard/public/jetty-icon-loading-alt.svg +11 -0
- package/apps/dashboard/public/jetty-icon-loading.svg +11 -0
- package/apps/dashboard/public/jettypod_logo.png +0 -0
- package/apps/dashboard/public/pier-icon.png +0 -0
- package/apps/dashboard/public/star-icon.png +0 -0
- package/apps/dashboard/public/wrench-icon.png +0 -0
- package/apps/dashboard/scripts/tauri-build.js +228 -0
- package/apps/dashboard/scripts/upload-tauri-to-r2.js +125 -0
- package/apps/dashboard/scripts/ws-server.js +191 -0
- package/apps/dashboard/src/main.tsx +12 -0
- package/apps/dashboard/src/router.tsx +107 -0
- package/apps/dashboard/src/vite-env.d.ts +1 -0
- package/apps/dashboard/tsconfig.json +7 -12
- package/apps/dashboard/tsconfig.tsbuildinfo +1 -1
- package/apps/dashboard/vite.config.ts +33 -0
- package/apps/update-server/src/index.ts +228 -80
- package/claude-hooks/global-guardrails.js +14 -13
- package/crates/jettypod-cli/Cargo.toml +19 -0
- package/crates/jettypod-cli/src/commands.rs +1249 -0
- package/crates/jettypod-cli/src/main.rs +595 -0
- package/crates/jettypod-core/Cargo.toml +26 -0
- package/crates/jettypod-core/build.rs +98 -0
- package/crates/jettypod-core/migrations/V1__baseline.sql +197 -0
- package/crates/jettypod-core/migrations/V2__work_items_indexes.sql +6 -0
- package/crates/jettypod-core/migrations/V3__qa_steps.sql +2 -0
- package/crates/jettypod-core/src/auth.rs +294 -0
- package/crates/jettypod-core/src/config.rs +397 -0
- package/crates/jettypod-core/src/db/mod.rs +507 -0
- package/crates/jettypod-core/src/db/recovery.rs +114 -0
- package/crates/jettypod-core/src/db/startup.rs +101 -0
- package/crates/jettypod-core/src/db/validate.rs +149 -0
- package/crates/jettypod-core/src/error.rs +76 -0
- package/crates/jettypod-core/src/git.rs +458 -0
- package/crates/jettypod-core/src/lib.rs +20 -0
- package/crates/jettypod-core/src/sessions.rs +625 -0
- package/crates/jettypod-core/src/skills.rs +556 -0
- package/crates/jettypod-core/src/work.rs +1086 -0
- package/crates/jettypod-core/src/worktree.rs +628 -0
- package/crates/jettypod-core/src/ws.rs +767 -0
- package/cucumber-test.cjs +6 -0
- package/cucumber.js +9 -3
- package/docs/COMMAND_REFERENCE.md +34 -0
- package/hooks/post-checkout +32 -75
- package/hooks/post-merge +111 -10
- package/jest.setup.js +1 -0
- package/jettypod.js +145 -116
- package/lib/bdd-preflight.js +96 -0
- package/lib/chore-taxonomy.js +33 -10
- package/lib/database.js +36 -16
- package/lib/db-watcher.js +1 -1
- package/lib/git-hooks/pre-commit +1 -1
- package/lib/jettypod-backup.js +27 -4
- package/lib/merge-lock.js +111 -253
- package/lib/migrations/027-plan-at-creation-column.js +3 -1
- package/lib/migrations/029-remove-autoincrement.js +307 -0
- package/lib/migrations/029-rename-corrupted-to-cleaned.js +149 -0
- package/lib/migrations/030-rejection-round-columns.js +54 -0
- package/lib/migrations/031-session-isolation-index.js +17 -0
- package/lib/migrations/index.js +47 -4
- package/lib/schema.js +10 -5
- package/lib/seed-onboarding.js +1 -1
- package/lib/update-command/index.js +9 -175
- package/lib/work-commands/index.js +144 -19
- package/lib/work-tracking/index.js +148 -27
- package/lib/worktree-diagnostics.js +16 -16
- package/lib/worktree-facade.js +1 -1
- package/lib/worktree-manager.js +8 -8
- package/lib/worktree-reconciler.js +5 -5
- package/package.json +9 -2
- package/scripts/ndjson-to-cucumber-json.js +152 -0
- package/scripts/postinstall.js +25 -0
- package/skills-templates/bug-mode/SKILL.md +79 -20
- package/skills-templates/bug-planning/SKILL.md +25 -29
- package/skills-templates/chore-mode/SKILL.md +171 -69
- package/skills-templates/chore-mode/verification.js +51 -10
- package/skills-templates/chore-planning/SKILL.md +47 -18
- package/skills-templates/design-system-selection/SKILL.md +273 -0
- package/skills-templates/epic-planning/SKILL.md +82 -48
- package/skills-templates/external-transition/SKILL.md +47 -47
- package/skills-templates/feature-planning/SKILL.md +173 -74
- package/skills-templates/production-mode/SKILL.md +69 -49
- package/skills-templates/request-routing/SKILL.md +4 -4
- package/skills-templates/simple-improvement/SKILL.md +74 -29
- package/skills-templates/speed-mode/SKILL.md +217 -141
- package/skills-templates/stable-mode/SKILL.md +148 -89
- package/apps/dashboard/README.md +0 -36
- package/apps/dashboard/app/api/claude/[workItemId]/message/route.ts +0 -386
- package/apps/dashboard/app/api/claude/[workItemId]/pin/route.ts +0 -24
- package/apps/dashboard/app/api/claude/[workItemId]/route.ts +0 -167
- package/apps/dashboard/app/api/claude/sessions/[sessionId]/content/route.ts +0 -52
- package/apps/dashboard/app/api/claude/sessions/[sessionId]/message/route.ts +0 -378
- package/apps/dashboard/app/api/claude/sessions/[sessionId]/pin/route.ts +0 -24
- package/apps/dashboard/app/api/claude/sessions/cleanup/route.ts +0 -34
- package/apps/dashboard/app/api/claude/sessions/route.ts +0 -184
- package/apps/dashboard/app/api/decisions/[id]/route.ts +0 -25
- package/apps/dashboard/app/api/internal/set-project/route.ts +0 -17
- package/apps/dashboard/app/api/kanban/route.ts +0 -15
- package/apps/dashboard/app/api/settings/env-vars/route.ts +0 -125
- package/apps/dashboard/app/api/settings/general/route.ts +0 -21
- package/apps/dashboard/app/api/tests/route.ts +0 -9
- package/apps/dashboard/app/api/tests/run/route.ts +0 -82
- package/apps/dashboard/app/api/tests/run/stream/route.ts +0 -71
- package/apps/dashboard/app/api/tests/undefined/route.ts +0 -9
- package/apps/dashboard/app/api/usage/route.ts +0 -17
- package/apps/dashboard/app/api/work/[id]/description/route.ts +0 -21
- package/apps/dashboard/app/api/work/[id]/epic/route.ts +0 -21
- package/apps/dashboard/app/api/work/[id]/order/route.ts +0 -21
- package/apps/dashboard/app/api/work/[id]/status/route.ts +0 -21
- package/apps/dashboard/app/api/work/[id]/title/route.ts +0 -21
- package/apps/dashboard/app/layout.tsx +0 -43
- package/apps/dashboard/components/UpgradeBanner.tsx +0 -29
- package/apps/dashboard/electron/ipc-handlers.js +0 -1028
- package/apps/dashboard/electron/main.js +0 -2124
- package/apps/dashboard/electron/preload.js +0 -123
- package/apps/dashboard/electron/session-manager.js +0 -141
- package/apps/dashboard/electron-builder.config.js +0 -357
- package/apps/dashboard/hooks/useClaudeSessions.ts +0 -299
- package/apps/dashboard/lib/claude-process-manager.ts +0 -492
- package/apps/dashboard/lib/db-bridge.ts +0 -282
- package/apps/dashboard/lib/prototypes.ts +0 -202
- package/apps/dashboard/lib/test-results-db.ts +0 -307
- package/apps/dashboard/lib/tests.ts +0 -282
- package/apps/dashboard/next.config.js +0 -50
- package/apps/dashboard/postcss.config.mjs +0 -7
- package/apps/dashboard/public/file.svg +0 -1
- package/apps/dashboard/public/globe.svg +0 -1
- package/apps/dashboard/public/next.svg +0 -1
- package/apps/dashboard/public/vercel.svg +0 -1
- package/apps/dashboard/public/window.svg +0 -1
- package/apps/dashboard/scripts/download-node.js +0 -104
- package/apps/dashboard/scripts/upload-to-r2.js +0 -89
- package/docs/bdd-guidance.md +0 -390
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { useRef, useState, useEffect, memo } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Finds the nearest scrollable ancestor for IntersectionObserver root.
|
|
5
|
+
*/
|
|
6
|
+
function getScrollParent(el: HTMLElement): HTMLElement | null {
|
|
7
|
+
let parent = el.parentElement;
|
|
8
|
+
while (parent) {
|
|
9
|
+
const { overflowY } = getComputedStyle(parent);
|
|
10
|
+
if (overflowY === 'auto' || overflowY === 'scroll') return parent;
|
|
11
|
+
parent = parent.parentElement;
|
|
12
|
+
}
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface LazyCardProps {
|
|
17
|
+
children: React.ReactNode;
|
|
18
|
+
/** Estimated card height used before first measurement */
|
|
19
|
+
estimatedHeight?: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Renders children only when visible in the scroll container.
|
|
24
|
+
* Offscreen cards are replaced with a height-matched placeholder,
|
|
25
|
+
* dramatically reducing DOM node count for large lists.
|
|
26
|
+
*/
|
|
27
|
+
export const LazyCard = memo(function LazyCard({
|
|
28
|
+
children,
|
|
29
|
+
estimatedHeight = 82,
|
|
30
|
+
}: LazyCardProps) {
|
|
31
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
32
|
+
const [visible, setVisible] = useState(false);
|
|
33
|
+
const measuredHeight = useRef(estimatedHeight);
|
|
34
|
+
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
const el = ref.current;
|
|
37
|
+
if (!el) return;
|
|
38
|
+
|
|
39
|
+
const root = getScrollParent(el);
|
|
40
|
+
const io = new IntersectionObserver(
|
|
41
|
+
([entry]) => {
|
|
42
|
+
if (entry.isIntersecting) {
|
|
43
|
+
setVisible(true);
|
|
44
|
+
} else {
|
|
45
|
+
// Capture height before replacing children with placeholder
|
|
46
|
+
const h = el.offsetHeight;
|
|
47
|
+
if (h > 0) measuredHeight.current = h;
|
|
48
|
+
setVisible(false);
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
{ root, rootMargin: '300px 0px' }
|
|
52
|
+
);
|
|
53
|
+
io.observe(el);
|
|
54
|
+
return () => io.disconnect();
|
|
55
|
+
}, []);
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<div ref={ref} style={visible ? undefined : { height: measuredHeight.current }}>
|
|
59
|
+
{visible ? children : null}
|
|
60
|
+
</div>
|
|
61
|
+
);
|
|
62
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
|
|
2
|
+
import ReactMarkdown, { type Components } from 'react-markdown';
|
|
3
|
+
import remarkGfm from 'remark-gfm';
|
|
4
|
+
|
|
5
|
+
export default function LazyMarkdown({ children, components }: { children: string; components?: Components }) {
|
|
6
|
+
return (
|
|
7
|
+
<ReactMarkdown remarkPlugins={[remarkGfm]} components={components}>
|
|
8
|
+
{children}
|
|
9
|
+
</ReactMarkdown>
|
|
10
|
+
);
|
|
11
|
+
}
|
|
@@ -1,130 +1,95 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import Image from 'next/image';
|
|
4
|
-
import Link from 'next/link';
|
|
5
|
-
import { usePathname } from 'next/navigation';
|
|
6
|
-
import { useClaudeSession } from '../contexts/ClaudeSessionContext';
|
|
7
|
-
import { useConnectionStatus } from '../contexts/ConnectionStatusContext';
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
import { Link, useLocation } from 'react-router-dom';
|
|
8
3
|
import { ProjectSwitcher } from './ProjectSwitcher';
|
|
4
|
+
import { prefetch } from '@/lib/data-bridge';
|
|
9
5
|
|
|
10
6
|
interface MainNavProps {
|
|
11
7
|
projectName: string;
|
|
12
8
|
}
|
|
13
9
|
|
|
14
10
|
export function MainNav({ projectName }: MainNavProps) {
|
|
15
|
-
const pathname =
|
|
16
|
-
const { openSessionPanel } = useClaudeSession();
|
|
17
|
-
const { status: connectionStatus } = useConnectionStatus();
|
|
18
|
-
|
|
11
|
+
const { pathname } = useLocation();
|
|
19
12
|
const isBacklogActive = pathname === '/';
|
|
20
13
|
const isTestsActive = pathname === '/tests';
|
|
21
14
|
const isPrototypesActive = pathname === '/prototypes';
|
|
22
15
|
const isSettingsActive = pathname === '/settings';
|
|
23
16
|
|
|
17
|
+
// Prefetch page data on hover — by the time the click fires and the component
|
|
18
|
+
// mounts, data is already cached and ready.
|
|
19
|
+
const prefetchBacklog = useCallback(() => { prefetch.backlog(); }, []);
|
|
20
|
+
const prefetchTests = useCallback(() => { prefetch.tests(); }, []);
|
|
21
|
+
const prefetchPrototypes = useCallback(() => { prefetch.prototypes(); }, []);
|
|
22
|
+
const prefetchSettings = useCallback(() => { prefetch.settings(); }, []);
|
|
23
|
+
|
|
24
24
|
return (
|
|
25
25
|
<header className="sticky top-0 z-10 border-b border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-900 flex-shrink-0">
|
|
26
|
-
<div className="
|
|
26
|
+
<div className="px-5 py-5">
|
|
27
27
|
<div className="flex items-center justify-between">
|
|
28
|
-
<div className="flex items-center gap-
|
|
29
|
-
<
|
|
30
|
-
src="/
|
|
28
|
+
<div className="flex items-center gap-4">
|
|
29
|
+
<img
|
|
30
|
+
src="/jettypod_logo.png"
|
|
31
31
|
alt="JettyPod"
|
|
32
|
-
width={
|
|
33
|
-
height={
|
|
34
|
-
|
|
32
|
+
width={36}
|
|
33
|
+
height={36}
|
|
34
|
+
className="rounded-full"
|
|
35
35
|
/>
|
|
36
36
|
<ProjectSwitcher projectName={projectName} />
|
|
37
37
|
{isBacklogActive ? (
|
|
38
|
-
<span className="px-
|
|
38
|
+
<span className="px-3 py-1.5 text-base text-zinc-900 dark:text-zinc-100 font-medium">
|
|
39
39
|
Backlog
|
|
40
40
|
</span>
|
|
41
41
|
) : (
|
|
42
42
|
<Link
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
to="/"
|
|
44
|
+
viewTransition
|
|
45
|
+
onMouseEnter={prefetchBacklog}
|
|
46
|
+
className="px-3 py-1.5 text-base text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 transition-colors duration-200 ease-out"
|
|
45
47
|
>
|
|
46
48
|
Backlog
|
|
47
49
|
</Link>
|
|
48
50
|
)}
|
|
49
51
|
{isTestsActive ? (
|
|
50
|
-
<span className="px-
|
|
52
|
+
<span className="px-3 py-1.5 text-base text-zinc-900 dark:text-zinc-100 font-medium">
|
|
51
53
|
Tests
|
|
52
54
|
</span>
|
|
53
55
|
) : (
|
|
54
56
|
<Link
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
to="/tests"
|
|
58
|
+
viewTransition
|
|
59
|
+
onMouseEnter={prefetchTests}
|
|
60
|
+
className="px-3 py-1.5 text-base text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 transition-colors duration-200 ease-out"
|
|
57
61
|
>
|
|
58
62
|
Tests
|
|
59
63
|
</Link>
|
|
60
64
|
)}
|
|
61
65
|
{isPrototypesActive ? (
|
|
62
|
-
<span className="px-
|
|
66
|
+
<span className="px-3 py-1.5 text-base text-zinc-900 dark:text-zinc-100 font-medium">
|
|
63
67
|
Prototypes
|
|
64
68
|
</span>
|
|
65
69
|
) : (
|
|
66
70
|
<Link
|
|
67
|
-
|
|
68
|
-
|
|
71
|
+
to="/prototypes"
|
|
72
|
+
viewTransition
|
|
73
|
+
onMouseEnter={prefetchPrototypes}
|
|
74
|
+
className="px-3 py-1.5 text-base text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 transition-colors duration-200 ease-out"
|
|
69
75
|
>
|
|
70
76
|
Prototypes
|
|
71
77
|
</Link>
|
|
72
78
|
)}
|
|
73
79
|
{isSettingsActive ? (
|
|
74
|
-
<span className="px-
|
|
80
|
+
<span className="px-3 py-1.5 text-base text-zinc-900 dark:text-zinc-100 font-medium">
|
|
75
81
|
Settings
|
|
76
82
|
</span>
|
|
77
83
|
) : (
|
|
78
84
|
<Link
|
|
79
|
-
|
|
80
|
-
|
|
85
|
+
to="/settings"
|
|
86
|
+
viewTransition
|
|
87
|
+
onMouseEnter={prefetchSettings}
|
|
88
|
+
className="px-3 py-1.5 text-base text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 transition-colors duration-200 ease-out"
|
|
81
89
|
>
|
|
82
90
|
Settings
|
|
83
91
|
</Link>
|
|
84
92
|
)}
|
|
85
|
-
{/* Connection Status Indicator */}
|
|
86
|
-
<div className="flex items-center gap-2" data-testid="connection-status">
|
|
87
|
-
<span
|
|
88
|
-
className={`w-2 h-2 rounded-full ${
|
|
89
|
-
connectionStatus === 'connected'
|
|
90
|
-
? 'bg-green-500'
|
|
91
|
-
: connectionStatus === 'reconnecting'
|
|
92
|
-
? 'bg-yellow-500 animate-pulse'
|
|
93
|
-
: 'bg-red-500'
|
|
94
|
-
}`}
|
|
95
|
-
/>
|
|
96
|
-
<span className="text-xs text-zinc-500 dark:text-zinc-400">
|
|
97
|
-
{connectionStatus === 'connected'
|
|
98
|
-
? 'Live updates active'
|
|
99
|
-
: connectionStatus === 'reconnecting'
|
|
100
|
-
? 'Reconnecting...'
|
|
101
|
-
: 'Disconnected'}
|
|
102
|
-
</span>
|
|
103
|
-
</div>
|
|
104
|
-
</div>
|
|
105
|
-
<div className="flex items-center">
|
|
106
|
-
<button
|
|
107
|
-
onClick={openSessionPanel}
|
|
108
|
-
className="px-4 py-2 text-xs font-medium rounded-xl transition-all duration-200 hover:-translate-y-1 hover:scale-[1.01] active:translate-y-0 active:scale-100"
|
|
109
|
-
style={{
|
|
110
|
-
cursor: 'pointer',
|
|
111
|
-
background: 'linear-gradient(145deg, #ffffff 0%, #faf9f7 10%, #f0f4f4 35%, #c8d9da 55%, #819D9F 90%)',
|
|
112
|
-
color: '#3d4d4e',
|
|
113
|
-
boxShadow: `
|
|
114
|
-
0 1px 1px rgba(0, 0, 0, 0.02),
|
|
115
|
-
0 2px 4px rgba(0, 0, 0, 0.03),
|
|
116
|
-
0 6px 12px rgba(0, 0, 0, 0.05),
|
|
117
|
-
0 12px 24px rgba(0, 0, 0, 0.06),
|
|
118
|
-
0 20px 40px rgba(129, 157, 159, 0.2),
|
|
119
|
-
0 32px 64px rgba(129, 157, 159, 0.18),
|
|
120
|
-
inset 0 2px 4px rgba(255, 255, 255, 1),
|
|
121
|
-
inset 0 -2px 4px rgba(129, 157, 159, 0.05)
|
|
122
|
-
`,
|
|
123
|
-
}}
|
|
124
|
-
data-testid="nav-claude-sessions-button"
|
|
125
|
-
>
|
|
126
|
-
Claude Sessions
|
|
127
|
-
</button>
|
|
128
93
|
</div>
|
|
129
94
|
</div>
|
|
130
95
|
</div>
|