Skip to content

Commit a5ed4cf

Browse files
authored
Merge pull request #492 from microsoft/macae-BS-UI-errorHandling
Fix: UI error handling
2 parents bcf5c22 + b87fe95 commit a5ed4cf

File tree

3 files changed

+72
-88
lines changed

3 files changed

+72
-88
lines changed

src/frontend/src/components/content/PlanChatBody.tsx

Lines changed: 49 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ import { Button, Caption1 } from "@fluentui/react-components";
44
import { Send } from "@/coral/imports/bundleicons";
55

66
interface SimplifiedPlanChatProps extends PlanChatProps {
7+
planData: any;
8+
input: string;
9+
setInput: (input: string) => void;
10+
submittingChatDisableInput: boolean;
11+
OnChatSubmit: (input: string) => void;
712
waitingForPlan: boolean;
813
}
914

@@ -18,87 +23,56 @@ const PlanChatBody: React.FC<SimplifiedPlanChatProps> = ({
1823
return (
1924
<div
2025
style={{
26+
position: 'sticky',
27+
bottom: 0,
2128
backgroundColor: 'var(--colorNeutralBackground1)',
22-
padding: '20px 0'
29+
// borderTop: '1px solid var(--colorNeutralStroke2)',
30+
padding: '16px 24px',
31+
maxWidth: '800px',
32+
margin: '0 auto',
33+
width: '100%',
34+
boxSizing: 'border-box',
35+
zIndex: 10,
2336
}}
2437
>
25-
<div
38+
<ChatInput
39+
value={input}
40+
onChange={setInput}
41+
onEnter={() => OnChatSubmit(input)}
42+
disabledChat={submittingChatDisableInput}
43+
placeholder={
44+
waitingForPlan
45+
? "Creating plan..."
46+
: "Type your message here..."
47+
}
2648
style={{
27-
maxWidth: '800px',
28-
margin: '0 auto',
29-
padding: '0 24px'
49+
fontSize: '16px',
50+
borderRadius: '8px',
51+
// border: '1px solid var(--colorNeutralStroke1)',
52+
backgroundColor: 'var(--colorNeutralBackground1)',
53+
width: '100%',
54+
boxSizing: 'border-box',
3055
}}
3156
>
32-
{/* Chat Input Container */}
33-
<div style={{
34-
position: 'relative',
35-
width: '100%'
36-
}}>
37-
<ChatInput
38-
value={input}
39-
onChange={setInput}
40-
onEnter={() => OnChatSubmit(input)}
41-
disabledChat={submittingChatDisableInput}
42-
placeholder={
43-
waitingForPlan
44-
? "Creating plan..."
45-
: "Tell us what needs planning, building, or connecting—we'll handle the rest."
46-
}
47-
style={{
48-
minHeight: '56px',
49-
fontSize: '16px',
50-
borderRadius: '8px',
51-
border: '2px solid var(--colorNeutralStroke2)',
52-
backgroundColor: 'var(--colorNeutralBackground1)',
53-
padding: '16px 60px 16px 20px',
54-
width: '100%',
55-
boxSizing: 'border-box',
56-
alignItems: 'flex-start',
57-
textAlign: 'left',
58-
verticalAlign: 'top'
59-
}}
60-
>
61-
<Button
62-
appearance="subtle"
63-
className="home-input-send-button"
64-
onClick={() => OnChatSubmit(input)}
65-
disabled={submittingChatDisableInput}
66-
icon={<Send />}
67-
style={{
68-
position: 'absolute',
69-
right: '12px',
70-
top: '16px',
71-
height: '32px',
72-
width: '32px',
73-
borderRadius: '4px',
74-
backgroundColor: 'transparent',
75-
border: 'none',
76-
color: submittingChatDisableInput
77-
? 'var(--colorNeutralForegroundDisabled)'
78-
: 'var(--colorBrandForeground1)'
79-
}}
80-
/>
81-
</ChatInput>
82-
83-
{/* AI disclaimer */}
84-
<div style={{
85-
color: 'var(--colorNeutralForeground3)',
86-
marginTop: '8px',
87-
paddingBottom: '8px',
88-
textAlign: 'center'
89-
}}>
90-
{/* <Caption1>AI-generated content may be incorrect</Caption1> */}
91-
</div>
92-
</div>
93-
</div>
94-
<div
95-
style={{
96-
marginTop: '8px',
97-
paddingBottom: '8px',
98-
}}
99-
>
100-
101-
</div>
57+
<Button
58+
appearance="subtle"
59+
className="home-input-send-button"
60+
onClick={() => OnChatSubmit(input)}
61+
disabled={submittingChatDisableInput || !input.trim()}
62+
icon={<Send />}
63+
style={{
64+
height: '32px',
65+
width: '32px',
66+
borderRadius: '4px',
67+
backgroundColor: 'transparent',
68+
border: 'none',
69+
color: (submittingChatDisableInput || !input.trim())
70+
? 'var(--colorNeutralForegroundDisabled)'
71+
: 'var(--colorBrandForeground1)',
72+
flexShrink: 0,
73+
}}
74+
/>
75+
</ChatInput>
10276
</div>
10377
);
10478
}

src/frontend/src/coral/components/PromptCard.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const PromptCard: React.FC<PromptCardProps> = ({
2929
backgroundColor: disabled
3030
? "var(--colorNeutralBackgroundDisabled)"
3131
: "var(--colorNeutralBackground3)",
32-
border: "1px solid var(--colorNeutralStroke2)",
32+
border: "1px solid var(--colorNeutralStroke1)",
3333
borderRadius: "8px",
3434
cursor: disabled ? "not-allowed" : "pointer",
3535
boxShadow: "none",

src/frontend/src/coral/modules/ChatInput.tsx

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import React, {
44
useEffect,
55
forwardRef,
66
useImperativeHandle,
7+
useLayoutEffect,
78
} from "react";
89
import {
910
Tag,
@@ -44,10 +45,18 @@ const ChatInput = forwardRef<HTMLTextAreaElement, ChatInputProps>(
4445
// ✅ Allow parent to access textarea DOM node
4546
useImperativeHandle(ref, () => textareaRef.current as HTMLTextAreaElement);
4647

47-
useEffect(() => {
48+
// ✅ Use useLayoutEffect to prevent visual jumping
49+
useLayoutEffect(() => {
4850
if (textareaRef.current) {
51+
// Store the current scroll position to prevent jumping
52+
const scrollTop = textareaRef.current.scrollTop;
53+
4954
textareaRef.current.style.height = "auto";
50-
textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;
55+
const newHeight = Math.max(textareaRef.current.scrollHeight, 24);
56+
textareaRef.current.style.height = `${newHeight}px`;
57+
58+
// Restore scroll position
59+
textareaRef.current.scrollTop = scrollTop;
5160
}
5261
}, [value]);
5362

@@ -56,17 +65,17 @@ const ChatInput = forwardRef<HTMLTextAreaElement, ChatInputProps>(
5665
<div
5766
ref={inputContainerRef}
5867
style={{
59-
display: "inline-flex",
68+
display: "flex",
6069
flexDirection: "column",
6170
gap: "8px",
6271
alignItems: "stretch",
6372
width: "100%",
6473
padding: "8px",
6574
borderRadius: "var(--borderRadiusLarge)",
6675
backgroundColor: "var(--colorNeutralBackground1)",
67-
borderColor: isFocused
76+
border: `1px solid ${isFocused
6877
? "var(--colorNeutralStroke1Pressed)"
69-
: "var(--colorNeutralStroke1)",
78+
: "var(--colorNeutralStroke1)"}`,
7079
transition: "border-color 0.2s ease-in-out",
7180
position: "relative",
7281
boxSizing: "border-box",
@@ -93,8 +102,8 @@ const ChatInput = forwardRef<HTMLTextAreaElement, ChatInputProps>(
93102
rows={1}
94103
style={{
95104
resize: "none",
96-
overflowY: "scroll",
97-
height: "auto",
105+
overflowY: "auto",
106+
height: "24px", // Set initial height
98107
minHeight: "24px",
99108
maxHeight: "150px",
100109
padding: "8px",
@@ -107,6 +116,8 @@ const ChatInput = forwardRef<HTMLTextAreaElement, ChatInputProps>(
107116
color: "var(--colorNeutralForeground1)",
108117
lineHeight: 1.5,
109118
boxSizing: "border-box",
119+
verticalAlign: "top", // Ensure text starts at top
120+
textAlign: "left", // Ensure text alignment is consistent
110121
}}
111122
/>
112123

@@ -115,7 +126,8 @@ const ChatInput = forwardRef<HTMLTextAreaElement, ChatInputProps>(
115126
display: "flex",
116127
alignItems: "center",
117128
justifyContent: "space-between",
118-
maxHeight: "32px",
129+
minHeight: "32px", // Use minHeight instead of maxHeight
130+
flexShrink: 0, // Prevent this div from shrinking
119131
}}
120132
>
121133
<span
@@ -127,6 +139,7 @@ const ChatInput = forwardRef<HTMLTextAreaElement, ChatInputProps>(
127139
>
128140
{value.length}/5000
129141
</span>
142+
130143
<HeaderTools>{children}</HeaderTools>
131144
</div>
132145

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

148-
<br />
149-
150160
<div
151161
style={{
152162
color: "var(--colorNeutralForeground3)",
@@ -162,4 +172,4 @@ const ChatInput = forwardRef<HTMLTextAreaElement, ChatInputProps>(
162172
}
163173
);
164174

165-
export default ChatInput;
175+
export default ChatInput;

0 commit comments

Comments
 (0)