Skip to Content

Container

페이지 콘텐츠를 중앙 정렬하고 최대 너비를 제한하는 레이아웃 컨테이너입니다.

개요

Container는 페이지 콘텐츠를 읽기 쉬운 너비로 제한하고 중앙 정렬하는 컴포넌트입니다. Cals 예약 관리 시스템의 모든 페이지 레이아웃에서 사용됩니다.

주요 특징:

  • 반응형 최대 너비 설정 (sm, md, lg, xl, 2xl)
  • 자동 중앙 정렬
  • 좌우 여백 자동 관리
  • 중첩 가능한 구조

설치

npx @vortex/cli add container

기본 사용법

import { Container } from "@vortex/ui"; export default function DashboardPage() { return ( <Container> <h1>예약 대시보드</h1> <p>오늘의 예약을 확인하세요.</p> </Container> ); }

Variants

최대 너비 설정

{ /* Small - 640px */ } <Container size="sm"> <p>작은 컨테이너 (640px)</p> </Container>; { /* Medium - 768px (기본값) */ } <Container size="md"> <p>중간 컨테이너 (768px)</p> </Container>; { /* Large - 1024px */ } <Container size="lg"> <p>큰 컨테이너 (1024px)</p> </Container>; { /* Extra Large - 1280px */ } <Container size="xl"> <p>아주 큰 컨테이너 (1280px)</p> </Container>; { /* 2X Large - 1536px */ } <Container size="2xl"> <p>최대 컨테이너 (1536px)</p> </Container>; { /* Full Width - 제한 없음 */ } <Container size="full"> <p>전체 너비 컨테이너</p> </Container>;

패딩 조정

{ /* 패딩 없음 */ } <Container padding="none"> <p>패딩이 없는 컨테이너</p> </Container>; { /* 작은 패딩 */ } <Container padding="sm"> <p>작은 패딩 컨테이너</p> </Container>; { /* 중간 패딩 (기본값) */ } <Container padding="md"> <p>중간 패딩 컨테이너</p> </Container>; { /* 큰 패딩 */ } <Container padding="lg"> <p>큰 패딩 컨테이너</p> </Container>;

중첩된 Container

<Container size="xl"> <h1>메인 페이지</h1> <Container size="lg" className="mt-8"> <h2>섹션 타이틀</h2> <p>중첩된 컨테이너로 콘텐츠를 더 좁게 만들 수 있습니다.</p> </Container> </Container>

Cals 브랜딩

Primary Pink 헤더 섹션

<Container className="bg-gradient-to-r from-[#e91e63] to-[#9c27b0] text-white py-12"> <h1 className="text-4xl font-bold mb-4">예약 관리 시스템</h1> <p className="text-xl opacity-90">간편하고 효율적인 예약 관리</p> </Container>

Secondary Blue 정보 섹션

<Container className="bg-[#03a9f4]/10 py-8"> <div className="flex items-center gap-4"> <div className="w-12 h-12 rounded-full bg-[#03a9f4] flex items-center justify-center text-white"> ℹ️ </div> <div> <h3 className="text-lg font-semibold text-[#03a9f4]">안내사항</h3> <p className="text-sm text-muted-foreground"> 예약 변경은 24시간 전까지 가능합니다. </p> </div> </div> </Container>

예약 상태별 섹션

{ /* Available - 예약 가능 시간대 */ } <Container className="border-l-4 border-[#4caf50] bg-[#4caf50]/5 py-6"> <h3 className="text-[#4caf50] font-semibold mb-2">예약 가능 시간대</h3> <p>오늘 오후 2시부터 4시까지 예약 가능합니다.</p> </Container>; { /* Pending - 예약 대기 */ } <Container className="border-l-4 border-[#ff9800] bg-[#ff9800]/5 py-6"> <h3 className="text-[#ff9800] font-semibold mb-2">확인 대기 중</h3> <p>3건의 예약이 확인을 기다리고 있습니다.</p> </Container>; { /* Confirmed - 예약 확정 */ } <Container className="border-l-4 border-[#03a9f4] bg-[#03a9f4]/5 py-6"> <h3 className="text-[#03a9f4] font-semibold mb-2">오늘의 예약</h3> <p>총 12건의 예약이 확정되었습니다.</p> </Container>;

브랜드별 비교

특성FoundationiCignalCals
목적범용 레이아웃전자 담배 페이지예약 관리 페이지
디자인중립적다크 테마밝고 친근한
Primary-Blue #0066ccPink #e91e63
기본 너비1280px1280px1024px
주요 사용모든 페이지제품 페이지, 이벤트대시보드, 예약 목록
특화 기능-다크 모드상태별 섹션 구분

Props API

PropTypeDefaultDescription
size’sm’ | ‘md’ | ‘lg’ | ‘xl’ | ‘2xl’ | ‘full''md’최대 너비 설정
padding’none’ | ‘sm’ | ‘md’ | ‘lg''md’좌우 패딩 크기
classNamestring-추가 CSS 클래스
childrenReactNode-컨테이너 내용
asElementType’div’렌더링할 HTML 요소

접근성

  • 시맨틱 HTML: 적절한 시맨틱 태그 사용 (<main>, <section>, <article>)
  • 랜드마크 영역: as="main" 또는 role 속성으로 명확한 구조 제공
  • 색상 대비: 배경색 사용 시 WCAG AA 기준 충족
  • 반응형: 모든 화면 크기에서 읽기 쉬운 레이아웃
{/* 접근성 개선 예제 */} <Container as="main" role="main" aria-label="메인 콘텐츠"> <h1>예약 관리 대시보드</h1> <p>오늘의 예약 현황을 확인하세요.</p> </Container> <Container as="section" aria-labelledby="upcoming-title"> <h2 id="upcoming-title">다가오는 예약</h2> <ul> <li>오늘 오후 2시 - 홍길동</li> <li>오늘 오후 3시 - 김고객</li> </ul> </Container>

예제

1. 예약 대시보드 레이아웃

import { Container } from "@vortex/ui"; import { Calendar, Users, Clock } from "lucide-react"; export default function ReservationDashboard() { return ( <> {/* 헤더 섹션 */} <Container size="full" className="bg-gradient-to-r from-[#e91e63] to-[#9c27b0] text-white" > <Container size="xl" padding="lg" className="py-12"> <h1 className="text-4xl font-bold mb-2">예약 대시보드</h1> <p className="text-xl opacity-90">2024년 1월 15일</p> </Container> </Container> {/* 통계 섹션 */} <Container size="xl" padding="lg" className="py-8"> <div className="grid grid-cols-1 md:grid-cols-3 gap-6"> <div className="p-6 rounded-lg bg-[#03a9f4]/10 border border-[#03a9f4]"> <div className="flex items-center gap-4"> <Calendar className="w-8 h-8 text-[#03a9f4]" /> <div> <p className="text-2xl font-bold text-[#03a9f4]">12</p> <p className="text-sm text-muted-foreground">오늘 예약</p> </div> </div> </div> <div className="p-6 rounded-lg bg-[#ff9800]/10 border border-[#ff9800]"> <div className="flex items-center gap-4"> <Clock className="w-8 h-8 text-[#ff9800]" /> <div> <p className="text-2xl font-bold text-[#ff9800]">3</p> <p className="text-sm text-muted-foreground">대기 중</p> </div> </div> </div> <div className="p-6 rounded-lg bg-[#4caf50]/10 border border-[#4caf50]"> <div className="flex items-center gap-4"> <Users className="w-8 h-8 text-[#4caf50]" /> <div> <p className="text-2xl font-bold text-[#4caf50]">48</p> <p className="text-sm text-muted-foreground">이번 주</p> </div> </div> </div> </div> </Container> {/* 콘텐츠 섹션 */} <Container size="xl" padding="lg" className="py-8"> <h2 className="text-2xl font-bold mb-6">다가오는 예약</h2> {/* 예약 목록 */} </Container> </> ); }

2. 예약 상세 페이지 레이아웃

import { Container } from "@vortex/ui"; import { ArrowLeft } from "lucide-react"; export default function ReservationDetailPage() { return ( <> {/* 브레드크럼 */} <Container size="lg" padding="lg" className="py-4 border-b"> <button className="flex items-center gap-2 text-[#e91e63] hover:underline"> <ArrowLeft className="w-4 h-4" /> 예약 목록으로 돌아가기 </button> </Container> {/* 예약 정보 */} <Container size="lg" padding="lg" className="py-8"> <div className="border-l-4 border-[#03a9f4] bg-[#03a9f4]/5 p-6 rounded-r-lg"> <h1 className="text-3xl font-bold text-[#03a9f4] mb-2"> 예약 #RSV-20240115-001 </h1> <p className="text-lg text-muted-foreground">헤어 커트 + 스타일링</p> </div> {/* 고객 정보 */} <div className="mt-8 p-6 bg-white rounded-lg border"> <h2 className="text-xl font-semibold mb-4">고객 정보</h2> <dl className="space-y-2"> <div className="flex"> <dt className="w-24 text-muted-foreground">이름</dt> <dd className="font-medium">홍길동</dd> </div> <div className="flex"> <dt className="w-24 text-muted-foreground">연락처</dt> <dd className="font-medium">010-1234-5678</dd> </div> <div className="flex"> <dt className="w-24 text-muted-foreground">이메일</dt> <dd className="font-medium">hong@example.com</dd> </div> </dl> </div> {/* 예약 내역 */} <div className="mt-6 p-6 bg-white rounded-lg border"> <h2 className="text-xl font-semibold mb-4">예약 내역</h2> <dl className="space-y-2"> <div className="flex"> <dt className="w-24 text-muted-foreground">날짜</dt> <dd className="font-medium">2024년 1월 15일</dd> </div> <div className="flex"> <dt className="w-24 text-muted-foreground">시간</dt> <dd className="font-medium">오후 2:00 - 3:00</dd> </div> <div className="flex"> <dt className="w-24 text-muted-foreground">담당</dt> <dd className="font-medium">김디자이너</dd> </div> <div className="flex"> <dt className="w-24 text-muted-foreground">금액</dt> <dd className="font-medium text-[#e91e63]">50,000원</dd> </div> </dl> </div> </Container> {/* 액션 버튼 */} <Container size="lg" padding="lg" className="py-6 border-t bg-gray-50"> <div className="flex gap-4 justify-end"> <button className="px-6 py-2 rounded-md border border-gray-300 hover:bg-gray-100"> 예약 변경 </button> <button className="px-6 py-2 rounded-md bg-[#e91e63] text-white hover:bg-[#c2185b]"> 예약 확정 </button> </div> </Container> </> ); }

3. 예약 생성 폼 레이아웃

import { Container } from "@vortex/ui"; export default function CreateReservationPage() { return ( <> {/* 프로그레스 바 */} <Container size="full" className="bg-white border-b"> <Container size="lg" padding="lg" className="py-4"> <div className="flex items-center justify-between"> <div className="flex-1"> <div className="h-2 bg-gray-200 rounded-full"> <div className="h-2 bg-[#e91e63] rounded-full" style={{ width: "33%" }} /> </div> </div> </div> <div className="flex justify-between mt-2 text-sm"> <span className="text-[#e91e63] font-medium">1. 서비스 선택</span> <span className="text-muted-foreground">2. 날짜/시간</span> <span className="text-muted-foreground">3. 고객 정보</span> </div> </Container> </Container> {/* 폼 섹션 */} <Container size="md" padding="lg" className="py-12"> <h1 className="text-3xl font-bold mb-2">새 예약 만들기</h1> <p className="text-muted-foreground mb-8"> 원하시는 서비스를 선택해주세요. </p> {/* 서비스 선택 */} <div className="space-y-4"> <div className="p-6 border-2 border-[#e91e63] bg-[#e91e63]/5 rounded-lg cursor-pointer"> <h3 className="text-lg font-semibold text-[#e91e63]">헤어 커트</h3> <p className="text-sm text-muted-foreground mt-1"> 30,000원 · 60분 </p> </div> <div className="p-6 border-2 border-gray-200 rounded-lg cursor-pointer hover:border-gray-300"> <h3 className="text-lg font-semibold">헤어 펌</h3> <p className="text-sm text-muted-foreground mt-1"> 80,000원 · 120분 </p> </div> <div className="p-6 border-2 border-gray-200 rounded-lg cursor-pointer hover:border-gray-300"> <h3 className="text-lg font-semibold">헤어 염색</h3> <p className="text-sm text-muted-foreground mt-1"> 100,000원 · 180분 </p> </div> </div> </Container> {/* 하단 액션 */} <Container size="full" className="border-t bg-white fixed bottom-0"> <Container size="md" padding="lg" className="py-4"> <div className="flex gap-4 justify-end"> <button className="px-6 py-2 rounded-md border border-gray-300 hover:bg-gray-100"> 취소 </button> <button className="px-6 py-2 rounded-md bg-[#e91e63] text-white hover:bg-[#c2185b]"> 다음 단계 </button> </div> </Container> </Container> </> ); }

관련 컴포넌트

  • Card - 카드 컴포넌트
  • Grid - 그리드 레이아웃
  • Stack - 수직/수평 스택
Last updated on