Skip to content

Commit

Permalink
Merge pull request #49 from dnd-side-project/feat/#48
Browse files Browse the repository at this point in the history
feat: HighlightText 공통 컴포넌트 구현, 스토리 작성
  • Loading branch information
lsy20140 committed Aug 23, 2024
2 parents 566a735 + 2bee8da commit 2cbfbff
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 2 deletions.
41 changes: 41 additions & 0 deletions src/components/common/HighlightText/HighlightText.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { Meta, StoryObj } from '@storybook/react'
import HighlightText from '.'

const meta: Meta<typeof HighlightText> = {
title: 'components/common/HighlightText',
component: HighlightText,
tags: ['autodocs'],
argTypes: {
text: {
description: 'target 단어를 포함한 `전체 문장 또는 단어`입니다.',
},
target: {
description: 'highlight 하고싶은 `특정 단어`입니다.<br/>(대소문자 구분X)',
},
variant: {
description: '카테고리 종류입니다.',
control: {
type: 'radio',
},
options: [null, '비즈니스', '디자인', '개발'],
},
},
}

export default meta

type Story = StoryObj<typeof HighlightText>

export const Default: Story = {
decorators: [
(Story) => (
<div className="bg-gray-200">
<Story />
</div>
),
],
args: {
text: '“우리는 애자일(Agile)한 조직으로 변모하기 위해 노력해왔습니다. 1년 동안 모두가 힘써주신 덕분에 높은 성과를 낼 수 있었어요.”',
target: '애자일(Agile)',
},
}
38 changes: 38 additions & 0 deletions src/components/common/HighlightText/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
export type HighlightTextProps = {
text: string
target: string
variant?: '비즈니스' | '디자인' | '개발'
}

const BASE_COLOR = 'text-primary-400'
const COLORS = {
비즈니스: 'text-[#00946D]',
디자인: 'text-[#A233CB]',
개발: 'text-[#2C6DC0]',
}

export default function HighlightText({
text,
target,
variant,
}: HighlightTextProps) {
const escapeRegExp = (str: string) => {
return str.replace(/[()]/g, '\\$&') // 특수 문자 이스케이프 처리
}
const regex = new RegExp(`(${escapeRegExp(target)})`, 'gi') // target 기준으로 split하지만 ()에 포함시켜 target 포함하여 배열 반환
const splitted = text.split(regex)

return (
<p>
{splitted.map((item, idx) =>
item.toLocaleLowerCase() === target.toLocaleLowerCase() ? (
<span key={idx} className={variant ? COLORS[variant] : BASE_COLOR}>
{item}
</span>
) : (
item
),
)}
</p>
)
}
5 changes: 3 additions & 2 deletions src/components/domain/wordDetail/WordInfo/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import HighlightText from '@/components/common/HighlightText'
import HorizontalScrollArea from '@/components/common/HorizontalScrollArea'
import CategoryTag from '@/components/shared/CategoryTag'
import { DetailWordType } from '@/types/word'
Expand Down Expand Up @@ -45,8 +46,8 @@ export default function WordInfo({ word }: { word: DetailWordType }) {
<HorizontalScrollArea title="예문" titleSize="small" scrollDivisor={1}>
{example.map((example, idx) => (
<div key={idx} className="min-w-fit">
<div className="max-w-[calc(100%-9px)] relative bg-gray-200 h-fit py-6 px-5 rounded-2xl">
<p className="text-sub2 text-background break-keep">{`"${example.text}"`}</p>
<div className="max-w-[calc(100%-9px)] h-fit relative bg-gray-200 text-background text-sub2 py-6 px-5 rounded-2xl">
<HighlightText text={`"${example.text}"`} target={name} />
<Image
alt="bubble"
src={'/images/bubble_tail.svg'}
Expand Down

0 comments on commit 2cbfbff

Please sign in to comment.