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

[FE] 인풋 컴포넌트 디자인 수정 및 로그인 페이지 디자인 수정 #417

Merged
merged 21 commits into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
f080eb1
chore: ios 기기에서 버튼 텍스트 색상이 파란색으로 보였던 문제 해결
hwinkr Oct 19, 2024
ae22916
chore: BottomFixedButton 높이 수정
hwinkr Oct 19, 2024
0a1d4e6
feat: floating 스타일, 타입 추가
hwinkr Oct 19, 2024
87084c9
feat: FloatingInput 구현
hwinkr Oct 19, 2024
94ee0cb
feat: 어떤 입력 Field 인지 나타내는 Title 컴포넌트 생성
hwinkr Oct 19, 2024
f6dd55c
refactor: FloatingInput을 사용해서 약속을 생성하는 것으로 변경
hwinkr Oct 19, 2024
d7d0c13
chore: DESCRIPTION, ERROR_MESSAGE를 구분
hwinkr Oct 19, 2024
8e8beb7
feat: 스크롤을 막는 컴포넌트 구현
hwinkr Oct 19, 2024
e92fa4a
refactor: 약속 참여자 로그인 페이지 로직, 스타일 수정
hwinkr Oct 19, 2024
4f5acae
refactor: 도메인 정책 변경으로 인한, 1년 뒤의 약속을 생성하려고 하는 경우 토스트 메시지로 알려주는 로직 추가
hwinkr Oct 19, 2024
80d1286
design: css 컨벤션을 맞추기 위해 rem으로 수정
hwinkr Oct 19, 2024
490ddeb
refactor: FloatingLabelInput으로 컴포넌트명 수정, 불필요햔 isFocused 상태 제거
hwinkr Oct 22, 2024
4b21dc5
chore: 컴포넌트명 변경 사항 반영, 버튼 텍스트 상수화 파일명 수정
hwinkr Oct 22, 2024
af03a30
chore: 직관적인 함수명을 사용하는 것으로 수정
hwinkr Oct 22, 2024
9e56798
chore: IOS 기기에서 드롭다운 텍스트가 파란색으로 보이는 문제 해결
hwinkr Oct 22, 2024
8777484
chore: css 선언 순서 수정
hwinkr Oct 22, 2024
317546c
refactor: 달(Month)를 이동시키는 함수 추상화
hwinkr Oct 22, 2024
47dae2c
test: 1년 범위를 벗어난 경우 토스트 UI를 활용해서 피드백을 전달하는 책임 테스트 추가
hwinkr Oct 22, 2024
eba1fca
chore: 테스트 환경에서 절대경로를 인식해야 하는 폴더 추가, svg를 자바스크립트 모듈로 바라볼 수 있도록 설정 추가
hwinkr Oct 22, 2024
0329517
design: 바텀고정버튼 높이 수정 변경 반영
hwinkr Oct 22, 2024
3308c01
chore: 불필요한 예외 처리 로직 제거
hwinkr Oct 22, 2024
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
6 changes: 6 additions & 0 deletions frontend/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module.exports = {
testEnvironment: 'jsdom',
transform: {
'^.+.tsx?$': ['ts-jest', {}],
'^.+\\.svg$': '<rootDir>/svgTransformer.js',
},
testEnvironmentOptions: {
customExportConditions: [''],
Expand All @@ -13,5 +14,10 @@ module.exports = {
moduleNameMapper: {
'^@utils/(.*)$': '<rootDir>/src/utils/$1',
'^@constants/(.*)$': '<rootDir>/src/constants/$1',
'^@contexts/(.*)$': '<rootDir>/src/contexts/$1',
'^@components/(.*)$': '<rootDir>/src/components/$1',
'^@hooks/(.*)$': '<rootDir>/src/hooks/$1',
'^@assets/(.*)$': '<rootDir>/src/assets/$1',
'^@styles/(.*)$': '<rootDir>/src/styles/$1',
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { Meta, StoryObj } from '@storybook/react';

import FloatingLabelInput from '.';

const meta = {
title: 'Components/Inputs/FloatingLabelInput',
component: FloatingLabelInput,
argTypes: {
label: { control: 'text' },
isError: { control: 'boolean' },
},
} satisfies Meta<typeof FloatingLabelInput>;

export default meta;

type Story = StoryObj<typeof meta>;

export const Default: Story = {
args: {
label: '낙타해리빙봉',
placeholder: '송재석최현웅김윤경',
isError: false,
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { css } from '@emotion/react';

import theme from '@styles/theme';

export const s_floatingLabelContainer = (isError: boolean) => css`
position: relative;
display: inline-block;
width: 100%;
color: ${isError ? '#EB1E1E' : '#71717a'};

&:focus-within label {
color: ${isError ? '#EB1E1E' : theme.colors.pink.medium};
}
`;

export const s_floatingLabelInput = (isError: boolean) => css`
appearance: none;
box-shadow: ${isError ? `0 0 0 0.1rem #EB1E1E` : `0 0 0 0.1rem #71717a`};
transition: box-shadow 0.3s;

&::placeholder {
color: #71717a;
}

&:focus {
box-shadow: ${isError
? `0 0 0 0.1rem #EB1E1E`
: `0 0 0 0.1rem ${theme.colors.pink.mediumLight}`};
}
`;

export const s_floatingLabel = () => css`
position: absolute;
top: 0.4rem;
left: 1em;

${theme.typography.captionMedium};

background: transparent;

transition: color 0.3s;
`;
34 changes: 34 additions & 0 deletions frontend/src/components/FloatingInput/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import type { InputProps } from '@components/_common/Input';
import Input from '@components/_common/Input';

import {
s_floatingLabel,
s_floatingLabelContainer,
s_floatingLabelInput,
} from './FloatingLabelInput.styles';

interface FloatingLabelInputProps extends InputProps {
label: string;
isError: boolean;
}
export default function FloatingLabelInput({
label,
placeholder,
isError,
...props
}: FloatingLabelInputProps) {
return (
<div css={s_floatingLabelContainer(isError)}>
<label css={s_floatingLabel} htmlFor={label}>
{label}
</label>
<Input
variant="floating"
css={s_floatingLabelInput(isError)}
placeholder={placeholder}
id={label}
{...props}
/>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export const s_rangeStart = (isAllRangeSelected: boolean) => css`

position: absolute;
top: 0;
right: 0.4px;
right: 0.02rem;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Q]

어째서 0.04rem이 아니라 0.02rem일까요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hw0603 페드로와 함께 달력 UI에 대해서 QA를 진행했었는데요..! 0.02rem이 사각형과 삼각형 사이의 간격을 최소화할 수 있는 위치인 것 같아서 이렇게 수정하게 되었습니다!

bottom: 0;

width: 20%;
Expand Down
21 changes: 21 additions & 0 deletions frontend/src/components/ScrollBlock/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { PropsWithChildren } from 'react';
import { useEffect, useRef } from 'react';

export default function ScrollBlock({ children }: PropsWithChildren) {
const contentRef = useRef<HTMLDivElement>(null);

useEffect(() => {
const preventTouchMove = (e: TouchEvent) => {
e.preventDefault();
};

// 터치 이벤트를 사용해서 스크롤을 할 경우, 해당 스크롤을 막는다는 것을 브라우저에게 명시적으로 알려주기 위해서 passive 속성 추가(@해리)
document.addEventListener('touchmove', preventTouchMove, { passive: false });

return () => {
document.removeEventListener('touchmove', preventTouchMove);
};
}, []);

return <div ref={contentRef}>{children}</div>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ import { css } from '@emotion/react';
export const s_dropdownContainer = css`
display: flex;
gap: 1.2rem;
justify-content: flex-start;
align-items: center;
justify-content: flex-start;
`;
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ export const s_bottomFixedStyles = css`

/* 버튼 컴포넌트의 full variants를 사용하려고 했으나 6rem보다 height값이 작아 직접 높이를 정의했어요(@해리)
full 버튼에 이미 의존하고 있는 컴포넌트들이 많아서 높이를 full 스타일을 변경할 수는 없었습니다.

버튼의 높이가 너무 높다는 피드백을 반영하기 위해서 높이 수정 5.2rem(@해리)
*/
height: 6rem;
height: 5.2rem;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2]

제가 이전 PR에서 Funnel 마지막 단계인 날짜 선택 부분에서 BottomFixedButton에 가려지는 문제때문에 임시 div 요소를 추가했는데 해당 높이가 6rem으로 설정되어 있습니다. 한번 보고 같이 해결하면 좋을 듯 싶어요!

노션 링크의 🚀 약속 생성 시, BottomFixedButton에 가려지는 문제 확인 부분 확인하면 됩니다!

box-shadow: 0 -4px 4px rgb(0 0 0 / 25%);
`;

Expand Down
5 changes: 5 additions & 0 deletions frontend/src/components/_common/Dropdown/Dropdown.styles.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { css } from '@emotion/react';

import theme from '@styles/theme';

export const s_dropdown = css`
width: fit-content;
height: 2.8rem;
padding: 0.4rem;

color: ${theme.colors.black};

border-radius: 0.4rem;
`;
1 change: 1 addition & 0 deletions frontend/src/components/_common/Field/Field.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const s_field = css`
display: flex;
flex-direction: column;
gap: 0.8rem;
margin-bottom: 1.2rem;
`;

export const s_label = css`
Expand Down
14 changes: 14 additions & 0 deletions frontend/src/components/_common/Field/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import type { ReactNode } from 'react';

import FloatingLabelInput from '@components/FloatingInput';

import Text from '../Text';
import {
s_description,
s_errorMessage,
Expand All @@ -16,6 +19,14 @@ const Field = ({ children }: FieldProps) => {
return <div css={s_field}>{children}</div>;
};

interface FieldTitleProps {
title: string;
}

const FieldTitle = ({ title }: FieldTitleProps) => {
return <Text typo="subTitleBold">{title}</Text>;
};

interface FieldLabelProps {
id: string;
labelText: string;
Expand All @@ -29,6 +40,7 @@ const FieldLabel = ({ id, labelText }: FieldLabelProps) => (

interface FieldDescriptionProps {
description?: string;
accentText?: string;
}

const FieldDescription = ({ description }: FieldDescriptionProps) =>
Expand All @@ -44,8 +56,10 @@ const FieldErrorMessage = ({ errorMessage }: FieldErrorMessageProps) => (
</div>
);

Field.Title = FieldTitle;
Field.Label = FieldLabel;
Field.Description = FieldDescription;
Field.ErrorMessage = FieldErrorMessage;
Field.FloatingLabelInput = FloatingLabelInput;

export default Field;
12 changes: 9 additions & 3 deletions frontend/src/components/_common/Input/Input.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import theme from '@styles/theme';

const baseInputStyle = css`
width: 100%;
height: 4.4rem;
padding: 0.8rem;
outline-color: ${theme.colors.primary};
height: 4.8rem;
outline: none;
${theme.typography.bodyMedium}
`;

Expand All @@ -19,4 +18,11 @@ export const s_input = {
border: none;
outline: none;
`,
floating: css`
padding-top: 1.6rem; /* 텍스트를 아래로 내리기 위해 top padding을 더 줌 (@해리) */
padding-left: 1.2rem;
border: none;
${baseInputStyle}
border-radius: 1.2rem;
`,
};
5 changes: 3 additions & 2 deletions frontend/src/components/_common/Input/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import type { InputHTMLAttributes } from 'react';

import { s_input } from './Input.styles';

export type InputVariant = 'default' | 'transparent';
export type InputVariant = 'default' | 'transparent' | 'floating';

export interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
variant?: InputVariant;
isError?: boolean;
}

export default function Input({ variant = 'default', type = 'text', ...props }: InputProps) {
return <input css={s_input[variant]} type={type} {...props} />;
return <input css={s_input[variant]} type={type} spellCheck={false} {...props} />;
}
5 changes: 5 additions & 0 deletions frontend/src/constants/buttons.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const MEETING_BUTTON_TEXTS = {
create: '약속 생성하기',
next: '다음',
register: '등록하러 가기',
};
29 changes: 28 additions & 1 deletion frontend/src/constants/inputFields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,35 @@ export const INPUT_RULES = {
};

export const FIELD_DESCRIPTIONS = {
meetingName: '약속 이름은 1~10자 사이로 입력해 주세요.',
nickname: '1~5자 사이로 입력해 주세요.',
password: '4자리 숫자로 입력해 주세요.',
date: '날짜를 하나씩 클릭해 여러 날짜를 선택하거나\n시작일과 종료일을 클릭해 사이의 모든 날짜를 선택해 보세요',
};

export const FIELD_TITLES = {
meetingName: '약속 정보 입력',
meetingHostInfo: '약속 주최자 정보 입력',
meetingDateTime: '약속 후보 날짜 선택',
meetingTimeRange: '약속 시간 범위 선택',
attendeeLogin: '내 정보 입력',
};

export const FIELD_LABELS = {
meetingName: '약속 이름',
nickname: '닉네임',
password: '비밀번호',
onlyDate: '날짜만 선택할래요',
};

export const FIELD_PLACEHOLDERS = {
meetingName: '10자 이내의 약속 이름 입력',
nickname: '5자 이내의 약속 닉네임 입력',
password: '4자리 숫자 입력',
};

export const FIELD_ERROR_MESSAGES = {
meetingName: '약속 이름은 1~10자 사이로 입력해 주세요.',
nickname: '닉네임은 1~5자 사이로 입력해 주세요.',
password: '비밀번호는 4자리 숫자로 입력해 주세요.',
date: '날짜를 하나씩 클릭해 여러 날짜를 선택하거나\n시작일과 종료일을 클릭해 사이의 모든 날짜를 선택해 보세요',
};
3 changes: 3 additions & 0 deletions frontend/src/constants/toasts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const TOAST_MESSAGES = {
OUT_OF_ONE_YEAR_RANGE: '최대 1년뒤의 약속만 생성할 수 있어요',
};
8 changes: 8 additions & 0 deletions frontend/src/hooks/__test__/Providers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { PropsWithChildren } from 'react';

import ToastProvider from '@contexts/ToastProvider';

// 필요한 _Provider 들은 유동적으로 추가해서 테스트 환경에서 사용할 수 있어요(@해리)
export default function Providers({ children }: PropsWithChildren) {
return <ToastProvider>{children}</ToastProvider>;
}
11 changes: 11 additions & 0 deletions frontend/src/hooks/__test__/renderHookWithProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { RenderOptions } from '@testing-library/react';
import { renderHook } from '@testing-library/react';

import Providers from './Providers';

export default function render<T>(callback: () => T, options?: Omit<RenderOptions, 'wrapper'>) {
return renderHook(callback, {
wrapper: Providers,
...options,
});
}
Loading