# 404 페이지

페이지를 찾지 못했을 때 보여 주는 블록이에요. 4, 0, 4를 도형으로 쓴 일러스트와 돌아갈 길을 함께 안내해요.

- Type: block
- Theme: base
- Tags: arc, block, 404, not-found, error, illustration, page
- English title: Not found
- URL: https://dsui.vercel.app/items/not-found

## Used items

- [링크형 버튼](https://dsui.vercel.app/items/button-link): 버튼처럼 보이지만 요소는 링크예요. 어딘가로 가는 자리에 써요.
- [일러스트](https://dsui.vercel.app/items/illustration): 히어로, 섹션 헤더, 카드 커버에 쓰는 도형 일러스트예요. 테마가 직접 그린 그림이 없으면 베이스 그림을 테마 색으로 그려요.

## Controls

| Key | Type | Label | Default |
| --- | --- | --- | --- |
| illustration | boolean | 일러스트 | true |
| title | text | 제목 | 페이지를 찾을 수 없어요 |
| description | text | 설명 | 주소가 바뀌었거나 없어진 페이지예요. 홈에서 다시 찾아볼까요? |
| headingLevel | select | 제목 단계 | 1 |

## Source

### not-found.module.css

```css
.notFound { display: flex; width: 100%; max-width: 36rem; margin-inline: auto; flex-direction: column; align-items: center; text-align: center; word-break: keep-all; color: var(--foreground); font-family: var(--font-body); letter-spacing: var(--tracking-body); }
.art { width: min(100%, 520px); margin-block-end: var(--space-4); border-radius: var(--radius-surface); }
.title { margin: 0; color: var(--foreground); font-family: var(--font-display); font-size: var(--text-2xl); font-weight: 500; letter-spacing: var(--tracking-display); line-height: 1.3; text-wrap: balance; }
.description { max-width: 24rem; margin: var(--space-3) 0 0; color: var(--text-secondary); font-size: var(--text-sm); line-height: var(--leading-body); text-wrap: balance; }
.actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-2); margin-top: var(--space-6); }

```

### not-found.tsx

```tsx
"use client";

import type { HTMLAttributes, ReactNode } from "react";
import { ButtonLink } from "../../button-link/button-link";
import { Illustration } from "../../illustration/illustration";
import styles from "./not-found.module.css";

export interface NotFoundProps extends Omit<HTMLAttributes<HTMLElement>, "title"> {
  title?: string;
  description?: ReactNode;
  /** The ways out, centred under the text. Left out, one link back to `homeHref`. */
  actions?: ReactNode;
  /** Where the default action goes. */
  homeHref?: string;
  /** The heading level. Default 1: a 404 page is usually the whole page, and the heading is its title. */
  headingLevel?: 1 | 2 | 3;
  /** Draws the 404 page-top illustration above the title. The theme's own art is used when it has one. Default true. */
  illustration?: boolean;
}

/**
 * The page a reader lands on when the link is broken or the page has moved. It says plainly what happened, not whose fault
 * it is, and gives a way out right away. The 404 page-top illustration spells 4-0-4 in shapes, in the theme's colours.
 *
 * The heading level is yours: on a real 404 page it is the h1, inside another page it is lower.
 */
export function NotFound({
  className,
  title = "페이지를 찾을 수 없어요",
  description = "주소가 바뀌었거나 없어진 페이지예요. 홈에서 다시 찾아볼까요?",
  actions,
  homeHref = "/",
  headingLevel = 1,
  illustration = true,
  ...props
}: NotFoundProps) {
  const Heading = `h${headingLevel}` as "h1" | "h2" | "h3";
  return (
    <section {...props} className={[styles.notFound, className].filter(Boolean).join(" ")}>
      {illustration ? <Illustration name="page-404" animated className={styles.art} /> : null}
      <Heading className={styles.title}>{title}</Heading>
      {description ? <p className={styles.description}>{description}</p> : null}
      <div className={styles.actions}>{actions ?? <ButtonLink href={homeHref}>홈으로 가기</ButtonLink>}</div>
    </section>
  );
}

NotFound.displayName = "NotFound";

export default NotFound;

```
