Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 49 additions & 75 deletions src/frontend/src/components/content/PlanChatBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import { Button, Caption1 } from "@fluentui/react-components";
import { Send } from "@/coral/imports/bundleicons";

interface SimplifiedPlanChatProps extends PlanChatProps {
planData: any;
input: string;
setInput: (input: string) => void;
submittingChatDisableInput: boolean;
OnChatSubmit: (input: string) => void;
waitingForPlan: boolean;
}

Expand All @@ -18,87 +23,56 @@ const PlanChatBody: React.FC<SimplifiedPlanChatProps> = ({
return (
<div
style={{
position: 'sticky',
bottom: 0,
backgroundColor: 'var(--colorNeutralBackground1)',
padding: '20px 0'
// borderTop: '1px solid var(--colorNeutralStroke2)',
padding: '16px 24px',
maxWidth: '800px',
margin: '0 auto',
width: '100%',
boxSizing: 'border-box',
zIndex: 10,
}}
>
<div
<ChatInput
value={input}
onChange={setInput}
onEnter={() => OnChatSubmit(input)}
disabledChat={submittingChatDisableInput}
placeholder={
waitingForPlan
? "Creating plan..."
: "Type your message here..."
}
style={{
maxWidth: '800px',
margin: '0 auto',
padding: '0 24px'
fontSize: '16px',
borderRadius: '8px',
// border: '1px solid var(--colorNeutralStroke1)',
backgroundColor: 'var(--colorNeutralBackground1)',
width: '100%',
boxSizing: 'border-box',
}}
>
{/* Chat Input Container */}
<div style={{
position: 'relative',
width: '100%'
}}>
<ChatInput
value={input}
onChange={setInput}
onEnter={() => OnChatSubmit(input)}
disabledChat={submittingChatDisableInput}
placeholder={
waitingForPlan
? "Creating plan..."
: "Tell us what needs planning, building, or connecting—we'll handle the rest."
}
style={{
minHeight: '56px',
fontSize: '16px',
borderRadius: '8px',
border: '2px solid var(--colorNeutralStroke2)',
backgroundColor: 'var(--colorNeutralBackground1)',
padding: '16px 60px 16px 20px',
width: '100%',
boxSizing: 'border-box',
alignItems: 'flex-start',
textAlign: 'left',
verticalAlign: 'top'
}}
>
<Button
appearance="subtle"
className="home-input-send-button"
onClick={() => OnChatSubmit(input)}
disabled={submittingChatDisableInput}
icon={<Send />}
style={{
position: 'absolute',
right: '12px',
top: '16px',
height: '32px',
width: '32px',
borderRadius: '4px',
backgroundColor: 'transparent',
border: 'none',
color: submittingChatDisableInput
? 'var(--colorNeutralForegroundDisabled)'
: 'var(--colorBrandForeground1)'
}}
/>
</ChatInput>

{/* AI disclaimer */}
<div style={{
color: 'var(--colorNeutralForeground3)',
marginTop: '8px',
paddingBottom: '8px',
textAlign: 'center'
}}>
{/* <Caption1>AI-generated content may be incorrect</Caption1> */}
</div>
</div>
</div>
<div
style={{
marginTop: '8px',
paddingBottom: '8px',
}}
>

</div>
<Button
appearance="subtle"
className="home-input-send-button"
onClick={() => OnChatSubmit(input)}
disabled={submittingChatDisableInput || !input.trim()}
icon={<Send />}
style={{
height: '32px',
width: '32px',
borderRadius: '4px',
backgroundColor: 'transparent',
border: 'none',
color: (submittingChatDisableInput || !input.trim())
? 'var(--colorNeutralForegroundDisabled)'
: 'var(--colorBrandForeground1)',
flexShrink: 0,
}}
/>
</ChatInput>
</div>
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/src/coral/components/PromptCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const PromptCard: React.FC<PromptCardProps> = ({
backgroundColor: disabled
? "var(--colorNeutralBackgroundDisabled)"
: "var(--colorNeutralBackground3)",
border: "1px solid var(--colorNeutralStroke2)",
border: "1px solid var(--colorNeutralStroke1)",
borderRadius: "8px",
cursor: disabled ? "not-allowed" : "pointer",
boxShadow: "none",
Expand Down
34 changes: 22 additions & 12 deletions src/frontend/src/coral/modules/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import React, {
useEffect,
forwardRef,
useImperativeHandle,
useLayoutEffect,
} from "react";
import {
Tag,
Expand Down Expand Up @@ -44,10 +45,18 @@ const ChatInput = forwardRef<HTMLTextAreaElement, ChatInputProps>(
// ✅ Allow parent to access textarea DOM node
useImperativeHandle(ref, () => textareaRef.current as HTMLTextAreaElement);

useEffect(() => {
// ✅ Use useLayoutEffect to prevent visual jumping
useLayoutEffect(() => {
if (textareaRef.current) {
// Store the current scroll position to prevent jumping
const scrollTop = textareaRef.current.scrollTop;

textareaRef.current.style.height = "auto";
textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;
const newHeight = Math.max(textareaRef.current.scrollHeight, 24);
textareaRef.current.style.height = `${newHeight}px`;

// Restore scroll position
textareaRef.current.scrollTop = scrollTop;
}
}, [value]);

Expand All @@ -56,17 +65,17 @@ const ChatInput = forwardRef<HTMLTextAreaElement, ChatInputProps>(
<div
ref={inputContainerRef}
style={{
display: "inline-flex",
display: "flex",
flexDirection: "column",
gap: "8px",
alignItems: "stretch",
width: "100%",
padding: "8px",
borderRadius: "var(--borderRadiusLarge)",
backgroundColor: "var(--colorNeutralBackground1)",
borderColor: isFocused
border: `1px solid ${isFocused
? "var(--colorNeutralStroke1Pressed)"
: "var(--colorNeutralStroke1)",
: "var(--colorNeutralStroke1)"}`,
transition: "border-color 0.2s ease-in-out",
position: "relative",
boxSizing: "border-box",
Expand All @@ -93,8 +102,8 @@ const ChatInput = forwardRef<HTMLTextAreaElement, ChatInputProps>(
rows={1}
style={{
resize: "none",
overflowY: "scroll",
height: "auto",
overflowY: "auto",
height: "24px", // Set initial height
minHeight: "24px",
maxHeight: "150px",
padding: "8px",
Expand All @@ -107,6 +116,8 @@ const ChatInput = forwardRef<HTMLTextAreaElement, ChatInputProps>(
color: "var(--colorNeutralForeground1)",
lineHeight: 1.5,
boxSizing: "border-box",
verticalAlign: "top", // Ensure text starts at top
textAlign: "left", // Ensure text alignment is consistent
}}
/>

Expand All @@ -115,7 +126,8 @@ const ChatInput = forwardRef<HTMLTextAreaElement, ChatInputProps>(
display: "flex",
alignItems: "center",
justifyContent: "space-between",
maxHeight: "32px",
minHeight: "32px", // Use minHeight instead of maxHeight
flexShrink: 0, // Prevent this div from shrinking
}}
>
<span
Expand All @@ -127,6 +139,7 @@ const ChatInput = forwardRef<HTMLTextAreaElement, ChatInputProps>(
>
{value.length}/5000
</span>

<HeaderTools>{children}</HeaderTools>
</div>

Expand All @@ -140,13 +153,10 @@ const ChatInput = forwardRef<HTMLTextAreaElement, ChatInputProps>(
backgroundColor: "var(--colorCompoundBrandStroke)",
transform: isFocused ? "scaleX(1)" : "scaleX(0)",
transition: "transform 0.2s ease-in-out",
textAlign: "center",
}}
/>
</div>

<br />

<div
style={{
color: "var(--colorNeutralForeground3)",
Expand All @@ -162,4 +172,4 @@ const ChatInput = forwardRef<HTMLTextAreaElement, ChatInputProps>(
}
);

export default ChatInput;
export default ChatInput;
Loading