Skip to content

Commit

Permalink
fix: 스크롤 처리 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
miro-ring committed Feb 24, 2024
1 parent f112121 commit 0e2b199
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 113 deletions.
80 changes: 21 additions & 59 deletions src/components/Input/WriteInput/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import type { ChangeEvent, HTMLAttributes, KeyboardEvent } from 'react';
import { useMemo, useRef, useState } from 'react';
import { assignInlineVars } from '@vanilla-extract/dynamic';
import type { HTMLAttributes, KeyboardEvent } from 'react';
import { useMemo, useRef } from 'react';

import Button from '@components/Button';
import Icon from '@components/Icon';
import { MAIN_INPUT_MAX_LENGTH } from '@constants/config';
import type { UseInputReturn } from '@hooks/useInput';
import { COLORS } from '@styles/tokens';

import * as style from './style.css';
import * as styles from './style.css';

interface WriteInputProps extends HTMLAttributes<HTMLTextAreaElement> {
inputProps: Omit<UseInputReturn, 'reset'>;
Expand All @@ -26,70 +25,37 @@ const WriteInput = ({
const { id, value, onChange } = inputProps;
const inputRef = useRef<HTMLTextAreaElement | null>(null);

const [textareaHeight, setTextareaHeight] = useState<{
row: number;
lineBreak: Record<number, boolean>;
}>({
row: 1,
lineBreak: {},
});

const isValid = useMemo(() => value.length > 0, [value.length]);

const handleResize = (e: ChangeEvent<HTMLTextAreaElement>) => {
const { scrollHeight, clientHeight, value } = e.target;

if (value.length === 0) {
setTextareaHeight((prev) => ({
row: 1,
lineBreak: { ...prev.lineBreak, [e.target.value.length]: false },
}));
}

if (scrollHeight > clientHeight) {
setTextareaHeight((prev) => ({
row: prev.row + 1,
lineBreak: { ...prev.lineBreak, [value.length - 1]: true },
}));
}

if (textareaHeight.lineBreak[value.length]) {
setTextareaHeight((prev) => ({
row: prev.row - 1,
lineBreak: { ...prev.lineBreak, [value.length]: false },
}));
}
const handleResize = () => {
if (!inputRef.current) return;
inputRef.current.setAttribute('style', 'height: 0px');
inputRef.current.setAttribute(
'style',
`height: ${inputRef.current.scrollHeight}px`,
);
};

const handleKeydownEnter = (e: KeyboardEvent<HTMLTextAreaElement>) => {
if (e.nativeEvent.isComposing) return;
if (e.nativeEvent.isComposing || !inputRef.current) return;

if (e.code === 'Enter' && !e.shiftKey) {
e.preventDefault();
setTextareaHeight({
row: 1,
lineBreak: {},
});
value.trim() && onSubmit();
inputRef.current.setAttribute('style', 'height: 27px');
onSubmit();
}
};

return (
<form className={style.conatiner}>
<div
className={style.contentWrapper}
style={assignInlineVars({
[style.inputHeight]: `${textareaHeight.row * 27}px`,
})}
>
<label htmlFor={id} className={style.label}>
<form className={styles.conatiner}>
<div className={styles.contentWrapper}>
<label htmlFor={id} className={styles.label}>
<textarea
id={id}
value={value}
ref={inputRef}
autoComplete="off"
rows={textareaHeight.row}
className={style.input}
className={styles.input}
placeholder={placeholder}
maxLength={maxLength}
onChange={onChange}
Expand All @@ -98,15 +64,11 @@ const WriteInput = ({
/>
</label>

<div
className={style.submitWrapper({
multirow: textareaHeight.row > 1,
})}
>
<div className={style.submit}>
<div className={styles.submitWrapper}>
<div className={styles.submit}>
{value.length > 0 && (
<span className={style.textCount}>
<span className={style.currentTextCount}>{value.length}</span>
<span className={styles.textCount}>
<span className={styles.currentTextCount}>{value.length}</span>
&nbsp;/&nbsp;500자
</span>
)}
Expand Down
27 changes: 7 additions & 20 deletions src/components/Input/WriteInput/style.css.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { createVar, style } from '@vanilla-extract/css';
import { recipe } from '@vanilla-extract/recipes';
import { style } from '@vanilla-extract/css';

import { COLORS } from '@styles/tokens';

Expand All @@ -13,14 +12,10 @@ export const conatiner = style({
backgroundColor: 'white',
});

export const inputHeight = createVar();
export const contentWrapper = style({
display: 'flex',
alignItems: 'center',
width: '100%',
height: inputHeight,
minHeight: '27px',
maxHeight: '260px',
});

export const label = style({
Expand All @@ -30,8 +25,8 @@ export const label = style({
export const input = style({
padding: '0',
width: '100%',
maxHeight: '216px',
resize: 'none',
height: '27px',
color: COLORS['Grey/900'],
fontSize: '17px',
lineHeight: '27px',
Expand All @@ -41,19 +36,11 @@ export const input = style({
},
});

export const submitWrapper = recipe({
base: {
display: 'flex',
alignItems: 'flex-end',
paddingLeft: '20px',
},
variants: {
multirow: {
true: {
height: '100%',
},
},
},
export const submitWrapper = style({
display: 'flex',
alignItems: 'flex-end',
paddingLeft: '20px',
height: '100%',
});

export const submit = style({
Expand Down
2 changes: 1 addition & 1 deletion src/domain/끄적이는/components/Today/index.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ export const container = style({
display: 'flex',
flexDirection: 'column',
gap: '20px',
marginBottom: '40px',
paddingBottom: '48px',
});
51 changes: 31 additions & 20 deletions src/domain/끄적이는/components/WriteTabContent/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useEffect, useRef } from 'react';
import { useEffect, useRef, useState } from 'react';
import { assignInlineVars } from '@vanilla-extract/dynamic';

import WriteInput from '@components/Input/WriteInput';
import useCreateTemporalMemo from '@domain/끄적이는/mutations/useCreateTemporalMemo';
Expand All @@ -12,6 +13,9 @@ import TodayTemoralMemos from '../Today';
import * as styles from './style.css';

const WriteTabContent = () => {
const [inputWrapperHeight, setInputWrapperHeight] = useState(0);

const inputWrapperRef = useRef<HTMLDivElement>(null);
const writeContentRef = useRef<HTMLDivElement>(null);
const writeInput = useInput({ id: 'write-input' });

Expand All @@ -22,26 +26,33 @@ const WriteTabContent = () => {
const { mutate: submitTemporalMemo } = useCreateTemporalMemo();
const { data: memoFolders } = useGetMemoFolders();

useEffect(() => {
handleScroll();
}, [todayMemos]);

const handleScroll = () => {
if (writeContentRef.current) {
writeContentRef.current.scrollTop = writeContentRef.current.scrollHeight;
}
};

const handleSubmit = () => {
submitTemporalMemo(writeInput.value);
writeInput.value.trim() && submitTemporalMemo(writeInput.value);
writeInput.reset();

handleScroll();
};

useEffect(() => {
if (!inputWrapperRef.current) return;
setInputWrapperHeight(inputWrapperRef.current.offsetHeight);
}, [writeInput.value]);

useEffect(() => {
writeContentRef.current?.scrollIntoView({
behavior: 'smooth',
block: 'end',
});
}, [todayMemos, inputWrapperHeight, writeContentRef.current?.scrollHeight]);

return (
<div className={styles.container}>
<div ref={writeContentRef} className={styles.content}>
<>
<div
className={styles.container}
style={assignInlineVars({
[styles.marginBottom]: `${inputWrapperHeight + 48}px`,
[styles.scrollMarginBottom]: `${inputWrapperHeight + 48}px`,
})}
ref={writeContentRef}
>
{!isLoadingWriteHistory && (
<Guide hasMemo={!!history.length || !!todayMemos.length} />
)}
Expand All @@ -50,11 +61,11 @@ const WriteTabContent = () => {
memos={todayMemos[0]?.temporalMemos}
memoFolders={memoFolders}
/>
<div className={styles.inputWrapper}>
<WriteInput inputProps={writeInput} onSubmit={handleSubmit} />
</div>
</div>
</div>
<div className={styles.inputWrapper} ref={inputWrapperRef}>
<WriteInput inputProps={writeInput} onSubmit={handleSubmit} />
</div>
</>
);
};

Expand Down
20 changes: 7 additions & 13 deletions src/domain/끄적이는/components/WriteTabContent/style.css.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
import { style } from '@vanilla-extract/css';
import { createVar, style } from '@vanilla-extract/css';

export const marginBottom = createVar();
export const scrollMarginBottom = createVar();

export const container = style({
height: `calc(100vh - 131px)`,
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-end',
padding: '0 40px',
marginBottom: '64px',
});

export const content = style({
overflow: 'scroll',
paddingBottom: '48px',

marginBottom,
scrollMarginBottom,
'::-webkit-scrollbar': {
display: 'none',
},
Expand All @@ -21,7 +15,7 @@ export const content = style({
export const inputWrapper = style({
position: 'fixed',
left: '50%',
bottom: '56px',
bottom: '48px',
width: '100%',
transform: 'translateX(-50%)',
maxWidth: '1120px',
Expand Down

0 comments on commit 0e2b199

Please sign in to comment.