Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fix/BAR-264] 끄적이는 스크롤 이슈 해결 #87

Merged
merged 3 commits into from
Feb 24, 2024
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
1 change: 0 additions & 1 deletion src/components/Card/style.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ export const menu = style({
top: '16px',
right: '16px',
padding: '8px',
zIndex: 10,
});

export const header = style([
Expand Down
2 changes: 2 additions & 0 deletions src/components/Dropdown/style.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export const wrapper = style({

export const trigger = style({
width: 'fit-content',
position: 'relative',
zIndex: 1,
});

export const top = createVar();
Expand Down
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
10 changes: 6 additions & 4 deletions src/components/Layout/MainPageTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,12 @@ const MainPageTab = ({
</Tabs.List>
</div>

<section className={styles.tabWrapper}>
<Tabs.Content value="write">{write}</Tabs.Content>
<Tabs.Content value="refer">{refer}</Tabs.Content>
</section>
<Tabs.Content className={styles.tabWrapper} value="write">
{write}
</Tabs.Content>
<Tabs.Content className={styles.tabWrapper} value="refer">
{refer}
</Tabs.Content>
</Tabs>
);
};
Expand Down
8 changes: 7 additions & 1 deletion src/domain/끄적이는/components/Card/Today/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,14 @@ const WriteTodayCard = ({
icon="spelling"
content="맞춤법 검사"
onClick={handleSpellCheck}
className={styles.tooltipButton}
/>
<TooltipButton
icon="copy"
content="복사"
onClick={handleCopyClick}
className={styles.tooltipButton}
/>
<TooltipButton icon="copy" content="복사" onClick={handleCopyClick} />
<FolderDropdown
isArchived={memo.isArchived}
memoFolders={memoFolders}
Expand Down
5 changes: 5 additions & 0 deletions src/domain/끄적이는/components/Card/Today/style.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,8 @@ export const editCompleteButton = style([
},
},
]);

export const tooltipButton = style({
position: 'relative',
zIndex: 1,
});
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',
});
4 changes: 2 additions & 2 deletions src/domain/끄적이는/components/Today/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const TodayTemoralMemos = ({ memos, memoFolders }: TodayTemoralMemosProps) => {
}

return (
<section>
<>
<DayMessage icon="clockActive">오늘 끄적인 문장</DayMessage>
<ul className={styles.container}>
{memos.map((memo) => (
Expand All @@ -34,7 +34,7 @@ const TodayTemoralMemos = ({ memos, memoFolders }: TodayTemoralMemosProps) => {
/>
))}
</ul>
</section>
</>
);
};

Expand Down
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
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,8 @@ export const count = style({
fontSize: '14px',
color: COLORS['Grey/500'],
});

export const tooltipButton = style({
position: 'relative',
zIndex: 1,
});
Loading
Loading