ErrorPage

Layout

에러 유형에 맞는 그래픽과 문구를 담는 에러 페이지.

Usage

라우트 전체를 대체하는 오류 화면에 그래픽·설명·복구 행동을 배치할 때 사용한다.

import

import

import { ErrorPage } from '@mildang/design-system/ErrorPage';

예제를 복사해 쓸 때 필요한 준비

@mildang/icons 를 따로 설치한다. DS 패키지에 아이콘 컴포넌트가 포함되지 않는다.

@mildang/styled-system 은 이 저장소에서 Panda 가 생성하는 산출물이다. 저장소 안에서는 turbo run ship 이후 쓸 수 있고, 패키지 소비자는 자기 Panda 산출물이나 다른 레이아웃 수단으로 바꿔야 한다.

API Reference

ErrorPage Props

Prop

Type

Default

type
필수

"common" | "notFound" | "server" | "authority" | "authorityAccount"

지정 안 함

children

ReactNode

지정 안 함

className

string

지정 안 함

description

ReactNode

지정 안 함

graphicSize

number

280

graphicType

"box" | "paper" | "barricade" | "lock" | "rene" | "symbols" | "brokenPencil" | "fallingAirplane"

지정 안 함

mobileGraphicSize

number

210

onBack

() => void

window.history.back()

onRetry

() => void

window.location.reload()

title

ReactNode

지정 안 함

ErrorPageActions

Prop

Type

Default

children
필수

ReactNode

지정 안 함

className

string

지정 안 함

ResponsiveButton

Prop

Type

Default

asChild

boolean

지정 안 함

children

ReactNode

지정 안 함

className

string

지정 안 함

disabled

boolean

지정 안 함

endIcon

ReactNode

지정 안 함

fullWidth

boolean

false

iconColor

string

지정 안 함

loading

boolean

지정 안 함

startIcon

ReactNode

지정 안 함

variant

"primary" | "impact" | "secondary" | "tertiary" | "quaternary"

지정 안 함

예제

유형별 기본 문구·버튼

type 이 그래픽·기본 문구·기본 버튼을 함께 고른다 — 대표 유형 네 가지를 나란히 비교한다.

코드

'use client';

import { ErrorPage, type ErrorPageType } from '@mildang/design-system/ErrorPage';
import { css } from '@mildang/styled-system/css';
import { Grid } from '@mildang/styled-system/jsx';

/**
 * `type` 이 그래픽·기본 문구·기본 버튼을 함께 고른다. 문구를 override 하지 않은 네 가지
 * 기본 케이스를 나란히 비교한다(`common` 은 문구·버튼이 비어 있어 override 전용 — 다른 예제 참고).
 */
const cases: readonly ErrorPageType[] = ['notFound', 'server', 'authority', 'authorityAccount'];

const card = css({
  height: '[280px]',
  borderWidth: '1',
  borderStyle: 'solid',
  borderColor: 'neutral.border.low',
  borderRadius: '12',
  overflow: 'hidden',
});

export default function ErrorPageTypesExample() {
  return (
    <Grid gridTemplateColumns="{repeat(auto-fit, minmax(200px, 1fr))}" gap="4">
      {cases.map((type) => (
        <div key={type} className={card}>
          <ErrorPage type={type} graphicSize={88} mobileGraphicSize={88} />
        </div>
      ))}
    </Grid>
  );
}

문구 직접 채우기

정해진 케이스에 맞지 않으면 type="common"(빈 캔버스)에 문구·그래픽·버튼을 직접 채운다.

코드

'use client';

import { ErrorPage, ResponsiveButton } from '@mildang/design-system/ErrorPage';
import RefreshIcon from '@mildang/icons/react/refresh';
import { css } from '@mildang/styled-system/css';

/**
 * 정해진 케이스에 맞지 않는 화면은 `type="common"`(문구·버튼이 비어 있는 빈 캔버스)에
 * title·description·graphicType·children 을 전부 직접 채워 쓴다.
 */
const frame = css({ height: '[360px]' });

export default function ErrorPageCustomContentExample() {
  return (
    <div className={frame}>
      <ErrorPage
        type="common"
        graphicType="fallingAirplane"
        title="결제 처리 중 문제가 발생했습니다."
        description={'카드사 응답이 지연되고 있어요.\n잠시 후 다시 시도해주세요.'}
      >
        <ResponsiveButton variant="primary" startIcon={<RefreshIcon />} onClick={() => {}}>
          다시 시도하기
        </ResponsiveButton>
      </ErrorPage>
    </div>
  );
}

버튼 두 개 조립하기

