diff --git a/src/components/icon/index.tsx b/src/components/icon/index.tsx
index f26d295b..61760f69 100644
--- a/src/components/icon/index.tsx
+++ b/src/components/icon/index.tsx
@@ -1,53 +1,52 @@
-// This file is auto-generated. Do not edit manually.
import { type ComponentProps } from 'react';
-import type { IconMetadata } from 'flexisvg';
+import { iconComponentMap } from './registry';
-export type DynamicIconId =
- | 'arrow-down'
- | 'arrow-up'
- | 'bell-read'
- | 'calendar-1'
- | 'calendar-2'
- | 'check'
- | 'chevron-left-1'
- | 'chevron-left-2'
- | 'chevron-right-1'
- | 'clock'
- | 'edit-bar'
- | 'edit'
- | 'heart'
- | 'home'
- | 'kebab'
- | 'map-pin-1'
- | 'map-pin-2'
- | 'message'
- | 'plus'
- | 'search'
- | 'send'
- | 'small-x-1'
- | 'small-x-2'
- | 'symbol'
- | 'tag'
- | 'user-1'
- | 'user-2'
- | 'users-1'
- | 'users-2'
- | 'x-1'
- | 'x-2';
-export type ResizableIconId =
- | 'bell-unread'
- | 'congratulate'
- | 'empty'
- | 'google-login'
- | 'kick'
- | 'not-found'
- | 'plus-circle'
- | 'visibility-false'
- | 'visibility-true'
- | 'wego-logo';
+export const iconMetadataMap = [
+ { id: 'arrow-down', variant: 'dynamic' },
+ { id: 'arrow-up', variant: 'dynamic' },
+ { id: 'bell-read', variant: 'dynamic' },
+ { id: 'calendar-1', variant: 'dynamic' },
+ { id: 'calendar-2', variant: 'dynamic' },
+ { id: 'check', variant: 'dynamic' },
+ { id: 'chevron-left-1', variant: 'dynamic' },
+ { id: 'chevron-left-2', variant: 'dynamic' },
+ { id: 'chevron-right-1', variant: 'dynamic' },
+ { id: 'clock', variant: 'dynamic' },
+ { id: 'edit-bar', variant: 'dynamic' },
+ { id: 'edit', variant: 'dynamic' },
+ { id: 'heart', variant: 'dynamic' },
+ { id: 'home', variant: 'dynamic' },
+ { id: 'kebab', variant: 'dynamic' },
+ { id: 'map-pin-1', variant: 'dynamic' },
+ { id: 'map-pin-2', variant: 'dynamic' },
+ { id: 'message', variant: 'dynamic' },
+ { id: 'plus', variant: 'dynamic' },
+ { id: 'search', variant: 'dynamic' },
+ { id: 'send', variant: 'dynamic' },
+ { id: 'small-x-1', variant: 'dynamic' },
+ { id: 'small-x-2', variant: 'dynamic' },
+ { id: 'symbol', variant: 'dynamic' },
+ { id: 'tag', variant: 'dynamic' },
+ { id: 'user-1', variant: 'dynamic' },
+ { id: 'user-2', variant: 'dynamic' },
+ { id: 'users-1', variant: 'dynamic' },
+ { id: 'users-2', variant: 'dynamic' },
+ { id: 'x-1', variant: 'dynamic' },
+ { id: 'x-2', variant: 'dynamic' },
+ { id: 'bell-unread', variant: 'resizable' },
+ { id: 'congratulate', variant: 'resizable' },
+ { id: 'empty', variant: 'resizable' },
+ { id: 'google-login', variant: 'resizable' },
+ { id: 'kick', variant: 'resizable' },
+ { id: 'not-found', variant: 'resizable' },
+ { id: 'plus-circle', variant: 'resizable' },
+ { id: 'visibility-false', variant: 'resizable' },
+ { id: 'visibility-true', variant: 'resizable' },
+ { id: 'wego-logo', variant: 'resizable' },
+] as const;
-export type IconId = DynamicIconId | ResizableIconId;
+export type IconId = (typeof iconMetadataMap)[number]['id'];
type IconProps = ComponentProps<'svg'> & {
id: IconId;
@@ -55,176 +54,6 @@ type IconProps = ComponentProps<'svg'> & {
};
export const Icon = ({ id, size = 24, ...props }: IconProps) => {
- return (
-
- );
+ const IconComponent = iconComponentMap[id];
+ return
;
};
-
-export const iconMetadataMap: IconMetadata[] = [
- {
- id: 'arrow-down',
- variant: 'dynamic',
- },
- {
- id: 'arrow-up',
- variant: 'dynamic',
- },
- {
- id: 'bell-read',
- variant: 'dynamic',
- },
- {
- id: 'calendar-1',
- variant: 'dynamic',
- },
- {
- id: 'calendar-2',
- variant: 'dynamic',
- },
- {
- id: 'check',
- variant: 'dynamic',
- },
- {
- id: 'chevron-left-1',
- variant: 'dynamic',
- },
- {
- id: 'chevron-left-2',
- variant: 'dynamic',
- },
- {
- id: 'chevron-right-1',
- variant: 'dynamic',
- },
- {
- id: 'clock',
- variant: 'dynamic',
- },
- {
- id: 'edit-bar',
- variant: 'dynamic',
- },
- {
- id: 'edit',
- variant: 'dynamic',
- },
- {
- id: 'heart',
- variant: 'dynamic',
- },
- {
- id: 'home',
- variant: 'dynamic',
- },
- {
- id: 'kebab',
- variant: 'dynamic',
- },
- {
- id: 'map-pin-1',
- variant: 'dynamic',
- },
- {
- id: 'map-pin-2',
- variant: 'dynamic',
- },
- {
- id: 'message',
- variant: 'dynamic',
- },
- {
- id: 'plus',
- variant: 'dynamic',
- },
- {
- id: 'search',
- variant: 'dynamic',
- },
- {
- id: 'send',
- variant: 'dynamic',
- },
- {
- id: 'small-x-1',
- variant: 'dynamic',
- },
- {
- id: 'small-x-2',
- variant: 'dynamic',
- },
- {
- id: 'symbol',
- variant: 'dynamic',
- },
- {
- id: 'tag',
- variant: 'dynamic',
- },
- {
- id: 'user-1',
- variant: 'dynamic',
- },
- {
- id: 'user-2',
- variant: 'dynamic',
- },
- {
- id: 'users-1',
- variant: 'dynamic',
- },
- {
- id: 'users-2',
- variant: 'dynamic',
- },
- {
- id: 'x-1',
- variant: 'dynamic',
- },
- {
- id: 'x-2',
- variant: 'dynamic',
- },
- {
- id: 'bell-unread',
- variant: 'resizable',
- },
- {
- id: 'congratulate',
- variant: 'resizable',
- },
- {
- id: 'empty',
- variant: 'resizable',
- },
- {
- id: 'google-login',
- variant: 'resizable',
- },
- {
- id: 'kick',
- variant: 'resizable',
- },
- {
- id: 'not-found',
- variant: 'resizable',
- },
- {
- id: 'plus-circle',
- variant: 'resizable',
- },
- {
- id: 'visibility-false',
- variant: 'resizable',
- },
- {
- id: 'visibility-true',
- variant: 'resizable',
- },
- {
- id: 'wego-logo',
- variant: 'resizable',
- },
-];
diff --git a/src/components/icon/registry/index.ts b/src/components/icon/registry/index.ts
new file mode 100644
index 00000000..b8e9592f
--- /dev/null
+++ b/src/components/icon/registry/index.ts
@@ -0,0 +1,89 @@
+import { type FC, type SVGProps } from 'react';
+
+import IconArrowDown from '../../../../public/icons/dynamic/icon-arrow-down.svg';
+import IconArrowUp from '../../../../public/icons/dynamic/icon-arrow-up.svg';
+import IconBellRead from '../../../../public/icons/dynamic/icon-bell-read.svg';
+import IconCalendar1 from '../../../../public/icons/dynamic/icon-calendar-1.svg';
+import IconCalendar2 from '../../../../public/icons/dynamic/icon-calendar-2.svg';
+import IconCheck from '../../../../public/icons/dynamic/icon-check.svg';
+import IconChevronLeft1 from '../../../../public/icons/dynamic/icon-chevron-left-1.svg';
+import IconChevronLeft2 from '../../../../public/icons/dynamic/icon-chevron-left-2.svg';
+import IconChevronRight1 from '../../../../public/icons/dynamic/icon-chevron-right-1.svg';
+import IconClock from '../../../../public/icons/dynamic/icon-clock.svg';
+import IconEdit from '../../../../public/icons/dynamic/icon-edit.svg';
+import IconEditBar from '../../../../public/icons/dynamic/icon-edit-bar.svg';
+import IconHeart from '../../../../public/icons/dynamic/icon-heart.svg';
+import IconHome from '../../../../public/icons/dynamic/icon-home.svg';
+import IconKebab from '../../../../public/icons/dynamic/icon-kebab.svg';
+import IconMapPin1 from '../../../../public/icons/dynamic/icon-map-pin-1.svg';
+import IconMapPin2 from '../../../../public/icons/dynamic/icon-map-pin-2.svg';
+import IconMessage from '../../../../public/icons/dynamic/icon-message.svg';
+import IconPlus from '../../../../public/icons/dynamic/icon-plus.svg';
+import IconSearch from '../../../../public/icons/dynamic/icon-search.svg';
+import IconSend from '../../../../public/icons/dynamic/icon-send.svg';
+import IconSmallX1 from '../../../../public/icons/dynamic/icon-small-x-1.svg';
+import IconSmallX2 from '../../../../public/icons/dynamic/icon-small-x-2.svg';
+import IconSymbol from '../../../../public/icons/dynamic/icon-symbol.svg';
+import IconTag from '../../../../public/icons/dynamic/icon-tag.svg';
+import IconUser1 from '../../../../public/icons/dynamic/icon-user-1.svg';
+import IconUser2 from '../../../../public/icons/dynamic/icon-user-2.svg';
+import IconUsers1 from '../../../../public/icons/dynamic/icon-users-1.svg';
+import IconUsers2 from '../../../../public/icons/dynamic/icon-users-2.svg';
+import IconX1 from '../../../../public/icons/dynamic/icon-x-1.svg';
+import IconX2 from '../../../../public/icons/dynamic/icon-x-2.svg';
+import IconBellUnread from '../../../../public/icons/resizable/icon-bell-unread.svg';
+import IconCongratulate from '../../../../public/icons/resizable/icon-congratulate.svg';
+import IconEmpty from '../../../../public/icons/resizable/icon-empty.svg';
+import IconGoogleLogin from '../../../../public/icons/resizable/icon-google-login.svg';
+import IconKick from '../../../../public/icons/resizable/icon-kick.svg';
+import IconNotFound from '../../../../public/icons/resizable/icon-not-found.svg';
+import IconPlusCircle from '../../../../public/icons/resizable/icon-plus-circle.svg';
+import IconVisibilityFalse from '../../../../public/icons/resizable/icon-visibility-false.svg';
+import IconVisibilityTrue from '../../../../public/icons/resizable/icon-visibility-true.svg';
+import IconWegoLogo from '../../../../public/icons/resizable/icon-wego-logo.svg';
+
+type SvgComponent = FC
>;
+
+export const iconComponentMap: Record = {
+ 'arrow-down': IconArrowDown,
+ 'arrow-up': IconArrowUp,
+ 'bell-read': IconBellRead,
+ 'calendar-1': IconCalendar1,
+ 'calendar-2': IconCalendar2,
+ check: IconCheck,
+ 'chevron-left-1': IconChevronLeft1,
+ 'chevron-left-2': IconChevronLeft2,
+ 'chevron-right-1': IconChevronRight1,
+ clock: IconClock,
+ 'edit-bar': IconEditBar,
+ edit: IconEdit,
+ heart: IconHeart,
+ home: IconHome,
+ kebab: IconKebab,
+ 'map-pin-1': IconMapPin1,
+ 'map-pin-2': IconMapPin2,
+ message: IconMessage,
+ plus: IconPlus,
+ search: IconSearch,
+ send: IconSend,
+ 'small-x-1': IconSmallX1,
+ 'small-x-2': IconSmallX2,
+ symbol: IconSymbol,
+ tag: IconTag,
+ 'user-1': IconUser1,
+ 'user-2': IconUser2,
+ 'users-1': IconUsers1,
+ 'users-2': IconUsers2,
+ 'x-1': IconX1,
+ 'x-2': IconX2,
+ 'bell-unread': IconBellUnread,
+ congratulate: IconCongratulate,
+ empty: IconEmpty,
+ 'google-login': IconGoogleLogin,
+ kick: IconKick,
+ 'not-found': IconNotFound,
+ 'plus-circle': IconPlusCircle,
+ 'visibility-false': IconVisibilityFalse,
+ 'visibility-true': IconVisibilityTrue,
+ 'wego-logo': IconWegoLogo,
+};
diff --git a/src/components/shared/card/card-tags/index.test.tsx b/src/components/shared/card/card-tags/index.test.tsx
index fd9a8dba..9d3fbede 100644
--- a/src/components/shared/card/card-tags/index.test.tsx
+++ b/src/components/shared/card/card-tags/index.test.tsx
@@ -2,13 +2,6 @@ import { render, screen } from '@testing-library/react';
import { type CardTag, CardTags, getLastVisibleIndex } from '.';
-// ResizeObserver 목
-global.ResizeObserver = class ResizeObserver {
- observe = jest.fn();
- disconnect = jest.fn();
- unobserve = jest.fn();
-} as unknown as typeof global.ResizeObserver;
-
describe('getLastVisibleIndex', () => {
it('태그들이 카드 너비를 넘어가지 않으면 모든 태그를 표시한다', () => {
const maxWidth = 300;
diff --git a/src/components/shared/card/card-tags/index.tsx b/src/components/shared/card/card-tags/index.tsx
index e98e0080..a2155a5d 100644
--- a/src/components/shared/card/card-tags/index.tsx
+++ b/src/components/shared/card/card-tags/index.tsx
@@ -1,8 +1,3 @@
-'use client';
-
-/* eslint-disable react-hooks/set-state-in-effect */
-import { useCallback, useLayoutEffect, useRef, useState } from 'react';
-
export type CardTag = {
id: string | number;
label: string;
@@ -11,14 +6,6 @@ export type CardTag = {
type CardTagsProps = {
tags: CardTag[];
};
-
-const TAG_GAP = 4;
-
-const BASE_TAG_CLASSES =
- 'bg-mint-100 text-text-2xs-medium text-mint-700 inline-flex shrink-0 items-center rounded-full px-2 py-0.5';
-
-const HIDDEN_TAG_CLASSES = `${BASE_TAG_CLASSES} invisible absolute`;
-
export const getLastVisibleIndex = (
maxWidth: number,
tagWidths: number[],
@@ -44,71 +31,16 @@ export const getLastVisibleIndex = (
};
export const CardTags = ({ tags }: CardTagsProps) => {
- const containerRef = useRef(null);
-
- const tagRefs = useRef<(HTMLSpanElement | null)[]>([]);
-
- const [lastVisibleIndex, setLastVisibleIndex] = useState(null);
-
- const updateVisibleTags = useCallback(() => {
- const container = containerRef.current;
-
- if (!container || tags.length === 0) {
- setLastVisibleIndex(null);
- return;
- }
-
- const maxWidth = container.offsetWidth;
- const tagWidths: number[] = [];
-
- for (let index = 0; index < tags.length; index++) {
- const tagElement = tagRefs.current[index];
- if (!tagElement) {
- tagWidths.push(0);
- continue;
- }
-
- tagWidths.push(tagElement.offsetWidth);
- }
-
- const nextLastVisibleIndex = getLastVisibleIndex(maxWidth, tagWidths, TAG_GAP);
- setLastVisibleIndex(nextLastVisibleIndex);
- }, [tags]);
-
- useLayoutEffect(() => {
- updateVisibleTags();
-
- const container = containerRef.current;
- if (!container) return;
-
- const resizeObserver = new ResizeObserver(() => {
- updateVisibleTags();
- });
-
- resizeObserver.observe(container);
-
- return () => {
- resizeObserver.disconnect();
- };
- }, [updateVisibleTags]);
-
return (
-
- {tags?.map((tag, index) => {
- const isVisible = lastVisibleIndex !== null && index <= lastVisibleIndex;
-
- return (
-
{
- tagRefs.current[index] = element;
- }}
- className={isVisible ? BASE_TAG_CLASSES : HIDDEN_TAG_CLASSES}
- >
- {tag.label}
-
- );
- })}
+
+ {tags?.map((tag) => (
+
+ {tag.label}
+
+ ))}
);
};
diff --git a/src/lib/fonts.ts b/src/lib/fonts.ts
deleted file mode 100644
index 1d1a4c75..00000000
--- a/src/lib/fonts.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import localFont from 'next/font/local';
-
-export const pretendard = localFont({
- src: [{ path: '../assets/fonts/PretendardVariable.woff2', weight: '45 920' }],
- variable: '--font-pretendard',
- display: 'swap',
-});
diff --git a/src/styles/globals.css b/src/styles/globals.css
index 8ce49d76..cdc9969f 100644
--- a/src/styles/globals.css
+++ b/src/styles/globals.css
@@ -1,3 +1,4 @@
+@import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css');
@import 'tailwindcss';
@import '../styles/base.css';
@import '../styles/colors.css';
@@ -24,6 +25,13 @@
}
body {
+ font-family:
+ 'Pretendard Variable',
+ Pretendard,
+ -apple-system,
+ BlinkMacSystemFont,
+ system-ui,
+ sans-serif;
background: var(--background);
color: var(--foreground);
}