UI iteration 4: dock morph animation, sticky-in-flow dock, scrollbar, indicators
- Animation: the blob's shell morphs height (WAAPI, 180ms) on every variant change — chat ↔ question ↔ collapsed bar — plus a quick fade/rise (160ms) on the swapped content. Gotcha pinned in code: never measure the shell while a morph is in flight (getBoundingClientRect reads the ANIMATED value and corrupts the next morph's start height); cancel running morphs before measuring, refresh settled height only when no morph is running. - Gradient-over-scrollbar fixed structurally: the dock is no longer an absolute overlay on the conversation root — it's sticky bottom-0 INSIDE the scroller (in flow). The transcript scrolls fully clear of the dock, the fade never touches the scrollbar lane, and the pb-hack clearances are gone. - New question while at the bottom scrolls to reveal the dock; scrolled up → collapsed bar, no yank. - Thin dark native scrollbar app-wide (8px webkit + scrollbar-width:thin, dark thumb, transparent track). Note: use-stick-to-bottom sets scrollbar-gutter: stable both-edges on its scroller — the lane is outside the content flow by design. - 'Writing a question…' transcript shimmer while a tool call streams its input (same slot as 'Thinking…'). Protocol pinned by a test asserting tool-input-start precedes tool-input-available; scripted mock now streams tool input as deltas like real providers do. (OpenRouter/ Anthropic often delivers the whole input in ONE delta — then the dock appears instantly and no indicator is needed or shown.) Verified live: grow 54→349px and shrink 349→54px fire with correct from/to; collapse/expand intact; gradient stops before the gutter; Thinking… observed in-page; 58/58 tests.
This commit is contained in:
@@ -16,7 +16,6 @@ import assert from "node:assert/strict";
|
||||
import { describe, it } from "node:test";
|
||||
import { renderToStaticMarkup } from "react-dom/server";
|
||||
import { MessageResponse } from "../components/ai-elements/message.tsx";
|
||||
import { StickToBottom } from "use-stick-to-bottom";
|
||||
import { QuestionDock } from "../components/question-dock.tsx";
|
||||
import { AnsweredCard } from "../components/answered-card.tsx";
|
||||
import { buildAnswer, coerceCorrectAnswer, normalizeOptions, resolveCorrect, type QuestionData } from "../src/core/question-core.ts";
|
||||
@@ -44,10 +43,11 @@ function quizQD(): QuestionData {
|
||||
|
||||
|
||||
function renderDock(props: { toolName: "quiz" | "ask_user_question"; toolCallId: string; input: never; onSubmit?: () => void }) {
|
||||
// The dock reads the stick-to-bottom scroll context; wrap it. In static
|
||||
// render the context starts at isAtBottom=true → the expanded form renders.
|
||||
// expanded=true renders the full form (the collapsed bar is covered by the
|
||||
// QuestionDockBar test below). No scroll context needed — the DockOverlay
|
||||
// in the chat view owns that.
|
||||
return renderToStaticMarkup(
|
||||
<StickToBottom><QuestionDock {...props} onSubmit={props.onSubmit ?? (() => {})} /></StickToBottom>,
|
||||
<QuestionDock {...props} expanded={true} onExpand={() => {}} onSubmit={props.onSubmit ?? (() => {})} />,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user