diff --git a/public/vite.svg b/public/vite.svg
deleted file mode 100644
index e7b8dfb..0000000
--- a/public/vite.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/src/pages/main/index.tsx b/src/pages/main/index.tsx
index 78a0057..7ed8d68 100644
--- a/src/pages/main/index.tsx
+++ b/src/pages/main/index.tsx
@@ -9,60 +9,71 @@ const MainPage = () => {
const [messages, setMessages] = useState([]);
const [inputMessage, setInputMessage] = useState("");
const [isSidebarOpen, setSidebarOpen] = useState(false);
- const messageListRef = useRef(null);
+ const [inputHeight, setInputHeight] = useState(36); // 메시지 입력창 높이 상태 추가
+ const pageRef = useRef(null);
const handleSendMessage = () => {
if (inputMessage.trim()) {
setMessages((prev) => [inputMessage, ...prev]);
- setInputMessage("");
+ setInputMessage(""); // 상태가 업데이트된 후에 입력창 초기화
}
};
- // 메시지가 추가될 때 메시지 리스트를 아래로 스크롤
+ // 메시지가 추가될 때 페이지를 가장 아래로 스크롤
useEffect(() => {
- if (messageListRef.current) {
- messageListRef.current.scrollTo({
- top: messageListRef.current.scrollHeight,
+ if (pageRef.current) {
+ pageRef.current.scrollTo({
+ top: pageRef.current.scrollHeight,
behavior: "smooth",
});
}
- }, [messages]);
+ }, [messages, inputHeight]); // inputHeight 추가하여 메시지 입력창 높이 변경에 따른 스크롤 업데이트
const toggleSidebar = () => {
setSidebarOpen((prev) => !prev);
};
return (
- <>
+
-
-
- {messages.length === 0 ? (
-
-
-
- ) : (
+
+ {messages.length === 0 ? (
+
+
+
+ ) : (
+
- )}
-
+
+ )}
-
- >
+
+
);
};
export default MainPage;
-// SidebarWrapper 스타일 컴포넌트
+// 전체 페이지 래퍼 (스크롤 가능한 요소)
+const PageWrapper = styled.div`
+ position: relative;
+ height: 100vh;
+ overflow-y: auto; // 전체 페이지에 스크롤이 생긴도록 설정
+ display: flex;
+ flex-direction: column;
+`;
+
+// SidebarWrapper 스타일 컨텐츠
const SidebarWrapper = styled.div<{ isOpen: boolean }>`
position: fixed;
left: 0;
@@ -75,23 +86,30 @@ const SidebarWrapper = styled.div<{ isOpen: boolean }>`
z-index: 1000;
`;
-// Wrapper 컴포넌트 스타일
-const Wrapper = styled.div`
- position: relative;
- height: 100vh; // 전체 화면 높이 차지
+// ContentWrapper 스타일 컨텐츠
+const ContentWrapper = styled.div<{ inputHeight: number }>`
+ flex: 1;
display: flex;
flex-direction: column;
+ align-items: center;
+ justify-content: flex-end;
+ margin-bottom: ${({ inputHeight }) =>
+ Math.min(
+ inputHeight - 40,
+ 120
+ )}px; // 메시지 입력창 높이에 따른 여백 동적 조정
+ transition: margin-left 0.3s ease-in-out;
`;
-// ContentWrapper 스타일 컴포넌트 (메시지 리스트를 포함)
-const ContentWrapper = styled.div`
- width: 95%;
- flex: 1; // 남은 공간을 모두 차지하여 MessageInput 위에 위치
- overflow-y: auto; // 메시지 리스트가 길어지면 스크롤 가능하도록 설정
- padding-bottom: 80px; // 메시지 입력창 공간 확보
+// MessageListWrapper 스타일 컨텐츠 (메시지 리스트를 포함)
+const MessageListWrapper = styled.div`
+ width: 100%;
+ flex-grow: 1;
+ overflow-y: auto;
+ margin-bottom: 20px; // 메시지 입력창과 메시지 리스트 간 여백 추가
`;
-// TutorialImageWrapper 스타일 컴포넌트
+// TutorialImageWrapper 스타일 컨텐츠
const TutorialImageWrapper = styled.div`
position: absolute;
top: 40%;
@@ -119,13 +137,11 @@ const TutorialImageWrapper = styled.div`
}
`;
-// MessageInputWrapper 스타일 컴포넌트
+// MessageInputWrapper 스타일 컨텐츠
const MessageInputWrapper = styled.div`
- position: fixed;
- bottom: 20px;
- left: 50%;
- transform: translateX(-50%);
width: 90%;
max-width: 800px;
- z-index: 100;
+ margin-top: 20px;
+ position: relative;
+ margin-bottom: 20px; // 메시지 입력창 아래 여백 추가
`;
diff --git a/src/pages/main/message-input/index.tsx b/src/pages/main/message-input/index.tsx
index b85120d..81ca961 100644
--- a/src/pages/main/message-input/index.tsx
+++ b/src/pages/main/message-input/index.tsx
@@ -8,12 +8,14 @@ interface MessageInputProps {
inputMessage: string;
setInputMessage: (message: string) => void;
onSendMessage: () => void;
+ setInputHeight: (height: number) => void; // 추가된 prop
}
export const MessageInput: React.FC = ({
inputMessage,
setInputMessage,
onSendMessage,
+ setInputHeight, // 추가된 prop
}) => {
const textareaRef = useRef(null);
const baseURL = import.meta.env.VITE_BASE_URL; // baseURL 가져오기
@@ -56,6 +58,9 @@ export const MessageInput: React.FC = ({
if (textareaRef.current) {
textareaRef.current.style.height = "auto";
textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;
+
+ // 입력창의 높이를 부모 컴포넌트에 전달
+ setInputHeight(textareaRef.current.scrollHeight);
}
};
@@ -106,7 +111,7 @@ const MessageInputContainer = styled(Box)`
const TextareaWrapper = styled.div`
position: relative;
display: flex;
- align-items: center;
+ align-items: flex-end;
`;
const StyledTextarea = styled(Textarea)`
@@ -115,12 +120,20 @@ const StyledTextarea = styled(Textarea)`
outline: none;
width: 100%;
font-size: 16px;
- padding-right: 40px;
+ padding-right: 45px; /* 전송 버튼과의 간격을 넓히기 위해 여유 공간 추가 */
resize: none;
- overflow-y: auto; // 스크롤바 추가
- max-height: 200px; // 최대 높이 설정
+ overflow-y: auto;
+ max-height: 180px; /* 높이 유지 */
min-height: 36px;
line-height: 1.5;
+ scrollbar-width: thin; /* 스크롤바의 너비를 줄임 (Firefox 지원) */
+ &::-webkit-scrollbar {
+ width: 6px; /* 스크롤바의 너비를 줄임 (Chrome, Safari 지원) */
+ }
+ &::-webkit-scrollbar-thumb {
+ background-color: #ccc; /* 스크롤바의 색상 */
+ border-radius: 10px; /* 스크롤바의 모서리를 둥글게 */
+ }
::placeholder {
color: #ccc;
}
@@ -132,8 +145,7 @@ const StyledTextarea = styled(Textarea)`
const FixedIconButton = styled(IconButton)`
position: absolute;
- right: -10px;
- bottom: -5px;
+ right: 15px; /* 버튼을 입력창 안쪽에 정확하게 배치 */
background-color: #d7d7d7;
z-index: 10;
`;