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:
Adeniji Adekunle James
2025-12-02 06:16:02 +00:00
committed by GitHub
parent fadfbc06be
commit dd14e67d48
3 changed files with 58 additions and 2 deletions

View File

@@ -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"]',
);
}

View File

@@ -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}

View 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;
}