기본 버튼 하나로 부족하면 children 을 ErrorPageActions 로 감싸 버튼을 두 개 이상 배치한다.

코드

'use client';

import { ErrorPage, ErrorPageActions, ResponsiveButton } from '@mildang/design-system/ErrorPage';
import ChevronLeftIcon from '@mildang/icons/react/chevron-left';
import HomeIcon from '@mildang/icons/react/home';
import { css } from '@mildang/styled-system/css';

/**
 * 기본 버튼 하나로 부족한 케이스는 `children` 을 `ErrorPageActions` 로 감싸 버튼을 두 개 이상
 * 조립한다. 각 버튼은 `ResponsiveButton` 이라 데스크톱 xl·모바일 lg 반응형이 그대로 유지된다.
 */
const frame = css({ height: '[360px]' });

export default function ErrorPageCompositionExample() {
  return (
    <div className={frame}>
      <ErrorPage type="authority" graphicType="fallingAirplane">
        <ErrorPageActions>
          <ResponsiveButton variant="secondary" startIcon={<ChevronLeftIcon />} onClick={() => {}}>
            이전 페이지로
          </ResponsiveButton>
          <ResponsiveButton variant="primary" startIcon={<HomeIcon />} onClick={() => {}}>
            홈으로
          </ResponsiveButton>
        </ErrorPageActions>
      </ErrorPage>
    </div>
  );
}

Common

import type { ComponentProps } from 'react';
import { ErrorPage } from '@mildang/design-system/ErrorPage';
import { ResponsiveButton } from '@mildang/design-system/ErrorPage';
import ChevronLeftIcon from '@mildang/icons/react/chevron-left';

const STORY_DEFAULT_ARGS = { ...({
    type: 'notFound',
  }), ...({
    type: 'common',
    title: '앗! 문제가 발생했습니다.',
    description: '추가 설명이 필요한 경우 Description을 적어주세요.',
  }) } as ComponentProps<typeof ErrorPage>;

const ErrorPageCommonExampleRender = (args: ComponentProps<typeof ErrorPage>) => (
    <ErrorPage {...args}>
      <ResponsiveButton variant="primary" startIcon={<ChevronLeftIcon />} onClick={() => alert('바로가기')}>
        바로가기
      </ResponsiveButton>
    </ErrorPage>
  );

export default function ErrorPageCommonExample(props: Partial<ComponentProps<typeof ErrorPage>>) {
  const mergedProps = { ...STORY_DEFAULT_ARGS, ...props } as ComponentProps<typeof ErrorPage>;
  return ErrorPageCommonExampleRender(mergedProps);
}

TwoButtons

import type { ComponentProps } from 'react';
import { ErrorPage } from '@mildang/design-system/ErrorPage';
import { ErrorPageActions } from '@mildang/design-system/ErrorPage';
import { ResponsiveButton } from '@mildang/design-system/ErrorPage';
import ChevronLeftIcon from '@mildang/icons/react/chevron-left';
import HomeIcon from '@mildang/icons/react/home';

const STORY_DEFAULT_ARGS = { ...({
    type: 'notFound',
  }), ...({ type: 'authority', graphicType: 'fallingAirplane' }) } as ComponentProps<typeof ErrorPage>;

const ErrorPageTwoButtonsExampleRender = (args: ComponentProps<typeof ErrorPage>) => (
    <ErrorPage {...args}>
      <ErrorPageActions>
        <ResponsiveButton
          variant="secondary"
          startIcon={<ChevronLeftIcon />}
          onClick={() => alert('이전 페이지로')}
        >
          이전 페이지로
        </ResponsiveButton>
        <ResponsiveButton variant="primary" startIcon={<HomeIcon />} onClick={() => alert('홈으로')}>
          홈으로
        </ResponsiveButton>
      </ErrorPageActions>
    </ErrorPage>
  );

export default function ErrorPageTwoButtonsExample(props: Partial<ComponentProps<typeof ErrorPage>>) {
  const mergedProps = { ...STORY_DEFAULT_ARGS, ...props } as ComponentProps<typeof ErrorPage>;
  return ErrorPageTwoButtonsExampleRender(mergedProps);
}

Custom

import type { ComponentProps } from 'react';
import { ErrorPage } from '@mildang/design-system/ErrorPage';
import { ResponsiveButton } from '@mildang/design-system/ErrorPage';
import ChevronLeftIcon from '@mildang/icons/react/chevron-left';

const STORY_DEFAULT_ARGS = { ...({
    type: 'notFound',
  }), ...({
    type: 'notFound',
    graphicType: 'symbols',
    title: '요청하신 페이지를 찾을 수 없어요',
    description: '링크가 만료되었거나 주소가 변경되었을 수 있습니다.',
  }) } as ComponentProps<typeof ErrorPage>;

const ErrorPageCustomExampleRender = (args: ComponentProps<typeof ErrorPage>) => (
    <ErrorPage {...args}>
      <ResponsiveButton
        variant="primary"
        startIcon={<ChevronLeftIcon />}
        onClick={() => alert('이전 페이지로')}
      >
        이전 페이지로 돌아가기
      </ResponsiveButton>
    </ErrorPage>
  );

export default function ErrorPageCustomExample(props: Partial<ComponentProps<typeof ErrorPage>>) {
  const mergedProps = { ...STORY_DEFAULT_ARGS, ...props } as ComponentProps<typeof ErrorPage>;
  return ErrorPageCustomExampleRender(mergedProps);
}

NotFound

import type { ComponentProps } from 'react';
import { ErrorPage } from '@mildang/design-system/ErrorPage';

const STORY_DEFAULT_ARGS = { ...({
    type: 'notFound',
  }), ...({ type: 'notFound' }) } as ComponentProps<typeof ErrorPage>;

export default function ErrorPageNotFoundExample(props: Partial<ComponentProps<typeof ErrorPage>> = {}) {
  const mergedProps = { ...STORY_DEFAULT_ARGS, ...props } as ComponentProps<typeof ErrorPage>;
  return <ErrorPage {...mergedProps} />;
}

ServerError

import type { ComponentProps } from 'react';
import { ErrorPage } from '@mildang/design-system/ErrorPage';

const STORY_DEFAULT_ARGS = { ...({
    type: 'notFound',
  }), ...({ type: 'server' }) } as ComponentProps<typeof ErrorPage>;

export default function ErrorPageServerErrorExample(props: Partial<ComponentProps<typeof ErrorPage>> = {}) {
  const mergedProps = { ...STORY_DEFAULT_ARGS, ...props } as ComponentProps<typeof ErrorPage>;
  return <ErrorPage {...mergedProps} />;
}

Auth

import type { ComponentProps } from 'react';
import { ErrorPage } from '@mildang/design-system/ErrorPage';

const STORY_DEFAULT_ARGS = { ...({
    type: 'notFound',
  }), ...({ type: 'authority' }) } as ComponentProps<typeof ErrorPage>;

export default function ErrorPageAuthExample(props: Partial<ComponentProps<typeof ErrorPage>> = {}) {
  const mergedProps = { ...STORY_DEFAULT_ARGS, ...props } as ComponentProps<typeof ErrorPage>;
  return <ErrorPage {...mergedProps} />;
}

AuthAccount

import type { ComponentProps } from 'react';
import { ErrorPage } from '@mildang/design-system/ErrorPage';

const STORY_DEFAULT_ARGS = { ...({
    type: 'notFound',
  }), ...({ type: 'authorityAccount' }) } as ComponentProps<typeof ErrorPage>;

export default function ErrorPageAuthAccountExample(props: Partial<ComponentProps<typeof ErrorPage>> = {}) {
  const mergedProps = { ...STORY_DEFAULT_ARGS, ...props } as ComponentProps<typeof ErrorPage>;
  return <ErrorPage {...mergedProps} />;
}

Basic

import { ErrorPageActions } from '@mildang/design-system/ErrorPage';
import { ResponsiveButton } from '@mildang/design-system/ErrorPage';

const ErrorPageActionsBasicExample = () => (
    <ErrorPageActions>
      <ResponsiveButton variant="secondary" onClick={() => {}}>
        이전 페이지로
      </ResponsiveButton>
      <ResponsiveButton variant="primary" onClick={() => {}}>
        홈으로
      </ResponsiveButton>
    </ErrorPageActions>
  );

export default ErrorPageActionsBasicExample;

Basic

import type { ComponentProps } from 'react';
import { ResponsiveButton } from '@mildang/design-system/ErrorPage';

const STORY_DEFAULT_ARGS = { ...({}), ...({
    variant: 'primary',
    children: '홈으로',
    onClick: () => {},
  }) } as ComponentProps<typeof ResponsiveButton>;

export default function ResponsiveButtonBasicExample(props: Partial<ComponentProps<typeof ResponsiveButton>> = {}) {
  const mergedProps = { ...STORY_DEFAULT_ARGS, ...props } as ComponentProps<typeof ResponsiveButton>;
  return <ResponsiveButton {...mergedProps} />;
}