Skip to content

Commit

Permalink
refactor: RecommendList 컴포넌트 리팩토링 (#78)
Browse files Browse the repository at this point in the history
* fix: Text 컴포넌트에서 as를 사용하지 않는 부분 해결

* refactor: MarkedText 스타일 마이그레이션

* refactor: RecommendList 컴포넌트 스타일 마이그레이션

* feat: 추천 검색어 옆에 '상품' 텍스트 추가
  • Loading branch information
xodms0309 authored Apr 9, 2024
1 parent 6c8ae2b commit 0c61323
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 66 deletions.
18 changes: 11 additions & 7 deletions src/components/Common/MarkedText/MarkedText.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { Fragment } from 'react';
import styled from 'styled-components';

import { markText } from './markedText.css';

import { Text } from '@/components/Common';

interface MarkedTextProps {
text: string;
Expand All @@ -13,16 +16,17 @@ const MarkedText = ({ text, mark }: MarkedTextProps) => {
<>
{textFragments.map((fragment, index) => (
<Fragment key={`fragment-${index}`}>
{fragment.toLowerCase() === mark.toLowerCase() ? <Mark>{fragment}</Mark> : <>{fragment}</>}
{fragment.toLowerCase() === mark.toLowerCase() ? (
<mark className={markText}>{fragment}</mark>
) : (
<Text as="span" weight="semiBold">
{fragment}
</Text>
)}
</Fragment>
))}
</>
);
};

export default MarkedText;

const Mark = styled.mark`
font-weight: ${({ theme }) => theme.fontWeights.bold};
background-color: ${({ theme }) => theme.backgroundColors.default};
`;
8 changes: 8 additions & 0 deletions src/components/Common/MarkedText/markedText.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { vars } from '@/styles/theme.css';
import { style } from '@vanilla-extract/css';

export const markText = style({
color: vars.colors.primary,
fontWeight: 700,
background: vars.colors.background.default,
});
17 changes: 17 additions & 0 deletions src/components/Search/RecommendList/RecommendList.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { Meta, StoryObj } from '@storybook/react';

import RecommendList from './RecommendList';

const meta: Meta<typeof RecommendList> = {
title: 'search/RecommendList',
component: RecommendList,
};

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
args: {
searchQuery: '꼬북칩',
},
};
76 changes: 17 additions & 59 deletions src/components/Search/RecommendList/RecommendList.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Button, Text } from '@fun-eat/design-system';
import type { MouseEventHandler } from 'react';
import { useRef } from 'react';
import styled from 'styled-components';

import { MarkedText } from '@/components/Common';
import { backdrop, container, productButton, wrapper } from './recommendList.css';

import { MarkedText, Text } from '@/components/Common';
import { useIntersectionObserver } from '@/hooks/common';
import { useInfiniteProductSearchAutocompleteQuery } from '@/hooks/queries/search';
import { vars } from '@/styles/theme.css';

interface RecommendListProps {
searchQuery: string;
Expand All @@ -21,72 +22,29 @@ const RecommendList = ({ searchQuery, handleSearchClick, handleAutocompleteClose
const products = searchResponse.pages.flatMap((page) => page.products);

if (products.length === 0) {
return <ErrorText>검색어가 포함된 상품을 찾지 못했어요</ErrorText>;
return <Text>검색어가 포함된 상품을 찾지 못했어요</Text>;
}

return (
<RecommendListContainer>
<Backdrop onClick={handleAutocompleteClose} />
<RecommendListWrapper>
<div className={container}>
<div className={backdrop} onClick={handleAutocompleteClose} />
<ul className={wrapper}>
{products.map(({ id, name }) => (
<li key={id}>
<ProductButton
type="button"
customWidth="100%"
customHeight="100%"
color="white"
value={name}
onClick={handleSearchClick}
>
<button className={productButton} type="button" color="white" value={name} onClick={handleSearchClick}>
<MarkedText text={name} mark={searchQuery} />
</ProductButton>
<div style={{ width: '10px' }} />
<Text size="caption4" weight="semiBold" color="disabled">
상품
</Text>
</button>
<hr style={{ border: `0.5px solid ${vars.colors.border.default}` }} />
</li>
))}
</RecommendListWrapper>
</ul>
<div ref={scrollRef} aria-hidden />
</RecommendListContainer>
</div>
);
};

export default RecommendList;

const Backdrop = styled.div`
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
`;

const RecommendListContainer = styled.div`
position: absolute;
top: 100%;
left: 0;
right: 0;
max-height: 150px;
padding: 10px 0;
border: 1px solid ${({ theme }) => theme.borderColors.default};
background-color: ${({ theme }) => theme.backgroundColors.default};
overflow-y: auto;
`;

const RecommendListWrapper = styled.ul`
position: relative;
width: 100%;
& > li {
height: 36px;
padding: 0 10px;
line-height: 36px;
}
`;

const ProductButton = styled(Button)`
text-align: left;
`;

const ErrorText = styled(Text)`
height: 36px;
padding: 0 10px;
line-height: 36px;
`;
34 changes: 34 additions & 0 deletions src/components/Search/RecommendList/recommendList.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { vars } from '@/styles/theme.css';
import { style } from '@vanilla-extract/css';

export const container = style({
position: 'absolute',
minWidth: 360,
maxHeight: 150,
padding: '10px 0',
background: vars.colors.background.default,
overflowY: 'auto',
});

export const backdrop = style({
position: 'fixed',
top: 0,
left: 0,
bottom: 0,
right: 0,
});

export const wrapper = style({
position: 'relative',
width: '100%',
});

export const productButton = style({
display: 'flex',
alignItems: 'center',
padding: '14px 0',
color: '#232527',
fontSize: '1.6rem',
fontWeight: 400,
textAlign: 'left',
});

0 comments on commit 0c61323

Please sign in to comment.