fix(chat): follow active response at bottom
Staging Backend Quality Gate / validate (push) Successful in 11m13s
Staging Backend Quality Gate / publish (push) Has been cancelled

This commit is contained in:
Jesse_Chen
2026-08-09 01:19:39 +08:00
parent 17430a1f21
commit 34395e902c
6 changed files with 33 additions and 14 deletions
+2 -2
View File
@@ -557,7 +557,7 @@ button:disabled { cursor: default; opacity: .45; }
@media (hover: hover) {
.product-entrypoint-card:has(.product-entrypoint-hitarea:not(:disabled):hover) { border-color: color-mix(in srgb, var(--color-action) 44%, var(--color-border)); transform: translateY(-1px); }
}
.product-entrypoint-card:has(.product-entrypoint-hitarea:disabled) { opacity: .65; }
.product-entrypoint-card:has(.product-entrypoint-hitarea:disabled) { opacity: 1; }
.product-entrypoint-hitarea:disabled { cursor: not-allowed; }
.daily-starlanguage-heading { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.daily-starlanguage-heading > span { color: var(--color-action); font-size: var(--type-overline); font-weight: 600; letter-spacing: 1.5px; }
@@ -1167,7 +1167,7 @@ input:not([class^="ant-"]):not([class*=" ant-"]):not(.ant-picker input):disabled
}
.product-entrypoint-card:has(.product-entrypoint-hitarea:disabled) {
opacity: .65;
opacity: 1;
}
.product-entrypoint-hitarea:disabled {
+5 -5
View File
@@ -1032,7 +1032,7 @@ export default function Home() {
const [birthTimeAssessmentPhase, setBirthTimeAssessmentPhase] = useState<BirthTimeAssessmentPhase | null>(null);
const [startGreeting, setStartGreeting] = useState("");
const [presetMessageLength, setPresetMessageLength] = useState(0);
const conversationEnd = useRef<HTMLDivElement>(null);
const conversation = useRef<HTMLDivElement>(null);
const accountTrigger = useRef<HTMLButtonElement>(null);
const accountDialog = useRef<HTMLElement>(null);
const dialogReturnTarget = useRef<HTMLButtonElement | null>(null);
@@ -1697,8 +1697,10 @@ export default function Home() {
useEffect(() => {
if (starterHomeVisible) return;
const container = conversation.current;
if (!container) return;
const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
conversationEnd.current?.scrollIntoView({ behavior: isLoading || reduceMotion ? "auto" : "smooth", block: "end" });
container.scrollTo({ top: container.scrollHeight, behavior: isLoading || reduceMotion ? "auto" : "smooth" });
}, [activeSessionId, activeSession?.messages.length, activeStreamingText, isLoading, onboardingPending, onboardingStep, presetMessageFinished, profileComplete, starterHomeVisible]);
useEffect(() => {
@@ -3127,7 +3129,7 @@ export default function Home() {
</header>
{!rectificationSurfaceOpen && (
<div className={`conversation ${activeSession?.messages.length ? "" : "is-empty"}`}>
<div ref={conversation} className={`conversation ${activeSession?.messages.length ? "" : "is-empty"}`}>
{!activeSession?.messages.length ? (
<div className="welcome">
{!profileComplete ? (
@@ -3299,7 +3301,6 @@ export default function Home() {
{onboardingError && <p className="starter-note"></p>}
</div>
))}
<div ref={conversationEnd} />
</div>
) : (
<div className="message-list" aria-busy={isLoading}>
@@ -3308,7 +3309,6 @@ export default function Home() {
<ChatMessageRow key={message.renderKey} message={message} />
))}
{activeError && <p className="error-message" role="alert">{activeError}</p>}
<div ref={conversationEnd} />
</div>
)}
</div>
@@ -83,7 +83,7 @@ export function AgenticRectificationChat(props: AgenticRectificationChatProps) {
const [acceptingTime, setAcceptingTime] = useState<string | null>(null);
const [suggestions, setSuggestions] = useState<string[]>([]);
const composer = useRef<HTMLTextAreaElement>(null);
const conversationEnd = useRef<HTMLDivElement>(null);
const conversation = useRef<HTMLElement>(null);
const keyCounter = useRef(0);
const openingStarted = useRef(false);
@@ -93,12 +93,14 @@ export function AgenticRectificationChat(props: AgenticRectificationChatProps) {
}, [onPendingChange]);
useEffect(() => {
const container = conversation.current;
if (!container) return;
const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
conversationEnd.current?.scrollIntoView({
container.scrollTo({
top: container.scrollHeight,
behavior: busy || reduceMotion ? "auto" : "smooth",
block: "end",
});
}, [busy, error, messages.length, savedTime]);
}, [busy, error, messages, savedTime]);
const send = useCallback(async (request: AgenticRectificationRequest, showUserMessage = true) => {
const trimmed = request.action === "message" ? request.message.trim() : "";
@@ -301,7 +303,7 @@ export function AgenticRectificationChat(props: AgenticRectificationChatProps) {
return (
<>
<section className="conversation" aria-label="生时校正对话" aria-busy={busy}>
<section ref={conversation} className="conversation" aria-label="生时校正对话" aria-busy={busy}>
<div className="message-list" aria-live="polite">
{messages.map((message) => <ChatMessageRow key={message.renderKey} message={message} />)}
{candidateResult?.selectionAllowed && candidateResult.candidates.length > 0 && (
@@ -344,7 +346,6 @@ export function AgenticRectificationChat(props: AgenticRectificationChatProps) {
</p>
)}
{error && <p className="error-message" role="alert">{error}</p>}
<div ref={conversationEnd} />
</div>
</section>