Animated placeholder with Prompt suggestion for home chat input (#1706)
<!-- This is an auto-generated description by cubic. --> ## Summary by cubic Adds an animated placeholder with rotating prompt suggestions to the home chat input to guide users. Also introduces a small hook for the typing effect and updates the e2e selector to handle dynamic text. - **New Features** - HomeChatInput shows "Ask Dyad to build" with cycling suggestions (ecommerce store, information page, landing page). - New useTypingPlaceholder hook for type/delete animation with configurable speeds and pause. - E2E test locator updated to match aria-placeholder by prefix to support dynamic content. <sup>Written for commit 6b8133ec9441f60909493cad3b43315348aed2d5. Summary will update automatically on new commits.</sup> <!-- End of auto-generated description by cubic. -->
This commit is contained in:
committed by
GitHub
parent
fadfbc06be
commit
dd14e67d48
@@ -713,7 +713,7 @@ export class PageObject {
|
||||
|
||||
getChatInput() {
|
||||
return this.page.locator(
|
||||
'[data-lexical-editor="true"][aria-placeholder="Ask Dyad to build..."]',
|
||||
'[data-lexical-editor="true"][aria-placeholder^="Ask Dyad to build"]',
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import { HomeSubmitOptions } from "@/pages/home";
|
||||
import { ChatInputControls } from "../ChatInputControls";
|
||||
import { LexicalChatInput } from "./LexicalChatInput";
|
||||
import { useChatModeToggle } from "@/hooks/useChatModeToggle";
|
||||
import { useTypingPlaceholder } from "@/hooks/useTypingPlaceholder";
|
||||
export function HomeChatInput({
|
||||
onSubmit,
|
||||
}: {
|
||||
@@ -26,6 +27,13 @@ export function HomeChatInput({
|
||||
}); // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
useChatModeToggle();
|
||||
|
||||
const typingText = useTypingPlaceholder([
|
||||
"an ecommerce store...",
|
||||
"an information page...",
|
||||
"a landing page...",
|
||||
]);
|
||||
const placeholder = `Ask Dyad to build ${typingText ?? ""}`;
|
||||
|
||||
// Use the attachments hook
|
||||
const {
|
||||
attachments,
|
||||
@@ -83,7 +91,7 @@ export function HomeChatInput({
|
||||
onChange={setInputValue}
|
||||
onSubmit={handleCustomSubmit}
|
||||
onPaste={handlePaste}
|
||||
placeholder="Ask Dyad to build..."
|
||||
placeholder={placeholder}
|
||||
disabled={isStreaming}
|
||||
excludeCurrentApp={false}
|
||||
disableSendButton={false}
|
||||
|
||||
48
src/hooks/useTypingPlaceholder.ts
Normal file
48
src/hooks/useTypingPlaceholder.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export function useTypingPlaceholder(
|
||||
phrases: string[],
|
||||
typingSpeed = 100,
|
||||
deletingSpeed = 50,
|
||||
pauseTime = 1500,
|
||||
) {
|
||||
const [text, setText] = useState("");
|
||||
const [index, setIndex] = useState(0);
|
||||
const [deleting, setDeleting] = useState(false);
|
||||
const [charIndex, setCharIndex] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
const current = phrases[index];
|
||||
const speed = deleting ? deletingSpeed : typingSpeed;
|
||||
let pauseTimer: NodeJS.Timeout;
|
||||
const timer = setTimeout(() => {
|
||||
if (!deleting && charIndex < current.length) {
|
||||
setText((prev) => prev + current.charAt(charIndex));
|
||||
setCharIndex((prev) => prev + 1);
|
||||
} else if (deleting && charIndex > 0) {
|
||||
setText((prev) => prev.slice(0, -1));
|
||||
setCharIndex((prev) => prev - 1);
|
||||
} else if (!deleting && charIndex === current.length) {
|
||||
pauseTimer = setTimeout(() => setDeleting(true), pauseTime);
|
||||
} else if (deleting && charIndex === 0) {
|
||||
setDeleting(false);
|
||||
setIndex((prev) => (prev + 1) % phrases.length);
|
||||
}
|
||||
}, speed);
|
||||
|
||||
return () => {
|
||||
clearTimeout(timer);
|
||||
clearTimeout(pauseTimer);
|
||||
};
|
||||
}, [
|
||||
phrases,
|
||||
index,
|
||||
deleting,
|
||||
charIndex,
|
||||
typingSpeed,
|
||||
deletingSpeed,
|
||||
pauseTime,
|
||||
]);
|
||||
|
||||
return text;
|
||||
}
|
||||
Reference in New Issue
Block a user