Fix canvas stuck on camera denial, move input under canvas
Camera denial now properly pops the dead scene off the stack so the fluid sim resumes. Desktop right pane reordered: canvas → input → scrollable output. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
047b5b8381
commit
a73644b516
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"totalArticles": 83,
|
||||
"totalClaims": 415,
|
||||
"lastUpdated": "2026-02-15T17:32:46.065Z",
|
||||
"lastUpdated": "2026-02-15T17:48:20.296Z",
|
||||
"latestArticleDate": "2026-02-14",
|
||||
"topics": [
|
||||
"business",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<link>https://kbanc.com</link>
|
||||
<description>Evidence-based claims about AI implementation, optimized for LLM extraction and research citation.</description>
|
||||
<language>en-us</language>
|
||||
<lastBuildDate>Sun, 15 Feb 2026 17:32:45 GMT</lastBuildDate>
|
||||
<lastBuildDate>Sun, 15 Feb 2026 17:48:19 GMT</lastBuildDate>
|
||||
<atom:link href="https://kbanc.com/feed.xml" rel="self" type="application/rss+xml"/>
|
||||
|
||||
<item>
|
||||
|
|
|
|||
|
|
@ -237,6 +237,7 @@ function TerminalHomepageInner({
|
|||
pushScene({
|
||||
type: "camera",
|
||||
onCameraDenied: () => {
|
||||
popScene();
|
||||
setCameraState("denied");
|
||||
},
|
||||
});
|
||||
|
|
@ -306,6 +307,7 @@ function TerminalHomepageInner({
|
|||
pushScene({
|
||||
type: "camera",
|
||||
onCameraDenied: () => {
|
||||
popScene();
|
||||
setCameraState("denied");
|
||||
},
|
||||
});
|
||||
|
|
@ -352,7 +354,7 @@ function TerminalHomepageInner({
|
|||
popScene();
|
||||
pushScene({ type: "camera" });
|
||||
},
|
||||
onCameraDenied: () => setCameraState("denied"),
|
||||
onCameraDenied: () => { popScene(); setCameraState("denied"); },
|
||||
});
|
||||
} else {
|
||||
// Normal fluid sim oracle overlay
|
||||
|
|
@ -685,69 +687,66 @@ function TerminalHomepageInner({
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right pane: canvas on top, output + input on bottom */}
|
||||
{/* Right pane: canvas on top, input below canvas, output scrolls down */}
|
||||
<div className="flex-1 flex flex-col min-w-0">
|
||||
{/* Top: fluid simulation / camera */}
|
||||
<div className="h-[45%] border-b border-border cursor-pointer overflow-hidden" onClick={handleCanvasClick}>
|
||||
<SidebarCanvas mode="pane" />
|
||||
</div>
|
||||
|
||||
{/* Bottom: scrollable output + sticky input */}
|
||||
<div className="flex-1 flex flex-col min-h-0">
|
||||
{/* Output area */}
|
||||
<div className="flex-1 overflow-y-auto p-5">
|
||||
{history.length === 0 ? (
|
||||
<p className="text-terminal-dim text-sm">
|
||||
type a command from the menu, or ask a question.
|
||||
</p>
|
||||
) : (
|
||||
<div className="space-y-4">
|
||||
{history.map((entry) => (
|
||||
<div key={entry.id}>
|
||||
<TerminalPrompt command={entry.command} />
|
||||
{entry.isOracle ? (
|
||||
<OracleOutput entry={entry} />
|
||||
) : streamingId === entry.id ? (
|
||||
<StreamingOutput entry={entry} onComplete={handleStreamComplete} />
|
||||
) : completedIds.has(entry.id) ? (
|
||||
<CompletedOutput entry={entry} />
|
||||
) : null}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<div ref={bottomRef} />
|
||||
</div>
|
||||
|
||||
{/* Input bar */}
|
||||
<div className="flex-shrink-0 border-t border-border px-5 py-3">
|
||||
<form onSubmit={handleSubmit} className="flex items-center gap-2">
|
||||
<span className="text-terminal-green select-none font-bold" aria-hidden="true">$</span>
|
||||
<div className="relative flex-1">
|
||||
<input
|
||||
ref={inputRef}
|
||||
type="text"
|
||||
value={inputValue}
|
||||
onChange={(e) => { setInputValue(e.target.value); setActiveItemIndex(-1); }}
|
||||
onKeyDown={handleKeyDown}
|
||||
disabled={streamingId !== null}
|
||||
className="bg-transparent border-none outline-none text-foreground placeholder:text-terminal-dim w-full font-mono disabled:opacity-50"
|
||||
placeholder={history.length === 0 ? "type a command or ask a question..." : ""}
|
||||
autoComplete="off"
|
||||
spellCheck={false}
|
||||
autoFocus
|
||||
/>
|
||||
{suggestion && inputValue && suggestion !== inputValue && (
|
||||
<span className="absolute left-0 top-0 pointer-events-none text-terminal-dim/40 font-mono" aria-hidden="true">
|
||||
{suggestion}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{streamingId === null && (
|
||||
<span className="terminal-cursor" aria-hidden="true">█</span>
|
||||
{/* Input bar (directly under canvas) */}
|
||||
<div className="flex-shrink-0 border-b border-border px-5 py-3">
|
||||
<form onSubmit={handleSubmit} className="flex items-center gap-2">
|
||||
<span className="text-terminal-green select-none font-bold" aria-hidden="true">$</span>
|
||||
<div className="relative flex-1">
|
||||
<input
|
||||
ref={inputRef}
|
||||
type="text"
|
||||
value={inputValue}
|
||||
onChange={(e) => { setInputValue(e.target.value); setActiveItemIndex(-1); }}
|
||||
onKeyDown={handleKeyDown}
|
||||
disabled={streamingId !== null}
|
||||
className="bg-transparent border-none outline-none text-foreground placeholder:text-terminal-dim w-full font-mono disabled:opacity-50"
|
||||
placeholder={history.length === 0 ? "type a command or ask a question..." : ""}
|
||||
autoComplete="off"
|
||||
spellCheck={false}
|
||||
autoFocus
|
||||
/>
|
||||
{suggestion && inputValue && suggestion !== inputValue && (
|
||||
<span className="absolute left-0 top-0 pointer-events-none text-terminal-dim/40 font-mono" aria-hidden="true">
|
||||
{suggestion}
|
||||
</span>
|
||||
)}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{streamingId === null && (
|
||||
<span className="terminal-cursor" aria-hidden="true">█</span>
|
||||
)}
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{/* Output area (scrolls down below input) */}
|
||||
<div className="flex-1 overflow-y-auto p-5">
|
||||
{history.length === 0 ? (
|
||||
<p className="text-terminal-dim text-sm">
|
||||
type a command from the menu, or ask a question.
|
||||
</p>
|
||||
) : (
|
||||
<div className="space-y-4">
|
||||
{history.map((entry) => (
|
||||
<div key={entry.id}>
|
||||
<TerminalPrompt command={entry.command} />
|
||||
{entry.isOracle ? (
|
||||
<OracleOutput entry={entry} />
|
||||
) : streamingId === entry.id ? (
|
||||
<StreamingOutput entry={entry} onComplete={handleStreamComplete} />
|
||||
) : completedIds.has(entry.id) ? (
|
||||
<CompletedOutput entry={entry} />
|
||||
) : null}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<div ref={bottomRef} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue