🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
DemoInstallSign in
Socket

react-common-components-library

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-common-components-library

모던하고 접근성 높은 컴포넌트 라이브러리입니다.

1.0.8
latest
Source
npm
Version published
Weekly downloads
2
-33.33%
Maintainers
1
Weekly downloads
 
Created
Source

React Common Components Library

모던하고 접근성 높은 React 컴포넌트 라이브러리입니다.

설치

npm을 사용하여 패키지를 설치합니다:

npm install react-common-components-library

또는 yarn을 사용:

yarn add react-common-components-library

컴포넌트

1. Accordion

접을 수 있는 콘텐츠 패널을 제공하는 컴포넌트입니다.

사용법

import { Accordion } from 'react-common-components-library';

function App() {
  // 기본 사용법
  const items = [
    {
      title: "섹션 1",
      content: "섹션 1의 내용입니다."
    },
    {
      title: "섹션 2",
      content: "섹션 2의 내용입니다."
    }
  ];

  // 커스텀 아이콘 예제
  const customIcon = (isOpen) => (
    <span>{isOpen ? '📖' : '📘'}</span>
  );

  return (
    <div>
      {/* 기본 사용법 */}
      <Accordion items={items} className="custom-accordion" />
      
      {/* 다중 선택 사용법 */}
      <Accordion 
        items={items} 
        allowMultiple 
        defaultExpanded={[0]} 
      />
      
      {/* 커스텀 스타일 예제 */}
      <Accordion 
        items={items}
        titleClassName="custom-title"
        contentClassName="custom-content"
        itemClassName="custom-item"
        disableAnimation={true}
        itemGap={10}
      />
      
      {/* 커스텀 아이콘 예제 */}
      <Accordion 
        items={items}
        customIcon={customIcon}
      />
    </div>
  );
}

Props

속성타입기본값설명
itemsArray<{title: ReactNode, content: ReactNode}>필수아코디언 항목 목록
titleStyleCSSProperties-제목 스타일
contentStyleCSSProperties-내용 스타일
styleCSSProperties-컨테이너 스타일
classNamestring''아코디언 컨테이너에 적용할 추가 CSS 클래스
titleClassNamestring''아코디언 제목에 적용할 추가 CSS 클래스
contentClassNamestring''아코디언 내용에 적용할 추가 CSS 클래스
itemClassNamestring''아코디언 항목에 적용할 추가 CSS 클래스
iconClassNamestring''아코디언 화살표 아이콘에 적용할 추가 CSS 클래스
customIcon(isOpen: boolean) => ReactNode-커스텀 화살표 아이콘 컴포넌트
disableAnimationbooleanfalse애니메이션 비활성화 여부
allowMultiplebooleanfalse여러 항목을 동시에 열 수 있는지 여부
defaultExpandednumber | number[]-기본적으로 펼쳐진 항목의 인덱스 또는 인덱스 배열
onItemClick(index: number, isOpen: boolean) => void-항목을 클릭할 때 호출되는 함수
itemGapnumber1항목 간 간격 (픽셀)
itemStyleCSSProperties-아코디언 항목 스타일
iconStyleCSSProperties-아이콘 스타일

2. AlertDialog

모달 형태의 경고 대화 상자를 제공하는 컴포넌트입니다.

사용법

import { AlertDialog } from 'react-common-components-library';
import { useState } from 'react';

function App() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <>
      <button onClick={() => setIsOpen(true)}>대화 상자 열기</button>
      
      <AlertDialog 
        isOpen={isOpen}
        onClose={() => setIsOpen(false)}
        title="정말 삭제하시겠습니까?"
        description="이 작업은 취소할 수 없으며 데이터가 영구적으로 삭제됩니다."
        cancelText="취소"
        confirmText="삭제"
        onConfirm={() => console.log('삭제됨')}
        className="custom-dialog"
        overlayClassName="custom-overlay"
      />
    </>
  );
}

Props

속성타입기본값설명
isOpenboolean필수대화 상자 표시 여부
onClose() => void필수닫기 핸들러
titleReactNode"Are you sure absolutely sure?"제목
descriptionReactNode"This action cannot be undone..."설명
cancelTextstring"Cancel"취소 버튼 텍스트
confirmTextstring"Continue"확인 버튼 텍스트
onCancel() => void-취소 버튼 클릭 핸들러
onConfirm() => void-확인 버튼 클릭 핸들러
styleCSSProperties-대화 상자 스타일
titleStyleCSSProperties-제목 스타일
descriptionStyleCSSProperties-설명 스타일
actionsStyleCSSProperties-버튼 영역 스타일
cancelButtonStyleCSSProperties-취소 버튼 스타일
confirmButtonStyleCSSProperties-확인 버튼 스타일
overlayStyleCSSProperties-오버레이 스타일
classNamestring''대화 상자에 적용할 추가 CSS 클래스
overlayClassNamestring''오버레이에 적용할 추가 CSS 클래스

3. AspectRatio

지정된 가로세로 비율을 유지하는 컨테이너를 제공하는 컴포넌트입니다.

사용법

import { AspectRatio } from 'react-common-components-library';

function App() {
  return (
    <div style={{ width: '300px' }}>
      <AspectRatio ratio={16} heightRatio={9}>
        <img 
          src="https://example.com/image.jpg" 
          alt="예시 이미지"
          style={{ width: '100%', height: '100%', objectFit: 'cover' }} 
        />
      </AspectRatio>
    </div>
  );
}

Props

속성타입기본값설명
rationumber필수가로 비율
heightRationumber1세로 비율
childrenReactNode필수컨테이너 내부에 표시될 콘텐츠
classNamestring-추가 CSS 클래스

4. Avatar

사용자 프로필 이미지나 이니셜을 표시하는 컴포넌트입니다.

사용법

import { Avatar } from 'react-common-components-library';

function App() {
  return (
    <div style={{ display: 'flex', gap: '10px' }}>
      {/* 이미지가 있는 아바타 */}
      <Avatar 
        src="https://example.com/avatar.jpg" 
        alt="사용자 이름"
        size="md"
      />
      
      {/* 이미지 없이 이니셜을 표시하는 아바타 */}
      <Avatar 
        alt="홍길동"
        size="lg"
        shape="square"
        online={true}
      />
    </div>
  );
}

Props

속성타입기본값설명
srcstring-아바타에 표시할 이미지 URL
altstring''이미지가 없을 경우 표시할 대체 텍스트 (이니셜)
size'xs' | 'sm' | 'md' | 'lg' | 'xl''md'아바타 크기
shape'circle' | 'square''circle'아바타 모양
borderedbooleanfalse아바타 테두리 표시 여부
onlinebooleanfalse온라인 상태 표시 여부
classNamestring-추가 CSS 클래스

5. Button

다양한 스타일과 기능을 가진 버튼 컴포넌트입니다.

사용법

import { Button } from 'react-common-components-library';

function App() {
  return (
    <div style={{ display: 'flex', gap: '10px', flexDirection: 'column' }}>
      <Button variant="primary" onClick={() => alert('클릭됨')}>
        기본 버튼
      </Button>
      
      <Button 
        variant="secondary" 
        size="lg" 
        fullWidth={true}
      >
        크고 넓은 버튼
      </Button>
      
      <Button 
        variant="outline"
        leftIcon={<span></span>}
      >
        이전으로
      </Button>
      
      <Button 
        variant="ghost"
        rightIcon={<span></span>}
      >
        다음으로
      </Button>
      
      <Button 
        variant="primary"
        isLoading={true}
      >
        로딩 중
      </Button>
    </div>
  );
}

Props

속성타입기본값설명
childrenReactNode필수버튼 내용
variant'primary' | 'secondary' | 'outline' | 'ghost' | 'link''primary'버튼 디자인 변형
size'sm' | 'md' | 'lg''md'버튼 크기
fullWidthbooleanfalse버튼을 최대 너비로 확장할지 여부
isLoadingbooleanfalse로딩 상태 표시 여부
leftIconReactNode-버튼 왼쪽에 표시할 아이콘
rightIconReactNode-버튼 오른쪽에 표시할 아이콘
classNamestring-추가 CSS 클래스
+ 기본 버튼 속성ButtonHTMLAttributes<HTMLButtonElement>-onClick, disabled 등

6. Checkbox

사용자가 하나 이상의 항목을 목록에서 선택할 수 있는 체크박스 컴포넌트입니다.

사용법

import { Checkbox } from 'react-common-components-library';
import { useState } from 'react';

function App() {
  const [checked, setChecked] = useState(false);

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>
      <Checkbox 
        checked={checked}
        onChange={(e) => setChecked(e.target.checked)}
      >
        이용 약관에 동의합니다
      </Checkbox>
      
      <Checkbox disabled>
        비활성화된 체크박스
      </Checkbox>
      
      <Checkbox indeterminate>
        부분 선택된 체크박스
      </Checkbox>
      
      <Checkbox error>
        에러 상태 체크박스
      </Checkbox>
    </div>
  );
}

Props

속성타입기본값설명
childrenReactNode-체크박스 라벨
size'sm' | 'md' | 'lg''md'체크박스 크기
indeterminatebooleanfalse체크박스 인디터미네이트(부분 선택) 상태
errorbooleanfalse에러 상태 표시
classNamestring''체크박스 입력에 적용할 추가 CSS 클래스
wrapperClassNamestring''체크박스 컨테이너에 적용할 추가 CSS 클래스
+ 기본 input 속성InputHTMLAttributes<HTMLInputElement>-checked, onChange, disabled 등

7. Collapsible

첫 번째 항목은 항상 표시하고 나머지 항목들은 토글 버튼으로 표시/숨김을 제어할 수 있는 컴포넌트입니다.

사용법

import { Collapsible } from 'react-common-components-library';
import { useState } from 'react';

function App() {
  const [open, setOpen] = useState(false);

  return (
    <div style={{ width: '400px' }}>
      {/* 기본 사용법 */}
      <Collapsible 
        title="저장된 리포지토리"
        firstItem="@radix-ui/primitives"
        restItems={[
          "@radix-ui/colors",
          "@stitches/react",
          "@tailwindcss/ui"
        ]}
      />
      
      {/* 제어 컴포넌트 */}
      <Collapsible
        title="제어 컴포넌트 예제"
        firstItem="항상 표시되는 첫 번째 항목"
        restItems={[
          "제어되는 항목 1",
          "제어되는 항목 2",
          "제어되는 항목 3"
        ]}
        open={open}
        onOpenChange={setOpen}
      />

      {/* 커스텀 스타일링 */}
      <Collapsible
        title="커스텀 스타일 예제"
        firstItem="커스텀 첫 번째 항목"
        restItems={[
          "커스텀 항목 1",
          "커스텀 항목 2"
        ]}
        titleClassName="custom-title"
        firstItemClassName="custom-first-item"
        itemClassName="custom-item"
        toggleClassName="custom-toggle"
        disableAnimation={true}
        itemGap={20}
      />

      {/* 커스텀 화살표 */}
      <Collapsible
        title="커스텀 화살표 예제"
        firstItem="커스텀 화살표 항목"
        restItems={["항목 1", "항목 2"]}
        customUpArrow={<span></span>}
        customDownArrow={<span></span>}
      />
    </div>
  );
}

Props

속성타입기본값설명
titleReactNode필수컴포넌트 제목
firstItemReactNode필수항상 표시되는 첫 번째 항목
restItemsReactNode[]필수토글로 표시/숨김 가능한 나머지 항목들
defaultOpenbooleanfalse초기 열림 상태
openboolean-외부에서 제어할 경우 열림 상태
onOpenChange(open: boolean) => void-열림 상태가 변경될 때 호출되는 콜백
classNamestring''컴포넌트에 적용할 추가 CSS 클래스
titleClassNamestring''제목에 적용할 추가 CSS 클래스
toggleClassNamestring''토글 버튼에 적용할 추가 CSS 클래스
firstItemClassNamestring''첫 번째 항목에 적용할 추가 CSS 클래스
itemClassNamestring''나머지 항목들에 적용할 추가 CSS 클래스
arrowClassNamestring''화살표에 적용할 추가 CSS 클래스
customUpArrowReactNode-커스텀 위쪽 화살표 요소
customDownArrowReactNode-커스텀 아래쪽 화살표 요소
disableAnimationbooleanfalse애니메이션 비활성화 여부
itemGapnumber12항목 간 간격 (픽셀)
styleCSSProperties-컴포넌트에 적용할 인라인 스타일
titleStyleCSSProperties-제목에 적용할 인라인 스타일
toggleStyleCSSProperties-토글 버튼에 적용할 인라인 스타일
firstItemStyleCSSProperties-첫 번째 항목에 적용할 인라인 스타일
itemStyleCSSProperties-나머지 항목들에 적용할 인라인 스타일

8. Command

키보드 중심의 명령어 팔레트 컴포넌트로, macOS Spotlight 또는 VSCode 명령어 팔레트와 유사한 인터페이스를 제공합니다.

사용법

import { Command } from 'react-common-components-library';
import { useState } from 'react';

function App() {
  const [isOpen, setIsOpen] = useState(false);
  
  // 명령어 그룹 정의
  const commandGroups = [
    {
      label: '자주 사용하는 기능',
      items: [
        {
          id: 'calendar',
          label: '캘린더',
          icon: <CalendarIcon />, // 적절한 아이콘 컴포넌트 사용
          onSelect: () => console.log('캘린더 선택됨'),
        },
        {
          id: 'calculator',
          label: '계산기',
          icon: <CalculatorIcon />, // 적절한 아이콘 컴포넌트 사용
          onSelect: () => console.log('계산기 선택됨'),
        },
      ],
    },
    {
      label: '설정',
      items: [
        {
          id: 'profile',
          label: '프로필',
          shortcut: '⌘P',
          icon: <ProfileIcon />, // 적절한 아이콘 컴포넌트 사용
          onSelect: () => console.log('프로필 선택됨'),
        },
        {
          id: 'settings',
          label: '설정',
          shortcut: '⌘S',
          icon: <SettingsIcon />, // 적절한 아이콘 컴포넌트 사용
          onSelect: () => console.log('설정 선택됨'),
        },
      ],
    },
  ];
  
  return (
    <>
      <button onClick={() => setIsOpen(true)}>
        명령어 팔레트 열기
      </button>
      
      <Command
        isOpen={isOpen}
        onClose={() => setIsOpen(false)}
        groups={commandGroups}
        placeholder="명령어 입력 또는 검색..."
      />
    </>
  );
}

// 아이콘 컴포넌트 예시
const CalendarIcon = () => (
  <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
    <rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect>
    <line x1="16" y1="2" x2="16" y2="6"></line>
    <line x1="8" y1="2" x2="8" y2="6"></line>
    <line x1="3" y1="10" x2="21" y2="10"></line>
  </svg>
);

Props

속성타입기본값설명
isOpenboolean필수컴포넌트 열림 상태
onClose() => void필수컴포넌트 닫기 핸들러
groupsCommandGroup[]필수명령어 그룹 목록
placeholderstring"Type a command or search..."검색 입력 필드 플레이스홀더
classNamestring''컴포넌트에 적용할 추가 CSS 클래스

타입

interface CommandGroup {
  /**
   * 그룹 제목
   */
  label: string;
  /**
   * 그룹에 속한 명령어 항목들
   */
  items: CommandItem[];
}

interface CommandItem {
  /**
   * 항목의 고유 식별자
   */
  id: string;
  /**
   * 항목에 표시될 이름
   */
  label: string;
  /**
   * 항목의 아이콘
   */
  icon: ReactNode;
  /**
   * 항목의 키보드 단축키 (선택 사항)
   */
  shortcut?: string;
  /**
   * 항목 선택 시 실행할 작업
   */
  onSelect: () => void;
}

9. ContextMenu

사용자 인터페이스에 맞춤형 컨텍스트 메뉴(우클릭 메뉴)를 제공하는 컴포넌트입니다.

사용법

import { ContextMenu } from 'react-common-components-library';
import { useState } from 'react';

function App() {
  const [isOpen, setIsOpen] = useState(false);
  const [position, setPosition] = useState({ x: 0, y: 0 });
  
  // 메뉴 섹션 정의
  const menuSections = [
    {
      items: [
        {
          type: 'normal',
          label: '뒤로',
          shortcut: '⌘[',
          onClick: () => console.log('뒤로 클릭됨'),
        },
        {
          type: 'normal',
          label: '앞으로',
          shortcut: '⌘]',
          disabled: true,
        },
        {
          type: 'normal',
          label: '새로고침',
          shortcut: '⌘R',
          onClick: () => console.log('새로고침 클릭됨'),
        },
      ],
    },
    {
      items: [
        {
          type: 'checkbox',
          label: '북마크 바 표시',
          shortcut: '⌘⇧B',
          checked: true,
          onClick: () => console.log('북마크 바 토글됨'),
        },
      ],
    },
    {
      title: '사용자',
      items: [
        {
          type: 'normal',
          label: '홍길동',
          onClick: () => console.log('홍길동 선택됨'),
        },
        {
          type: 'normal',
          label: '김철수',
          onClick: () => console.log('김철수 선택됨'),
        },
      ],
    },
  ];
  
  // 우클릭 핸들러
  const handleContextMenu = (e) => {
    e.preventDefault();
    setIsOpen(true);
    setPosition({ x: e.clientX, y: e.clientY });
  };
  
  return (
    <div 
      style={{ width: '500px', height: '300px', background: '#f5f5f5' }}
      onContextMenu={handleContextMenu}
    >
      이 영역에서 마우스 오른쪽 버튼을 클릭하세요
      
      <ContextMenu
        isOpen={isOpen}
        onClose={() => setIsOpen(false)}
        x={position.x}
        y={position.y}
        sections={menuSections}
      />
    </div>
  );
}

Props

속성타입기본값설명
isOpenboolean필수메뉴 표시 여부
onClose() => void필수메뉴 닫기 핸들러
sectionsMenuSection[]필수메뉴 섹션 목록
xnumber필수메뉴 표시 X 좌표
ynumber필수메뉴 표시 Y 좌표
classNamestring''컴포넌트에 적용할 추가 CSS 클래스

타입

type MenuItemType = 'normal' | 'separator' | 'checkbox';

interface MenuItem {
  /**
   * 메뉴 항목 ID (선택적)
   */
  id?: string;
  /**
   * 메뉴 항목 타입
   */
  type: MenuItemType;
  /**
   * 메뉴 항목에 표시될 레이블
   */
  label?: ReactNode;
  /**
   * 메뉴 항목 비활성화 여부
   */
  disabled?: boolean;
  /**
   * 메뉴 항목 클릭시 실행할 작업
   */
  onClick?: () => void;
  /**
   * 키보드 단축키 표시 (선택적)
   */
  shortcut?: string;
  /**
   * 체크 여부 (checkbox 타입에서만 사용)
   */
  checked?: boolean;
  /**
   * 서브메뉴 항목들 (선택적)
   */
  items?: MenuItem[];
  /**
   * 항목 앞에 표시할 아이콘 (선택적)
   */
  icon?: ReactNode;
}

interface MenuSection {
  /**
   * 섹션 제목 (선택적)
   */
  title?: string;
  /**
   * 섹션에 포함된 메뉴 항목들
   */
  items: MenuItem[];
}

10. Dialog

사용자를 중요한 내용으로 중단시키고 응답을 기대하는 모달 다이얼로그입니다. 주의를 필요로 하는 중요한 정보를 표시하거나 사용자의 결정이 필요한 상황에서 사용합니다. 폼 레이아웃을 포함할 수 있어 프로필 편집과 같은 작업에도 적합합니다.

사용법

import { Dialog, FormField } from 'react-common-components-library';
import { useState } from 'react';

function App() {
  const [isOpen, setIsOpen] = useState(false);
  
  return (
    <div>
      <button onClick={() => setIsOpen(true)}>
        다이얼로그 열기
      </button>
      
      {/* 기본 다이얼로그 */}
      <Dialog
        isOpen={isOpen}
        onClose={() => setIsOpen(false)}
        title="다이얼로그 제목"
        description="이것은 기본 다이얼로그 내용입니다. 모달 형태로 표시되며 배경을 클릭하거나 ESC 키를 눌러 닫을 수 있습니다."
        footer={
          <div>
            <button onClick={() => setIsOpen(false)}>
              취소
            </button>
            <button 
              onClick={() => {
                alert('확인 버튼이 클릭되었습니다.');
                setIsOpen(false);
              }}
            >
              확인
            </button>
          </div>
        }
      >
        <p>다이얼로그 내용을 여기에 작성합니다.</p>
      </Dialog>
      
      {/* 프로필 편집 폼 */}
      <Dialog
        isOpen={isOpen}
        onClose={() => setIsOpen(false)}
        title="Edit profile"
        description="Make changes to your profile here. Click save when you're done."
        onSubmit={(e) => {
          e.preventDefault();
          // 폼 데이터 처리
          setIsOpen(false);
        }}
      >
        <FormField label="Name">
          <input
            type="text"
            name="name"
            defaultValue="Email"
            placeholder="Enter your name"
          />
        </FormField>
        
        <FormField label="Username">
          <input
            type="text"
            name="username"
            defaultValue="@peduarte"
            placeholder="Enter your username"
          />
        </FormField>
      </Dialog>
    </div>
  );
}

Props

속성타입기본값설명
isOpenboolean필수다이얼로그 열림 상태
onClose() => void필수다이얼로그 닫기 핸들러
titleReactNode-다이얼로그 제목
descriptionReactNode-다이얼로그 설명 또는 내용
childrenReactNode-다이얼로그 내용 (description과 함께 사용 가능)
footerReactNode-하단 버튼 또는 액션 영역
submitTextstring"Save changes"제출 버튼 텍스트
onSubmit(e: React.FormEvent) => void-폼 제출 핸들러
closeOnOverlayClickbooleantrue배경 클릭시 닫기 허용 여부
closeOnEscbooleantrueESC 키로 닫기 허용 여부
classNamestring''컴포넌트에 적용할 추가 CSS 클래스
overlayClassNamestring''오버레이에 적용할 추가 CSS 클래스
titleClassNamestring''제목에 적용할 추가 CSS 클래스
contentClassNamestring''내용에 적용할 추가 CSS 클래스
footerClassNamestring''하단 영역에 적용할 추가 CSS 클래스
widthstring-다이얼로그 너비 (px 또는 %)
maxWidthstring'500px'다이얼로그 최대 너비 (px 또는 %)
styleCSSProperties-다이얼로그 컨테이너에 적용할 스타일

FormField Props

속성타입기본값설명
labelReactNode필수필드 레이블
childrenReactNode필수필드 입력 요소
labelClassNamestring''레이블에 적용할 추가 CSS 클래스
classNamestring''필드 컨테이너에 적용할 추가 CSS 클래스

11. DropdownMenu

드롭다운 메뉴를 제공하는 컴포넌트입니다. 계층적인 메뉴 구조, 아이콘, 단축키, 하위 메뉴 등을 지원합니다.

사용법

import { DropdownMenu } from 'react-common-components-library';
import { useState } from 'react';

function App() {
  const [isOpen, setIsOpen] = useState(false);
  
  // 아이콘 컴포넌트 정의
  const ProfileIcon = () => (
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
      <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
      <circle cx="12" cy="7" r="4"></circle>
    </svg>
  );
  
  const SettingsIcon = () => (
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
      <circle cx="12" cy="12" r="3"></circle>
      <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path>
    </svg>
  );
  
  const LogoutIcon = () => (
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
      <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path>
      <polyline points="16 17 21 12 16 7"></polyline>
      <line x1="21" y1="12" x2="9" y2="12"></line>
    </svg>
  );
  
  const HelpIcon = () => (
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
      <circle cx="12" cy="12" r="10"></circle>
      <path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path>
      <line x1="12" y1="17" x2="12.01" y2="17"></line>
    </svg>
  );
  
  const ChatIcon = () => (
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
      <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
    </svg>
  );
  
  return (
    <div>
      {/* 기본 사용법 */}
      <DropdownMenu
        title="내 계정"
        isOpen={isOpen}
        onClose={() => setIsOpen(false)}
        sections={[
          {
            items: [
              { 
                id: 'profile', 
                label: '프로필', 
                icon: <ProfileIcon />, 
                onClick: () => console.log('프로필 클릭됨') 
              },
              { 
                id: 'settings', 
                label: '설정', 
                icon: <SettingsIcon />,
                shortcut: '⌘S', 
                onClick: () => console.log('설정 클릭됨') 
              },
            ]
          },
          {
            items: [
              { 
                id: 'logout', 
                label: '로그아웃', 
                icon: <LogoutIcon />, 
                onClick: () => console.log('로그아웃 클릭됨') 
              },
            ]
          }
        ]}
        trigger={
          <button onClick={() => setIsOpen(!isOpen)}>
            계정 메뉴
          </button>
        }
      />
      
      {/* 서브메뉴 사용 예제 */}
      <DropdownMenu
        title="지움말 메뉴"
        isOpen={isOpen}
        onClose={() => setIsOpen(false)}
        sections={[
          {
            items: [
              { 
                id: 'support', 
                label: '고객 지움', 
                icon: <HelpIcon />,
                hasSubmenu: true, // 선택적으로 사용 가능
                subItems: [
                  {
                    id: 'help',
                    label: '도움말 센터',
                    icon: <HelpIcon />,
                    onClick: () => console.log('도움말 센터 클릭됨')
                  },
                  {
                    id: 'chat',
                    label: '실시간 채팅',
                    icon: <ChatIcon />,
                    onClick: () => console.log('실시간 채팅 클릭됨')
                  }
                ]
              }
            ]
          }
        ]}
        trigger={
          <button onClick={() => setIsOpen(!isOpen)}>
            지움말 메뉴
          </button>
        }
      />
      
      {/* 다양한 위치 옵션 */}
      <DropdownMenu
        title="메뉴 위치"
        isOpen={isOpen}
        onClose={() => setIsOpen(false)}
        position="bottom-end"
        sections={[
          {
            items: [
              { id: 'item1', label: '항목 1', onClick: () => {} },
              { id: 'item2', label: '항목 2', onClick: () => {} },
            ]
          }
        ]}
        trigger={<button onClick={() => setIsOpen(!isOpen)}>오른쪽 정렬 메뉴</button>}
      />
      
      {/* 섹션 제목 사용 */}
      <DropdownMenu
        isOpen={isOpen}
        onClose={() => setIsOpen(false)}
        sections={[
          {
            title: "계정 설정",
            items: [
              { id: 'profile', label: '프로필', onClick: () => {} },
              { id: 'settings', label: '설정', onClick: () => {} },
            ]
          },
          {
            title: "지움말",
            items: [
              { id: 'help', label: '도움말', onClick: () => {} },
              { id: 'feedback', label: '피드백 보내기', onClick: () => {} },
            ]
          }
        ]}
        trigger={<button onClick={() => setIsOpen(!isOpen)}>섹션 메뉴</button>}
      />
    </div>
  );
}

Props

DropdownMenuProps
속성타입기본값설명
titleReactNode-드롭다운 메뉴 제목
sectionsDropdownMenuSection[]필수드롭다운 메뉴 섹션들
isOpenboolean필수메뉴 열림 상태
onClose() => void필수메뉴 닫기 핸들러
triggerReactNode-트리거 요소 (드롭다운을 열기 위한 버튼/요소)
classNamestring''컴포넌트에 적용할 추가 CSS 클래스
menuClassNamestring''메뉴 컨테이너에 적용할 추가 CSS 클래스
widthstring'300px'메뉴의 너비
position'bottom-start' | 'bottom-end' | 'top-start' | 'top-end' | 'right-start' | 'left-start''bottom-start'메뉴가 트리거 요소 기준으로 표시될 위치
DropdownMenuSection
속성타입기본값설명
titlestring-섹션 제목 (선택적)
itemsDropdownMenuItem[]필수섹션에 포함된 메뉴 항목들
classNamestring''섹션에 적용할 추가 CSS 클래스
DropdownMenuItem
속성타입기본값설명
idstring필수메뉴 항목의 고유 ID
labelstring필수메뉴 항목에 표시될 레이블
iconReactNode-항목의 아이콘
shortcutstring-단축키 표시
onClick() => void-항목 클릭 시 실행할 작업
hasSubmenubooleanfalse하위 메뉴가 있는지 여부
subItemsDropdownMenuItem[]-하위 메뉴 항목들. 메뉴 항목에 마우스를 올리면 표시됨
disabledbooleanfalse비활성화 여부
classNamestring''항목에 적용할 추가 CSS 클래스

12. HoverCard

마우스를 특정 요소 위에 올렸을 때 추가 정보를 카드 형태로 표시하는 컴포넌트입니다. SNS 프로필 미리보기, 용어 설명, 이미지 미리보기 등 다양한 상황에서 활용할 수 있습니다.

사용법

import { HoverCard } from 'react-common-components-library';
import { useState } from 'react';

function App() {
  const [isHovered, setIsHovered] = useState(false);

  return (
    <div style={{ padding: '50px', fontFamily: 'Arial' }}>
      {/* 기본 사용법 */}
      <div style={{ marginBottom: '30px' }}>
        <HoverCard
          trigger={<span style={{ fontWeight: 'bold', color: '#6366f1' }}>@홍길동</span>}
          content={
            <div style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
                <img
                  src="https://i.pravatar.cc/100"
                  alt="홍길동"
                  style={{ width: '48px', height: '48px', borderRadius: '24px' }}
                />
                <div>
                  <div style={{ fontWeight: 'bold' }}>홍길동</div>
                  <div style={{ color: '#666' }}>@honggildong</div>
                </div>
              </div>
              <div>프론트엔드 개발자 | React, TypeScript 전문</div>
              <div style={{ display: 'flex', gap: '10px' }}>
                <div>팔로워: 1,234</div>
                <div>팔로잉: 567</div>
              </div>
            </div>
          }
        />
        <span> 님이 새 글을 작성했습니다.</span>
      </div>

      {/* 다양한 위치 옵션 */}
      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '30px' }}>
        <HoverCard
          trigger={<button>Top</button>}
          content={<div>상단에 표시되는 호버 카드입니다.</div>}
          position="top"
        />
        
        <HoverCard
          trigger={<button>Right</button>}
          content={<div>오른쪽에 표시되는 호버 카드입니다.</div>}
          position="right"
        />
        
        <HoverCard
          trigger={<button>Bottom</button>}
          content={<div>하단에 표시되는 호버 카드입니다.</div>}
          position="bottom"
        />
        
        <HoverCard
          trigger={<button>Left</button>}
          content={<div>왼쪽에 표시되는 호버 카드입니다.</div>}
          position="left"
        />
      </div>

      {/* 지연 시간 설정 */}
      <div style={{ marginBottom: '30px' }}>
        <HoverCard
          trigger={<button>빠른 표시 (지연 100ms)</button>}
          content={<div>마우스를 올리면 빠르게 표시됩니다.</div>}
          openDelay={100}
          closeDelay={500}
        />
      </div>

      {/* 제어 컴포넌트 */}
      <div style={{ marginBottom: '30px' }}>
        <button 
          onMouseEnter={() => setIsHovered(true)}
          onMouseLeave={() => setIsHovered(false)}
        >
          제어 컴포넌트
        </button>
        
        <HoverCard
          trigger={<span />} // 빈 트리거 사용
          content={<div>상태로 제어되는 호버 카드입니다.</div>}
          open={isHovered}
          onOpenChange={setIsHovered}
          position="right"
        />
      </div>

      {/* 커스텀 스타일링 */}
      <div>
        <HoverCard
          trigger={<span style={{ color: 'purple', textDecoration: 'underline' }}>용어 설명</span>}
          content={
            <div>
              <h4 style={{ margin: '0 0 8px 0' }}>호버 카드</h4>
              <p style={{ margin: 0 }}>마우스를 특정 요소 위에 올렸을 때 추가 정보를 제공하는 UI 요소입니다.</p>
            </div>
          }
          cardStyle={{ 
            background: 'linear-gradient(45deg, #6366f1, #8b5cf6)',
            color: 'white',
            border: 'none'
          }}
          showArrow={true}
          arrowClassName="custom-arrow"
          width="300px"
        />
      </div>
    </div>
  );
}

Props

속성타입기본값설명
triggerReactNode필수호버 시 카드가 표시될 트리거 요소
contentReactNode필수호버 카드에 표시될 내용
openDelaynumber300카드가 표시되기까지의 지연 시간 (밀리초)
closeDelaynumber300카드가 닫히기까지의 지연 시간 (밀리초)
position'top' | 'bottom' | 'left' | 'right''bottom'카드 위치
openboolean-외부에서 제어할 때 사용하는 열림 상태
onOpenChange(open: boolean) => void-열림 상태가 변경될 때 호출되는 콜백
widthstring | number-카드 너비
styleCSSProperties-부모 요소 스타일
cardStyleCSSProperties-카드 스타일
classNamestring''부모 요소에 적용할 추가 CSS 클래스
cardClassNamestring''카드에 적용할 추가 CSS 클래스
inPortalbooleanfalse카드가 트리거보다 앞에 렌더링될지 여부
showArrowbooleantrue화살표 표시 여부
arrowClassNamestring''화살표에 적용할 추가 CSS 클래스
arrowStyleCSSProperties-화살표 스타일

13. Input

사용자로부터 텍스트 입력을 받기 위한 컴포넌트입니다.

사용법

import { Input } from 'react-common-components-library';
import { useState } from 'react';

function App() {
  const [email, setEmail] = useState('');
  
  return (
    <div style={{ padding: '20px', maxWidth: '600px' }}>
      {/* 기본 사용법 */}
      <Input
        label="이메일"
        placeholder="example@email.com"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        helperText="업무용 이메일을 입력해주세요"
      />
      
      {/* 에러 상태 */}
      <Input
        label="비밀번호"
        type="password"
        placeholder="비밀번호 입력"
        error="비밀번호는 8자 이상이어야 합니다"
        style={{ marginTop: '20px' }}
      />
      
      {/* 성공 상태 */}
      <Input
        label="사용자명"
        value="johndoe"
        success
        helperText="사용 가능한 사용자명입니다"
        style={{ marginTop: '20px' }}
      />
      
      {/* 어도먼트 사용 */}
      <Input
        label="금액"
        startAdornment="₩"
        placeholder="0"
        style={{ marginTop: '20px' }}
      />
      
      <Input
        label="웹사이트"
        endAdornment=".com"
        placeholder="example"
        style={{ marginTop: '20px' }}
      />
      
      {/* 다양한 크기 */}
      <div style={{ display: 'flex', gap: '20px', marginTop: '20px' }}>
        <Input size="sm" placeholder="작은 입력" />
        <Input size="md" placeholder="중간 입력" />
        <Input size="lg" placeholder="큰 입력" />
      </div>
      
      {/* 다양한 변형 */}
      <div style={{ display: 'flex', flexDirection: 'column', gap: '20px', marginTop: '20px' }}>
        <Input variant="outlined" placeholder="Outlined Input" />
        <Input variant="filled" placeholder="Filled Input" />
        <Input variant="standard" placeholder="Standard Input" />
      </div>
      
      {/* 구독 양식 예제 */}
      <div style={{ marginTop: '40px' }}>
        <h3>Email</h3>
        <div style={{ display: 'flex' }}>
          <Input
            placeholder="Email"
            fullWidth
            style={{
              borderTopRightRadius: 0,
              borderBottomRightRadius: 0,
            }}
          />
          <button
            style={{
              padding: '10px 20px',
              background: '#0f172a',
              color: 'white',
              border: 'none',
              borderTopRightRadius: '8px',
              borderBottomRightRadius: '8px',
              fontWeight: 'bold',
              cursor: 'pointer',
            }}
          >
            Subscribe
          </button>
        </div>
        <p style={{ marginTop: '8px', color: '#64748b', fontSize: '14px' }}>
          Enter your email address
        </p>
      </div>
    </div>
  );
}

Props

속성타입기본값설명
labelReactNode-Input에 나타날 레이블
errorstring-에러 메시지
successbooleanfalse성공 상태
helperTextReactNode-힌트 텍스트
startAdornmentReactNode-입력 필드 앞에 표시할 아이콘이나 요소
endAdornmentReactNode-입력 필드 뒤에 표시할 아이콘이나 요소
size'sm' | 'md' | 'lg''md'Input의 크기
variant'outlined' | 'filled' | 'standard''outlined'Input의 변형
fullWidthbooleanfalse가득 채우는 너비로 설정할지 여부
containerClassNamestring''컨테이너에 적용할 CSS 클래스
inputClassNamestring''입력 요소에 적용할 CSS 클래스
labelClassNamestring''레이블에 적용할 CSS 클래스
containerStyleCSSProperties-컨테이너에 적용할 스타일
idstring-폼 ID 연결용 (레이블의 for 속성)

Input 컴포넌트는 표준 HTML input 요소의 모든 속성도 지원합니다.

14. Label

레이블 컴포넌트는 입력 필드나 체크박스 같은 사용자 인터페이스 요소에 설명을 제공합니다.

사용법

import { Label } from 'react-common-components-library';
import { useState } from 'react';

function App() {
  const [accepted, setAccepted] = useState(false);
  
  return (
    <div style={{ padding: '20px', maxWidth: '600px' }}>
      {/* 기본 사용법 */}
      <div style={{ marginBottom: '20px' }}>
        <Label htmlFor="username">사용자명</Label>
        <input id="username" type="text" style={{ display: 'block', marginTop: '8px', padding: '8px', width: '100%', borderRadius: '4px', border: '1px solid #ccc' }} />
      </div>
      
      {/* 체크박스 레이블 */}
      <div style={{ marginBottom: '20px' }}>
        <Label
          hasCheckbox
          checked={accepted}
          onChange={(e) => setAccepted(e.target.checked)}
        >
          이용약관에 동의합니다
        </Label>
      </div>
      
      {/* 필수 필드 */}
      <div style={{ marginBottom: '20px' }}>
        <Label htmlFor="email" required>이메일</Label>
        <input id="email" type="email" required style={{ display: 'block', marginTop: '8px', padding: '8px', width: '100%', borderRadius: '4px', border: '1px solid #ccc' }} />
      </div>
      
      {/* 에러 상태 */}
      <div style={{ marginBottom: '20px' }}>
        <Label
          hasCheckbox
          checked={false}
          error={true}
          errorMessage="계속하려면 동의해야 합니다"
        >
          개인정보 처리방침에 동의합니다
        </Label>
      </div>
      
      {/* 다양한 크기 */}
      <div style={{ marginBottom: '20px' }}>
        <div style={{ marginBottom: '10px' }}>
          <Label size="sm" hasCheckbox>작은 레이블</Label>
        </div>
        <div style={{ marginBottom: '10px' }}>
          <Label size="md" hasCheckbox>중간 레이블</Label>
        </div>
        <div>
          <Label size="lg" hasCheckbox>큰 레이블</Label>
        </div>
      </div>
      
      {/* Accept Terms and Condition 예제 */}
      <div style={{ marginBottom: '20px' }}>
        <Label
          hasCheckbox
          checked={accepted}
          onChange={(e) => setAccepted(e.target.checked)}
          labelClassName="terms-label"
          checkboxClassName="terms-checkbox"
        >
          Accept terms and condition
        </Label>
      </div>
    </div>
  );
}

Props

속성타입기본값설명
childrenReactNode필수레이블 내용
hasCheckboxbooleanfalse체크박스 포함 여부
requiredbooleanfalse필수 필드 여부 (별표 표시)
size'sm' | 'md' | 'lg''md'레이블 크기
errorbooleanfalse에러 상태 표시
errorMessagestring-에러 메시지
labelClassNamestring''레이블에 적용할 추가 클래스명
checkboxClassNamestring''체크박스에 적용할 추가 클래스명
checkedboolean-체크박스 상태
onChange(e: React.ChangeEvent<HTMLInputElement>) => void-체크박스 상태 변경 핸들러
labelStyleReact.CSSProperties-레이블에 적용할 스타일
checkboxStyleReact.CSSProperties-체크박스에 적용할 스타일
htmlForstring-htmlFor 속성 (체크박스 ID 연결)
idstring-체크박스 ID
disabledbooleanfalse비활성화 상태

15. MenuBar

MenuBar 컴포넌트는 데스크톱 애플리케이션 스타일의 메뉴 인터페이스를 제공합니다. 수평으로 배치된 메뉴 항목과 드롭다운 메뉴, 키보드 단축키 등을 지원합니다.

사용법

import { MenuBar } from 'react-common-components-library';

function App() {
  return (
    <div style={{ padding: '20px' }}>
      {/* 기본 사용법 */}
      <MenuBar
        items={[
          {
            id: 'file',
            label: 'File',
            items: [
              {
                id: 'new-tab',
                label: 'New Tab',
                shortcut: '⌘T',
                onClick: () => console.log('New Tab clicked'),
              },
              {
                id: 'new-window',
                label: 'New Window',
                shortcut: '⌘N',
                onClick: () => console.log('New Window clicked'),
              },
              {
                id: 'new-incognito',
                label: 'New Incognito Window',
                disabled: true,
              },
              {
                id: 'separator-1',
                isSeparator: true,
              },
              {
                id: 'share',
                label: 'Share',
                items: [
                  {
                    id: 'email',
                    label: 'Email',
                    onClick: () => console.log('Email clicked'),
                  },
                  {
                    id: 'message',
                    label: 'Message',
                    onClick: () => console.log('Message clicked'),
                  },
                ],
              },
              {
                id: 'separator-2',
                isSeparator: true,
              },
              {
                id: 'print',
                label: 'Print...',
                shortcut: '⌘P',
                onClick: () => console.log('Print clicked'),
              },
            ],
          },
          {
            id: 'edit',
            label: 'Edit',
            items: [
              {
                id: 'undo',
                label: 'Undo',
                shortcut: '⌘Z',
                onClick: () => console.log('Undo clicked'),
              },
              {
                id: 'redo',
                label: 'Redo',
                shortcut: '⌘⇧Z',
                onClick: () => console.log('Redo clicked'),
              },
            ],
          },
          {
            id: 'view',
            label: 'View',
            items: [
              {
                id: 'zoom-in',
                label: 'Zoom In',
                shortcut: '⌘+',
                onClick: () => console.log('Zoom In clicked'),
              },
              {
                id: 'zoom-out',
                label: 'Zoom Out',
                shortcut: '⌘-',
                onClick: () => console.log('Zoom Out clicked'),
              },
            ],
          },
          {
            id: 'profile',
            label: 'Profile',
            items: [
              {
                id: 'account',
                label: 'Account',
                onClick: () => console.log('Account clicked'),
              },
              {
                id: 'settings',
                label: 'Settings',
                onClick: () => console.log('Settings clicked'),
              },
              {
                id: 'separator-3',
                isSeparator: true,
              },
              {
                id: 'logout',
                label: 'Log Out',
                onClick: () => console.log('Log Out clicked'),
              },
            ],
          },
        ]}
      />
      
      {/* 비활성화된 항목 */}
      <div style={{ marginTop: '60px' }}>
        <MenuBar
          items={[
            {
              id: 'file',
              label: 'File',
              items: [
                {
                  id: 'new-tab',
                  label: 'New Tab',
                  onClick: () => console.log('New Tab clicked'),
                },
                {
                  id: 'incognito-window',
                  label: 'Incognito Window',
                  disabled: true,
                },
              ],
            },
            {
              id: 'edit',
              label: 'Edit',
              disabled: true,
              items: [],
            },
          ]}
        />
      </div>
    </div>
  );
}

Props

MenuBar
속성타입기본값설명
itemsMenuBarItemProps[]필수메뉴바 아이템 배열
classNamestring''메뉴바에 적용할 추가 CSS 클래스
styleReact.CSSProperties-메뉴바에 적용할 스타일
widthstring'max-content'메뉴바의 너비. '100%', '300px' 등 CSS 너비 값 사용 가능
MenuBarItemProps
속성타입기본값설명
idstring필수메뉴 아이템 ID
labelstring필수메뉴 아이템 레이블
disabledbooleanfalse메뉴 아이템 비활성화 여부
itemsMenuItemProps[]-서브메뉴 항목
classNamestring''메뉴 아이템에 적용할 추가 CSS 클래스
MenuItemProps
속성타입기본값설명
idstring필수메뉴 항목의 고유 ID
labelstring필수메뉴 항목에 표시될 레이블
iconReactNode-항목의 아이콘
shortcutstring-단축키 표시
onClick() => void-항목 클릭 시 실행할 작업
hasSubmenubooleanfalse하위 메뉴가 있는지 여부
subItemsMenuItemProps[]-하위 메뉴 항목들. 메뉴 항목에 마우스를 올리면 표시됨
disabledbooleanfalse비활성화 여부
classNamestring''항목에 적용할 추가 CSS 클래스

16. NavigationMenu

NavigationMenu 컴포넌트는 웹사이트의 주요 네비게이션 영역을 구성하는 데 사용됩니다. 드롭다운 메뉴와 링크 목록을 포함할 수 있으며, 사용자가 웹사이트의 다양한 섹션으로 쉽게 이동할 수 있도록 도와줍니다.

사용법

import { NavigationMenu } from 'react-common-components-library';

function App() {
  return (
    <NavigationMenu
      items={[
        {
          label: 'Getting started',
          content: {
            title: 'Introduction',
            description: 'Re-usable components built using Radix UI and Tailwind CSS',
            links: [
              {
                title: 'Introduction',
                description: 'Re-usable components built using Radix UI and Tailwind CSS',
                href: '/docs/introduction',
              },
              {
                title: 'Installation',
                description: 'How to install dependencies and structure your app.',
                href: '/docs/installation',
              },
            ],
          },
          active: true,
        },
        {
          label: 'Components',
          content: {
            links: [
              {
                title: 'Accordion',
                description: 'A vertically stacked set of interactive headings.',
                href: '/docs/components/accordion',
              },
              {
                title: 'Button',
                description: 'Displays a button or a component that looks like a button.',
                href: '/docs/components/button',
              },
            ],
          },
        },
        {
          label: 'Blog',
          href: '/blog',
        },
      ]}
    />
  );
}

Props

NavigationMenu
속성타입기본값설명
itemsNavigationItemProps[]필수네비게이션 메뉴 항목 목록
classNamestring''네비게이션 메뉴에 적용할 추가 CSS 클래스
styleReact.CSSProperties-네비게이션 메뉴에 적용할 스타일
widthstring'100%'네비게이션 메뉴의 너비
NavigationItemProps
속성타입기본값설명
labelstring필수네비게이션 항목 제목
contentNavigationContent-네비게이션 항목 콘텐츠 (드롭다운 메뉴)
hrefstring-네비게이션 항목 링크 URL (content가 없을 경우 사용)
activebooleanfalse현재 활성화된 항목인지 여부
classNamestring''네비게이션 항목에 적용할 추가 CSS 클래스
NavigationContent
속성타입기본값설명
titlestring-콘텐츠 제목
descriptionstring-콘텐츠 설명
linksNavigationLink[]-콘텐츠 내 링크 목록
customContentReact.ReactNode-커스텀 콘텐츠

17. Popover

Popover 컴포넌트는 특정 요소를 클릭했을 때 팝업 형태로 정보나 작업을 제공하는 컴포넌트입니다. 사용자에게 추가 정보를 표시하거나 설정을 변경할 수 있는 인터페이스를 제공합니다.

사용법

import { Popover, PopoverField } from 'react-common-components-library';
import { Button } from 'react-common-components-library';

function App() {
  // 기본 사용법
  return (
    <Popover
      trigger={<Button>클릭하세요</Button>}
      title="팝오버 제목"
      description="팝오버에 대한 설명입니다."
    >
      <div>팝오버 내용을 여기에 넣을 수 있습니다.</div>
    </Popover>
  );
}

// 치수 설정 예제
function DimensionsExample() {
  const [width, setWidth] = useState('100%');
  const [maxWidth, setMaxWidth] = useState('300px');
  const [height, setHeight] = useState('25px');
  const [maxHeight, setMaxHeight] = useState('none');
  
  return (
    <Popover
      trigger={<Button>치수 설정</Button>}
      title="치수 설정"
      description="Set the dimensions for the layer."
      width={260}
    >
      <PopoverField
        label="Width"
        value={width}
        onChange={setWidth}
      />
      <PopoverField
        label="Max. width"
        value={maxWidth}
        onChange={setMaxWidth}
      />
      <PopoverField
        label="Height"
        value={height}
        onChange={setHeight}
      />
      <PopoverField
        label="Max. height"
        value={maxHeight}
        onChange={setMaxHeight}
      />
    </Popover>
  );
}

Props

Popover
속성타입기본값설명
triggerReactNode필수Popover를 열기 위한 트리거 요소
titleReactNode-Popover의 제목
descriptionReactNode-Popover의 설명
childrenReactNode필수Popover의 내용
defaultOpenbooleanfalsePopover가 기본적으로 열려있는지 여부
openboolean-외부에서 제어하는 열림 상태
onOpenChange(open: boolean) => void-열림 상태가 변경될 때 호출되는 함수
closeOnOutsideClickbooleantrue클릭 외부에서 Popover를 닫을지 여부
closeOnEscapebooleantrueESC 키를 눌렀을 때 Popover를 닫을지 여부
widthstring | number-Popover 컨텐츠의 너비
position'top' | 'right' | 'bottom' | 'left''bottom'Popover가 열리는 위치
triggerClassNamestring-Popover 트리거에 적용할 클래스
contentClassNamestring-Popover 컨텐츠에 적용할 클래스
titleClassNamestring-Popover 제목에 적용할 클래스
descriptionClassNamestring-Popover 설명에 적용할 클래스
triggerStyleCSSProperties-Popover 트리거에 적용할 스타일
contentStyleCSSProperties-Popover 컨텐츠에 적용할 스타일
PopoverField
속성타입기본값설명
labelstring필수필드 레이블
typestring'text'입력 타입
valuestring필수입력 값
onChange(value: string) => void필수값이 변경될 때 호출되는 함수
placeholderstring-플레이스홀더
classNamestring-필드 클래스

18. Progress

Progress 컴포넌트는 작업의 완료 상태나 프로세스의 진행 상황을 시각적으로 표시하는 데 사용됩니다. 사용자에게 작업이 얼마나 진행되었는지 직관적으로 보여줍니다.

사용법

import { Progress } from 'react-common-components-library';

function App() {
  // 기본 사용법
  return (
    <Progress value={60} />
  );
  
  // 레이블과 값 표시
  return (
    <Progress 
      value={60} 
      label="다운로드 진행률" 
      showValue 
    />
  );
  
  // 다양한 크기와 색상
  return (
    <>
      <Progress value={60} size="sm" color="primary" />
      <Progress value={60} size="md" color="success" />
      <Progress value={60} size="lg" color="danger" />
    </>
  );
  
  // 애니메이션 효과
  return (
    <Progress value={60} animated />
  );
}

Props

속성타입기본값설명
valuenumber필수진행률 (0-100)
maxnumber100최대값
labelstring-진행 바 위에 표시될 레이블
showValuebooleanfalse진행률 텍스트 표시 여부
valueFormatstring'{value}%'진행률 텍스트 형식
animatedbooleanfalse애니메이션 효과 적용 여부
size'sm' | 'md' | 'lg''md'진행 바 크기
color'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info''primary'진행 바 색상
classNamestring-컴포넌트에 적용할 추가 CSS 클래스
styleCSSProperties-컴포넌트에 적용할 인라인 스타일
containerClassNamestring-진행 바 배경에 적용할 추가 CSS 클래스
indicatorClassNamestring-진행 바 인디케이터에 적용할 추가 CSS 클래스
valueClassNamestring-진행률 표시 텍스트에 적용할 추가 CSS 클래스
labelClassNamestring-레이블에 적용할 추가 CSS 클래스

19. RadioGroup

RadioGroup 컴포넌트는 사용자가 여러 옵션 중 하나를 선택할 수 있는 라디오 버튼 그룹을 제공합니다. 각 옵션은 상호 배타적이며, 한 번에 하나의 옵션만 선택할 수 있습니다.

사용법

import { RadioGroup } from 'react-common-components-library';

function App() {
  // 기본 사용법
  const [value, setValue] = React.useState('default');
  
  return (
    <RadioGroup value={value} onChange={setValue}>
      <RadioGroup.Item value="default">Default</RadioGroup.Item>
      <RadioGroup.Item value="comfortable">Comfortable</RadioGroup.Item>
      <RadioGroup.Item value="compact">Compact</RadioGroup.Item>
    </RadioGroup>
  );
  
  // 가로 방향 라디오 그룹
  return (
    <RadioGroup value={value} onChange={setValue} orientation="horizontal">
      <RadioGroup.Item value="option1">Option 1</RadioGroup.Item>
      <RadioGroup.Item value="option2">Option 2</RadioGroup.Item>
      <RadioGroup.Item value="option3">Option 3</RadioGroup.Item>
    </RadioGroup>
  );
  
  // 다양한 크기
  return (
    <>
      <RadioGroup value="small" size="sm">
        <RadioGroup.Item value="small">Small</RadioGroup.Item>
      </RadioGroup>
      
      <RadioGroup value="medium" size="md">
        <RadioGroup.Item value="medium">Medium (Default)</RadioGroup.Item>
      </RadioGroup>
      
      <RadioGroup value="large" size="lg">
        <RadioGroup.Item value="large">Large</RadioGroup.Item>
      </RadioGroup>
    </>
  );
  
  // 비활성화
  return (
    <RadioGroup value="option1" disabled>
      <RadioGroup.Item value="option1">Option 1</RadioGroup.Item>
      <RadioGroup.Item value="option2">Option 2</RadioGroup.Item>
    </RadioGroup>
  );
}

Props

RadioGroup
속성타입기본값설명
valuestring-선택된 라디오 버튼의 값
defaultValuestring-기본 선택값
onChange(value: string) => void-값이 변경될 때 호출되는 함수
namestring자동 생성라디오 그룹의 이름
childrenReactNode필수라디오 버튼들
disabledbooleanfalse모든 라디오 버튼 비활성화 여부
size'sm' | 'md' | 'lg''md'라디오 버튼 크기
orientation'horizontal' | 'vertical''vertical'라디오 버튼 방향
classNamestring-라디오 그룹에 적용할 CSS 클래스
styleCSSProperties-라디오 그룹에 적용할 스타일
RadioGroup.Item
속성타입기본값설명
valuestring필수라디오 아이템의 값
childrenReactNode필수라디오 아이템 레이블
disabledbooleanfalse비활성화 여부
classNamestring-라디오 아이템에 적용할 CSS 클래스
labelClassNamestring-라벨에 적용할 CSS 클래스

20. ScrollArea

ScrollArea 컴포넌트는 제한된 공간 내에서 콘텐츠를 스크롤할 수 있게 해주며, 사용자 정의 스크롤바를 제공합니다. 기본 브라우저 스크롤바를 대체하여 더 일관되고 시각적으로 매력적인 UI를 구현할 수 있습니다.

사용법

import { ScrollArea } from 'react-common-components-library';

function App() {
  // 기본 사용법 (세로 스크롤)
  return (
    <ScrollArea 
      height={300} 
      width="100%"
    >
      {/* 스크롤될 내용 */}
      <div>
        {Array.from({ length: 50 }).map((_, i) => (
          <p key={i}>항목 {i + 1}</p>
        ))}
      </div>
    </ScrollArea>
  );
  
  // 가로 스크롤
  return (
    <ScrollArea 
      height={300} 
      width="100%" 
      orientation="horizontal"
    >
      <div style={{ display: 'flex', gap: '20px', whiteSpace: 'nowrap' }}>
        {Array.from({ length: 20 }).map((_, i) => (
          <div 
            key={i} 
            style={{ 
              minWidth: '150px', 
              height: '150px',
              background: `hsl(${i * 20}, 70%, 70%)`,
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center'
            }}
          >
            항목 {i + 1}
          </div>
        ))}
      </div>
    </ScrollArea>
  );
  
  // 양방향 스크롤
  return (
    <ScrollArea 
      height={300} 
      width="100%" 
      orientation="both"
    >
      <div style={{ width: '1000px', height: '1000px' }}>
        {/* 넓은 콘텐츠 */}
      </div>
    </ScrollArea>
  );
  
  // 스크롤바 항상 표시
  return (
    <ScrollArea 
      height={300} 
      width="100%" 
      autoHide={false}
    >
      {/* 스크롤될 내용 */}
    </ScrollArea>
  );
}

Props

속성타입기본값설명
childrenReactNode필수스크롤 영역 내부에 들어갈 컨텐츠
orientation'vertical' | 'horizontal' | 'both''vertical'스크롤 방향
autoHidebooleantrue스크롤바 자동 숨김 여부
widthstring | number-스크롤 영역 너비
heightstring | number-스크롤 영역 높이
maxWidthstring | number-스크롤 영역 최대 너비
maxHeightstring | number-스크롤 영역 최대 높이
classNamestring-루트 요소에 적용할 CSS 클래스
viewportClassNamestring-뷰포트(스크롤 영역)에 적용할 CSS 클래스
styleCSSProperties-루트 요소에 적용할 인라인 스타일
viewportStyleCSSProperties-뷰포트에 적용할 인라인 스타일
scrollbarClassNamestring-스크롤바에 적용할 CSS 클래스
trackClassNamestring-스크롤바 트랙에 적용할 CSS 클래스
thumbClassNamestring-스크롤바 썸(핸들)에 적용할 CSS 클래스

21. Select

사용자가 미리 정의된 옵션 목록에서 선택할 수 있는 드롭다운 선택 인터페이스를 제공하는 컴포넌트입니다.

사용법

import { Select } from 'react-common-components-library';

function App() {
  // 기본 사용법
  return (
    <div style={{ width: '300px' }}>
      {/* 기본 사용법 */}
      <Select
        placeholder="옵션 선택"
        options={[
          { value: 'option1', label: '옵션 1' },
          { value: 'option2', label: '옵션 2' },
          { value: 'option3', label: '옵션 3' },
        ]}
        onChange={(value) => console.log('선택된 값:', value)}
      />
      
      {/* 그룹화된 옵션 예시 */}
      <Select
        placeholder="카테고리 선택"
        options={[
          {
            label: '과일',
            options: [
              { value: 'apple', label: '사과' },
              { value: 'banana', label: '바나나' },
              { value: 'orange', label: '오렌지' },
            ],
          },
          {
            label: '채소',
            options: [
              { value: 'carrot', label: '당근' },
              { value: 'broccoli', label: '브로콜리', disabled: true },
              { value: 'cucumber', label: '오이' },
            ],
          },
        ]}
        onChange={(value) => console.log('선택된 값:', value)}
      />
      
      {/* 다크 테마 예시 */}
      <Select
        placeholder="다크 테마"
        theme="dark"
        options={[
          { value: 'option1', label: '옵션 1' },
          { value: 'option2', label: '옵션 2' },
          { value: 'option3', label: '옵션 3' },
        ]}
      />
    </div>
  );
}

Props

속성타입기본값설명
placeholderstring'옵션 선택'기본적으로 표시할 플레이스홀더 텍스트
valuestring-현재 선택된 값 (제어 컴포넌트로 사용 시)
defaultValuestring-기본 선택 값 (비제어 컴포넌트로 사용 시)
options(SelectOption | SelectGroup)[][]선택 가능한 옵션 목록 또는 그룹화된 옵션 목록
disabledbooleanfalse컴포넌트 비활성화 여부
size'sm' | 'md' | 'lg''md'컴포넌트의 크기
theme'light' | 'dark' | 'auto''light'테마 모드
onChange(value: string) => void-선택 시 호출될 콜백 함수
onOpenChange(open: boolean) => void-드롭다운 열림/닫힘 시 호출될 콜백 함수
classNamestring-컴포넌트에 적용할 추가 CSS 클래스
styleReact.CSSProperties-컴포넌트에 적용할 인라인 스타일
requiredbooleanfalse선택 필수 여부
idstring-컴포넌트 ID
namestring-컴포넌트 이름 (폼 제출용)
maxDropdownHeightnumber-최대 드롭다운 높이 (px)

타입

interface SelectOption {
  value: string;
  label: string;
  disabled?: boolean;
}

interface SelectGroup {
  label: string;
  options: SelectOption[];
}

22. Separator

콘텐츠 영역을 시각적으로 구분하는 수평 또는 수직 구분선을 제공하는 컴포넌트입니다.

사용법

import { Separator } from 'react-common-components-library';

function App() {
  return (
    <div>
      {/* 기본 수평 구분선 */}
      <div>상단 콘텐츠</div>
      <Separator />
      <div>하단 콘텐츠</div>
      
      {/* 수직 구분선 */}
      <div style={{ display: 'flex', alignItems: 'center', height: '100px' }}>
        <div>왼쪽 콘텐츠</div>
        <Separator orientation="vertical" style={{ height: '80%', margin: '0 16px' }} />
        <div>오른쪽 콘텐츠</div>
      </div>
      
      {/* 데코레이티브 구분선 */}
      <div>
        <h1>제목</h1>
        <p>부제목</p>
        <Separator decorative />
        <div>본문 내용</div>
      </div>
      
      {/* 다양한 스타일 옵션 */}
      <div style={{ display: 'flex', flexDirection: 'column', gap: '24px' }}>
        <Separator variant="primary" />
        <Separator dashed />
        <Separator withSpacing spacing={24} />
        <Separator theme="dark" />
      </div>
    </div>
  );
}

Props

속성타입기본값설명
orientation'horizontal' | 'vertical''horizontal'구분선 방향
decorativebooleanfalse데코레이티브 여부 (더 두껍게 표시)
variant'default' | 'primary' | 'secondary' | 'success' | 'danger' | 'warning''default'구분선 색상 변형
dashedbooleanfalse점선 스타일 사용 여부
theme'light' | 'dark' | 'auto''light'테마 모드
withSpacingbooleanfalse구분선 위아래(또는 좌우) 간격 추가 여부
spacingnumber16간격 크기 (px)
classNamestring-컴포넌트에 적용할 추가 CSS 클래스
styleReact.CSSProperties-컴포넌트에 적용할 인라인 스타일

23. Slider

사용자가 특정 범위 내에서 값을 선택할 수 있게 해주는 수평 또는 수직 슬라이더 컴포넌트입니다.

사용법

import { Slider } from 'react-common-components-library';

function App() {
  return (
    <div>
      {/* 기본 슬라이더 */}
      <Slider defaultValue={30} />
      
      {/* 수직 슬라이더 */}
      <div style={{ height: '200px' }}>
        <Slider orientation="vertical" defaultValue={50} />
      </div>
      
      {/* 값 레이블 표시 */}
      <Slider defaultValue={40} showValueLabel />
      
      {/* 제어 컴포넌트로 사용 */}
      const [value, setValue] = useState(50);
      
      <Slider 
        value={value} 
        onChange={setValue} 
        onChangeComplete={(val) => console.log('완료:', val)} 
      />
      
      {/* 커스텀 범위 및 단계 */}
      <Slider 
        min={-50} 
        max={50} 
        step={10} 
        defaultValue={0} 
        showValueLabel 
      />
      
      {/* 다양한 스타일 옵션 */}
      <Slider variant="primary" size="lg" thumbSize="lg" />
      <Slider variant="success" theme="dark" />
      <Slider variant="danger" disabled />
    </div>
  );
}

Props

속성타입기본값설명
valuenumber-현재 슬라이더 값 (제어 컴포넌트로 사용 시)
defaultValuenumber0기본 슬라이더 값 (비제어 컴포넌트로 사용 시)
minnumber0최솟값
maxnumber100최댓값
stepnumber1단계
disabledbooleanfalse비활성화 여부
orientation'horizontal' | 'vertical''horizontal'슬라이더의 방향
size'sm' | 'md' | 'lg''md'슬라이더의 크기
showValueLabelbooleanfalse값 레이블 표시 여부
formatLabel(value: number) => string(value) => \${value}``값 레이블 포맷 함수
theme'light' | 'dark' | 'auto''light'테마 모드
variant'default' | 'primary' | 'secondary' | 'success' | 'danger' | 'warning''primary'슬라이더의 색상 변형
classNamestring''추가 CSS 클래스
trackClickablebooleantrue슬라이더 트랙 클릭 가능 여부
thumbSize'sm' | 'md' | 'lg''md'슬라이더 썸(핸들) 크기
onChange(value: number) => void-값 변경 시 호출될 함수
onChangeComplete(value: number) => void-슬라이더 조작이 완료되었을 때 호출될 함수

24. Switch

사용자가 설정을 켜거나 끄는 상태를 토글할 수 있게 하는 컴포넌트입니다.

사용법

import { Switch } from 'react-common-components-library';

function App() {
  const [airplaneMode, setAirplaneMode] = React.useState(false);
  
  return (
    <div>
      {/* 기본 사용법 */}
      <Switch>비행기 모드</Switch>
      
      {/* 제어 컴포넌트로 사용 */}
      <Switch
        checked={airplaneMode}
        onChange={(e) => setAirplaneMode(e.target.checked)}
      >
        비행기 모드 {airplaneMode ? '켜짐' : '꺼짐'}
      </Switch>
      
      {/* 비활성화 상태 */}
      <Switch disabled>비활성화된 스위치</Switch>
      
      {/* 크기 변형 */}
      <Switch size="sm">작은 크기</Switch>
      <Switch size="md">중간 크기</Switch>
      <Switch size="lg">큰 크기</Switch>
    </div>
  );
}

Props

속성타입기본값설명
childrenReactNode-스위치 레이블
size'sm' | 'md' | 'lg''md'스위치 크기
errorbooleanfalse에러 상태 표시
checkedboolean-스위치 체크 상태 (제어 컴포넌트로 사용할 때)
defaultCheckedboolean-스위치 기본 체크 상태 (비제어 컴포넌트로 사용할 때)
disabledbooleanfalse스위치 비활성화 여부
onChange(event: ChangeEvent<HTMLInputElement>) => void-스위치 상태 변경 시 호출될 콜백 함수
classNamestring-루트 요소에 적용할 CSS 클래스
wrapperClassNamestring-스위치 컨테이너에 적용할 CSS 클래스

25. Tabs

여러 컨텐츠 영역을 동일한 공간에서 전환하여 표시할 수 있는 탭 인터페이스 컴포넌트입니다.

사용법

import { Tabs, TabsList, TabsTrigger, TabsContent } from 'react-common-components-library';
// 또는 중첩 구조로 사용
import { Tabs } from 'react-common-components-library';

function App() {
  return (
    <Tabs defaultValue="account">
      <Tabs.List>
        <Tabs.Trigger value="account">Account</Tabs.Trigger>
        <Tabs.Trigger value="password">Password</Tabs.Trigger>
      </Tabs.List>
      <Tabs.Content value="account">
        <div style={{ padding: '16px 0' }}>
          <p>Make changes to your account here. Click save when you're done.</p>
          
          <div style={{ marginBottom: '16px' }}>
            <label htmlFor="name">Name</label>
            <input
              id="name"
              defaultValue="Pietro Schirano"
              style={{ width: '100%' }}
            />
          </div>
          
          <div style={{ marginBottom: '24px' }}>
            <label htmlFor="username">Username</label>
            <input
              id="username"
              defaultValue="@skirano"
              style={{ width: '100%' }}
            />
          </div>
          
          <button>Save changes</button>
        </div>
      </Tabs.Content>
      <Tabs.Content value="password">
        <p>Password settings content</p>
      </Tabs.Content>
    </Tabs>
  );
}

Props

Tabs
속성타입기본값설명
defaultValuestring-초기에 활성화된 탭의 ID
valuestring-현재 선택된 탭의 ID (제어 컴포넌트로 사용할 때)
onValueChange(value: string) => void-탭 변경 시 호출되는 콜백 함수
classNamestring-루트 요소에 적용할 CSS 클래스
TabsList / Tabs.List
속성타입기본값설명
classNamestring-탭 리스트에 적용할 CSS 클래스
TabsTrigger / Tabs.Trigger
속성타입기본값설명
valuestring-탭의 고유 식별자
classNamestring-탭 버튼에 적용할 CSS 클래스
disabledbooleanfalse탭 버튼의 비활성화 여부
TabsContent / Tabs.Content
속성타입기본값설명
valuestring-연결된 탭의 고유 식별자
classNamestring-탭 컨텐츠에 적용할 CSS 클래스
forceMountbooleanfalse탭이 비활성화되었을 때 DOM에서 제거할지 여부

26. Textarea

사용자가 여러 줄의 텍스트를 입력할 수 있는 텍스트 영역 컴포넌트입니다.

사용법

import { Textarea } from 'react-common-components-library';

function App() {
  return (
    <div>
      {/* 기본 사용법 */}
      <Textarea 
        placeholder="텍스트를 입력하세요..." 
        rows={3}
      />
      
      {/* 레이블 및 설명 추가 */}
      <Textarea
        label="자기 소개"
        description="간단한 자기 소개를 작성해 주세요."
        placeholder="자기 소개를 입력하세요..."
      />
      
      {/* 에러 상태 */}
      <Textarea
        label="바이오"
        error={true}
        errorMessage="바이오는 필수 입력 항목입니다."
        placeholder="자기 소개를 입력하세요..."
      />
      
      {/* 자동 크기 조절 */}
      <Textarea
        label="자동 크기 조절"
        autoResize
        placeholder="텍스트를 입력하면 높이가 자동으로 조절됩니다..."
        maxHeight={200}
      />
      
      {/* 크기 변형 */}
      <Textarea size="sm" placeholder="작은 크기..." />
      <Textarea size="md" placeholder="중간 크기..." />
      <Textarea size="lg" placeholder="큰 크기..." />
      
      {/* 제어 컴포넌트로 사용 */}
      const [value, setValue] = useState('');
      
      <Textarea
        label="코멘트"
        value={value}
        onChange={(e) => setValue(e.target.value)}
        placeholder="코멘트를 입력하세요..."
      />
    </div>
  );
}

Props

속성타입기본값설명
size'sm' | 'md' | 'lg''md'텍스트 영역 크기
errorbooleanfalse에러 상태 표시
errorMessagestring-에러 메시지
labelstring-레이블
descriptionstring-설명 텍스트
classNamestring-텍스트 영역에 적용할 CSS 클래스
containerClassNamestring-컨테이너에 적용할 CSS 클래스
maxHeightnumber-최대 높이 (px)
autoResizebooleanfalse자동 크기 조절 여부
rowsnumber3표시할 줄 수
valuestring-텍스트 영역 값 (제어 컴포넌트로 사용 시)
defaultValuestring-초기 값 (비제어 컴포넌트로 사용 시)
placeholderstring-플레이스홀더 텍스트
disabledbooleanfalse비활성화 여부
onChange(e: ChangeEvent<HTMLTextAreaElement>) => void-값 변경 시 호출될 함수

27. Tooltip

요소에 마우스를 올리거나 클릭했을 때 추가 정보를 표시하는 작은 팝업 컴포넌트입니다.

사용법

import { Tooltip, Button } from 'react-common-components-library';

function App() {
  return (
    <div>
      {/* 기본 사용법 */}
      <Tooltip content="툴팁 내용입니다">
        <Button>마우스를 올려보세요</Button>
      </Tooltip>
      
      {/* 다양한 위치 */}
      <Tooltip content="상단에 표시" placement="top">
        <Button>상단</Button>
      </Tooltip>
      
      <Tooltip content="우측에 표시" placement="right">
        <Button>우측</Button>
      </Tooltip>
      
      <Tooltip content="하단에 표시" placement="bottom">
        <Button>하단</Button>
      </Tooltip>
      
      <Tooltip content="좌측에 표시" placement="left">
        <Button>좌측</Button>
      </Tooltip>
      
      {/* 크기 옵션 */}
      <Tooltip content="작은 툴팁" size="sm">
        <Button>작은 크기</Button>
      </Tooltip>
      
      <Tooltip content="중간 크기 툴팁" size="md">
        <Button>중간 크기</Button>
      </Tooltip>
      
      <Tooltip content="큰 크기 툴팁" size="lg">
        <Button>큰 크기</Button>
      </Tooltip>
      
      {/* 화살표 옵션 */}
      <Tooltip content="화살표 없음" arrow={false}>
        <Button>화살표 없음</Button>
      </Tooltip>
      
      {/* 트리거 방식 */}
      <Tooltip content="클릭하면 표시" trigger="click">
        <Button>클릭하세요</Button>
      </Tooltip>
      
      {/* 긴 텍스트 */}
      <Tooltip content="이것은 매우 긴 텍스트 내용입니다. 툴팁은 길이가 긴 텍스트를 표시할 때 자동으로 여러 줄로 나뉘어 표시됩니다.">
        <Button>긴 텍스트</Button>
      </Tooltip>
      
      {/* 지연 시간 설정 */}
      <Tooltip
        content="마우스를 올리고 0.5초 후 표시됩니다"
        delayShow={500}
        delayHide={200}
      >
        <Button>지연 시간</Button>
      </Tooltip>
      
      {/* 제어 컴포넌트 */}
      const [visible, setVisible] = useState(false);
      
      <>
        <Button onClick={() => setVisible(!visible)}>
          {visible ? '툴팁 숨기기' : '툴팁 표시하기'}
        </Button>
        
        <Tooltip
          content="제어 모드 툴팁"
          visible={visible}
          onVisibleChange={setVisible}
        >
          <Button>Controlled 툴팁</Button>
        </Tooltip>
      </>
    </div>
  );
}

Props

속성타입기본값설명
contentReactNode필수툴팁에 표시할 내용
childrenReactElement필수툴팁을 표시할 대상 요소
placement'top' | 'right' | 'bottom' | 'left''top'툴팁 표시 위치
size'sm' | 'md' | 'lg''md'툴팁 크기
trigger'hover' | 'click' | 'focus''hover'툴팁 표시 트리거 방식
arrowbooleantrue화살표 표시 여부
delayShownumber0툴팁 표시 지연 시간 (ms)
delayHidenumber0툴팁 숨김 지연 시간 (ms)
defaultVisiblebooleanfalse초기 표시 여부 (비제어 모드)
visibleboolean-툴팁 표시 여부 (제어 모드)
onVisibleChange(visible: boolean) => void-툴팁 표시 상태 변경 시 호출되는 함수
classNamestring-툴팁에 적용할 CSS 클래스
contentClassNamestring-툴팁 내용에 적용할 CSS 클래스
zIndexnumber1000z-index 값
styleCSSProperties-툴팁에 적용할 인라인 스타일

TypeScript 지원

이 라이브러리는 TypeScript로 작성되었으며 모든 컴포넌트에 대한 타입 정의를 제공합니다.

import { Button, ButtonProps } from 'react-common-components-library';

const MyButton: React.FC<ButtonProps> = (props) => {
  return <Button {...props} />;
};

테마 시스템

이 라이브러리는 라이트/다크 테마를 지원하며, 시스템 설정을 따르거나 사용자가 직접 테마를 선택할 수 있습니다.

테마 설정하기

애플리케이션 최상위 레벨에서 ThemeProvider를 사용하여 테마 컨텍스트를 설정합니다:

import { ThemeProvider } from 'react-common-components-library';

function App() {
  return (
    <ThemeProvider defaultTheme="light">
      {/* 앱 컴포넌트 */}
    </ThemeProvider>
  );
}

테마 전환 버튼 사용하기

테마를 손쉽게 전환할 수 있는 ThemeToggle 컴포넌트를 제공합니다:

import { ThemeToggle } from 'react-common-components-library';

function Header() {
  return (
    <header>
      <div className="header-right">
        <ThemeToggle size="md" />
      </div>
    </header>
  );
}

프로그래밍 방식으로 테마 제어하기

useTheme 훅을 사용하여 어느 컴포넌트에서든 테마 상태에 접근하고 제어할 수 있습니다:

import { useTheme } from 'react-common-components-library';

function ThemeControls() {
  const { theme, setTheme, toggleTheme } = useTheme();
  
  return (
    <div>
      <p>현재 테마: {theme === 'light' ? '라이트' : '다크'}</p>
      <button onClick={() => setTheme('light')}>라이트 모드</button>
      <button onClick={() => setTheme('dark')}>다크 모드</button>
      <button onClick={toggleTheme}>테마 전환</button>
    </div>
  );
}

CSS 변수를 활용한 테마 스타일링

모든 컴포넌트는 테마에 따라 자동으로 스타일이 변경됩니다. 자체 컴포넌트를 만들 때도 이 CSS 변수를 활용할 수 있습니다:

.custom-component {
  color: var(--color-text-primary);
  background-color: var(--color-bg-primary);
  border: 1px solid var(--color-border-primary);
}

.custom-component:hover {
  background-color: var(--color-bg-secondary);
  border-color: var(--color-border-hover);
}

주요 CSS 변수

테마 시스템은 다음과 같은 CSS 변수 그룹을 제공합니다:

변수 그룹설명예시
색상 시스템주요 색상 변수--color-primary, --color-primary-light
텍스트 색상텍스트 관련 색상--color-text-primary, --color-text-secondary
배경 색상배경 관련 색상--color-bg-primary, --color-bg-secondary
테두리 색상테두리 관련 색상--color-border-primary, --color-border-hover
상태 색상상태 표시 색상--color-error, --color-success, --color-warning
그림자그림자 효과--shadow-sm, --shadow-md, --shadow-lg
간격여백, 패딩 등--spacing-xs, --spacing-sm, --spacing-md
테두리 반경모서리 둥글기--border-radius-sm, --border-radius-md

특정 영역에 테마 적용하기

특정 영역에만 다른 테마를 적용하려면 CSS 클래스를 직접 사용할 수 있습니다:

// 항상 다크 테마로 표시되는 영역
<div className="dark-theme">
  <Card>다크 테마 컨텐츠</Card>
</div>

// 항상 라이트 테마로 표시되는 영역
<div className="light-theme">
  <Card>라이트 테마 컨텐츠</Card>
</div>

라이센스

MIT 라이센스로 배포됩니다. 자세한 내용은 LICENSE 파일을 참조하세요.

트리쉐이킹(Tree Shaking) 사용법

이 라이브러리는 트리쉐이킹을 완벽히 지원하므로 사용하지 않는 컴포넌트는 최종 번들에 포함되지 않습니다. 다음과 같이 두 가지 방식으로 컴포넌트를 가져올 수 있습니다:

1. 기본 임포트 방식 (ESM)

import { Button, Input, Accordion } from 'react-common-components-library';

이 방식은 대부분의 번들러(Webpack, Rollup, Vite 등)에서 자동으로 트리쉐이킹이 작동합니다.

2. 개별 컴포넌트 임포트 방식 (최적화)

import Button from 'react-common-components-library/button';
import Input from 'react-common-components-library/input';
import Accordion from 'react-common-components-library/accordion';

이 방식은 트리쉐이킹이 더 명시적으로 이루어져 일부 번들러에서 더 효과적으로 작동할 수 있습니다.

트리쉐이킹 요구사항

트리쉐이킹이 제대로 작동하기 위해서는 다음 조건이 필요합니다:

  • Webpack, Rollup, Vite 등의 모듈 번들러를 사용할 것
  • ESM 방식으로 임포트할 것
  • 번들러의 최적화 옵션이 활성화되어 있을 것

번들 크기 비교

임포트 방식Button만 사용Button, Input 사용전체 라이브러리
기본 방식~10KB~18KB~120KB
개별 임포트~8KB~16KB~120KB

테마 컴포넌트 사용법

이 라이브러리는 다크 모드와 라이트 모드를 지원하는 테마 시스템을 제공합니다. 테마 기능을 사용하려면 애플리케이션의 루트에 ThemeProvider를 설정하고, 필요한 경우 ThemeToggle 컴포넌트를 사용하여 테마를 전환할 수 있습니다.

ThemeProvider 설정

import { ThemeProvider } from 'react-common-components-library/theme-provider';

function App() {
  return (
    <ThemeProvider defaultTheme="light">
      {/* 애플리케이션 컴포넌트들 */}
    </ThemeProvider>
  );
}

테마 전환 버튼 사용

import { ThemeToggle } from 'react-common-components-library/theme-toggle';

function Header() {
  return (
    <header>
      <h1>내 애플리케이션</h1>
      <ThemeToggle />
    </header>
  );
}

현재 테마 사용하기

import { useTheme } from 'react-common-components-library/theme-provider';

function MyComponent() {
  const { theme, setTheme } = useTheme();
  
  return (
    <div>
      <p>현재 테마: {theme}</p>
      <button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
        테마 전환
      </button>
    </div>
  );
}

Keywords

react

FAQs

Package last updated on 25 Mar 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts