-
Notifications
You must be signed in to change notification settings - Fork 1
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
Style/#286: 꿀팁 페이지 디자인 수정 #287
Changes from 23 commits
da26a77
57fd0e3
ec3fba0
383dcb4
2a5183b
30262e5
98639c5
7a0b4e7
617e656
05c27c2
0634a15
9deaccf
6ad84b3
1cff18c
f8b3f67
06159ce
c9844aa
34806d6
940f65f
6bf3166
ce845c1
19b2d53
c9b2f7f
26f2b58
2f1c3fc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import Image from '@components/Common/Image'; | ||
import { css } from '@emotion/react'; | ||
import React from 'react'; | ||
|
||
interface TipImageProps { | ||
title: string; | ||
webpPath: string; | ||
pngPath: string; | ||
} | ||
|
||
const TipImage = ({ title, webpPath, pngPath }: TipImageProps) => { | ||
return ( | ||
<picture> | ||
<source srcSet={webpPath} type="image/webp" /> | ||
<Image | ||
src={pngPath} | ||
size="tiny" | ||
alt={title} | ||
css={css` | ||
padding: 0 16px 16px 0; | ||
position: absolute; | ||
z-index: -1; | ||
right: 0; | ||
bottom: 0; | ||
opacity: 0.2; | ||
`} | ||
/> | ||
</picture> | ||
); | ||
}; | ||
|
||
export default TipImage; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import styled from '@emotion/styled'; | ||
import React from 'react'; | ||
|
||
interface TipSubTitleProps { | ||
subTitle: string; | ||
} | ||
|
||
const TipSubTitle = ({ subTitle }: TipSubTitleProps) => { | ||
const seperatedSubTitle = subTitle.split('\n'); | ||
return ( | ||
<SubTitle> | ||
{seperatedSubTitle.map((subTitle, index) => ( | ||
<p key={index}>{subTitle}</p> | ||
))} | ||
</SubTitle> | ||
); | ||
}; | ||
|
||
export default TipSubTitle; | ||
|
||
const SubTitle = styled.span` | ||
padding: 0 0 0 16px; | ||
line-height: 1rem; | ||
font-size: 0.8rem; | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import styled from '@emotion/styled'; | ||
import React from 'react'; | ||
|
||
interface TipTitleProps { | ||
title: string; | ||
} | ||
|
||
const TipTitle = ({ title }: TipTitleProps) => { | ||
const seperatedTitle = title.split('\n'); | ||
return ( | ||
<Title> | ||
{seperatedTitle.map((titleItem, index) => ( | ||
<p key={index}>{titleItem}</p> | ||
))} | ||
</Title> | ||
); | ||
}; | ||
|
||
export default TipTitle; | ||
|
||
const Title = styled.span` | ||
padding: 20px 0px 10px 16px; | ||
line-height: 1.2rem; | ||
font-size: 1.2rem; | ||
font-weight: bold; | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { Children, isValidElement } from 'react'; | ||
|
||
import TipImage from '../TipImage'; | ||
import TipSubTitle from '../TipSubTitle'; | ||
import TipTitle from '../TipTitle'; | ||
|
||
type TipCardChildType = typeof TipTitle | typeof TipSubTitle | typeof TipImage; | ||
|
||
const getTipCardSubElement = ( | ||
children: React.ReactNode, | ||
childType: TipCardChildType, | ||
) => { | ||
const chidrenArray = Children.toArray(children); | ||
const targetChild = chidrenArray | ||
.filter((child) => isValidElement(child) && child.type === childType) | ||
.slice(0, 2); | ||
|
||
return targetChild; | ||
}; | ||
|
||
export default getTipCardSubElement; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import styled from '@emotion/styled'; | ||
import { THEME } from '@styles/ThemeProvider/theme'; | ||
import React from 'react'; | ||
|
||
import getTipCardSubElement from './domain/getTipCardSubElement'; | ||
import TipImage from './TipImage'; | ||
import TipSubTitle from './TipSubTitle'; | ||
import TipTitle from './TipTitle'; | ||
|
||
type StrictPropsWithChildren<T = unknown> = T & { | ||
children: React.ReactNode; | ||
onClick: () => void; | ||
}; | ||
|
||
const TipCard = ({ children, onClick }: StrictPropsWithChildren) => { | ||
const tipTitle = getTipCardSubElement(children, TipTitle); | ||
const tipSubTitle = getTipCardSubElement(children, TipSubTitle); | ||
const tipImage = getTipCardSubElement(children, TipImage); | ||
|
||
return ( | ||
<Container onClick={onClick}> | ||
{tipTitle} | ||
{tipSubTitle} | ||
{tipImage} | ||
</Container> | ||
); | ||
}; | ||
|
||
export default TipCard; | ||
|
||
TipCard.TipTitle = TipTitle; | ||
TipCard.TipSubTitle = TipSubTitle; | ||
TipCard.TipImage = TipImage; | ||
|
||
const Container = styled.div` | ||
position: relative; | ||
height: 10rem; | ||
width: 10rem; | ||
display: flex; | ||
flex-direction: column; | ||
background-color: ${THEME.PRIMARY}20; | ||
border: 1px solid ${THEME.PRIMARY}30; | ||
border-radius: 10px; | ||
box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.1); | ||
gap: 5px; | ||
z-index: 1; | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import styled from '@emotion/styled'; | ||
import { THEME } from '@styles/ThemeProvider/theme'; | ||
import React from 'react'; | ||
|
||
interface InformSubTitleProps { | ||
subTitle: string; | ||
} | ||
|
||
const InformSubTitle = ({ subTitle }: InformSubTitleProps) => { | ||
const seperatedSubTitle = subTitle.split('\n'); | ||
|
||
return ( | ||
<SubTitle> | ||
{seperatedSubTitle.map((subTitle, index) => ( | ||
<p key={index}>{subTitle}</p> | ||
))} | ||
</SubTitle> | ||
); | ||
}; | ||
|
||
export default InformSubTitle; | ||
|
||
const SubTitle = styled.span` | ||
padding: 0 0 1rem 0; | ||
color: ${THEME.TEXT.GRAY}; | ||
line-height: 1.3; | ||
font-size: 0.9rem; | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import styled from '@emotion/styled'; | ||
import { THEME } from '@styles/ThemeProvider/theme'; | ||
import React from 'react'; | ||
|
||
interface InformTitleProps { | ||
title: string; | ||
} | ||
|
||
const InformTitle = ({ title }: InformTitleProps) => { | ||
return <Title>{title}</Title>; | ||
}; | ||
|
||
export default InformTitle; | ||
|
||
const Title = styled.span` | ||
padding: 1.5rem 0 1.5rem 0; | ||
color: ${THEME.TEXT.BLACK}; | ||
font-size: 1.5rem; | ||
font-weight: bold; | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import Button from '@components/Common/Button'; | ||
import { css } from '@emotion/react'; | ||
import { THEME } from '@styles/ThemeProvider/theme'; | ||
import React from 'react'; | ||
|
||
interface InformTypeButtonProps { | ||
type: string; | ||
isActive: boolean; | ||
onClick: () => void; | ||
} | ||
|
||
const InformTypeButton = ({ | ||
type, | ||
isActive, | ||
onClick, | ||
}: InformTypeButtonProps) => { | ||
return ( | ||
<Button | ||
css={css` | ||
height: 2rem; | ||
width: 4rem; | ||
border-radius: 4rem; | ||
font-size: 0.7rem; | ||
font-weight: normal; | ||
background-color: ${isActive ? THEME.BUTTON.BLUE : THEME.BUTTON.GRAY}; | ||
color: ${isActive ? THEME.TEXT.WHITE : THEME.TEXT.GRAY}; | ||
`} | ||
onClick={onClick} | ||
> | ||
{type} | ||
</Button> | ||
); | ||
}; | ||
|
||
export default InformTypeButton; |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. props 로 받은 childType 에 매핑되는 함수가 언제 적용이 되는건가요? 흐름상 해당 함수에서 childType 으로 받은 함수를 적용하여 반환할 것 같은데 코드만 봤을때 잘 모르겠네요,, |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { Children, isValidElement } from 'react'; | ||
|
||
import InformSubTitle from '../InformSubTitle'; | ||
import InformTitle from '../InformTitle'; | ||
import InformTypeButton from '../InformTypeButton'; | ||
|
||
type InformUpperLayoutChildType = | ||
| typeof InformTitle | ||
| typeof InformSubTitle | ||
| typeof InformTypeButton; | ||
Comment on lines
+7
to
+10
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. InformTitle, InformSubTitle, InformTypeButton There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 리액트 함수형 컴포넌트에 const Component = (props) => UI 따라서, const add = (a: number, b: number) => a + b;
const TipCard = ({ children, onClick }: StrictPropsWithChildren) => {
const tipTitle = getTipCardSubElement(children, TipTitle);
const tipSubTitle = getTipCardSubElement(children, TipSubTitle);
const tipImage = getTipCardSubElement(children, TipImage);
const addFunciton = getTipCardSubElement(children, add)
//...
이와 같은 에러가 발생하는 것을 알 수 있어요. |
||
|
||
const getInformUpperLayoutSubElement = ( | ||
children: React.ReactNode, | ||
childType: InformUpperLayoutChildType, | ||
) => { | ||
const childrenArray = Children.toArray(children); | ||
const targetChild = childrenArray | ||
.filter((child) => isValidElement(child) && child.type === childType) | ||
.slice(0, 2); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 왜 최대 2개까지 배열을 자르는지 궁금해요! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
이렇게 합성 컴포넌트의 자식들이 최대 2개씩 있어서 일단 2개까지 잘랐어요. 나중에 구분하는 버튼들이 많아지고 자르는 컴포넌트의 갯수에도 제한을 두려고 한다면 함수 호출부에서 어디까지 자를 것인지를 주입할 수도 있겠네요~ |
||
|
||
return targetChild; | ||
}; | ||
|
||
export default getInformUpperLayoutSubElement; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당 코드는 webp 를 지원하는 브라우저면 webp 파일을 보여주고
태그로 png를 보여주는 방식인가요?
그게 아니면
분기처리가 없는걸로 봐서 2가지 방식의 이미지를 다 보여주는 방식인가요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2개의 이미지를 다 보여주는 방식이 아니라, webp를 지원하는 브라우저면 webp를 사용해서 보여주고 그렇지 않다면 png 이미지를 보여주는 방식이에요. 여기 잘 정리되어 있어 도움 될 것 같아요~