import type { ReactNode, Ref } from "react"; import { FoxChatDotsIcon, FoxCheckCircleIcon, FoxInfoIcon, FoxProhibitIcon, FoxWarningIcon, } from "../../icons"; import { cx } from "../../utils"; export type FoxAlertType = | "default" | "information" | "success" | "warning" | "danger"; export interface FoxAlertProps { /** * 알림의 성격. 아이콘·배경·테두리·제목 색이 여기서 갈린다. * * 계열이 바꾸는 것은 배경 · 테두리 · 제목 글자색과 아이콘이다. 본문 글자색은 계열과 * 무관하게 같다. * * 아이콘은 계열이 정하고 굵기는 시안대로 `duotone`이며, 색은 제목 글자와 같은 계열색이다. */ type?: FoxAlertType; /** 굵은 제목 줄. 넘기지 않으면 영역을 렌더링하지 않는다. */ title?: ReactNode; /** 제목 아래 본문. 넘기지 않으면 영역을 렌더링하지 않는다. */ message?: ReactNode; /** * 보조기술이 읽는 방식을 정한다(`FoxToast`와 같은 규칙). * * - `false`(기본): `role="status"` — 하던 말을 끊지 않는다. 화면과 함께 처음부터 놓여 * 있는 알림은 이쪽이다. * - `true`: `role="alert"` — 읽던 것을 끊고 바로 읽는다. 사용자의 동작 결과로 **그 자리에 * 나타난** 알림에만 쓴다. * * `type="danger"`가 자동으로 이걸 켜지 않는다 — 위험한 내용인 것과 지금 끼어들어야 하는 * 것은 다른 문제이고, 페이지와 함께 그려지는 경고까지 낭독을 끊으면 방해만 된다. */ urgent?: boolean; /** 참이면 렌더하지 않는다(DOM에 남지 않는다). */ hidden?: boolean; id?: string; /** 배치 조정용. 시안의 폭(720px)을 바꿔야 할 때도 여기로 준다. */ className?: string; ref?: Ref; } /** `Record`로 고정해 계열을 추가하면 항목 누락이 타입 에러가 되게 한다. */ const TYPE_CLASS: Record = { default: "fox-alert--default", information: "fox-alert--information", success: "fox-alert--success", warning: "fox-alert--warning", danger: "fox-alert--danger", }; /** * 계열이 정하는 아이콘. 호출부가 넘기지 않는다 — 무엇을 그릴지는 계열이 이미 답한다 * (`FoxTag`와 같은 규칙). * * 시안 `ico/*`가 Phosphor 원본이라 이름이 그대로 붙는다(`ico/Prohibit` → * `FoxProhibitIcon`). 손으로 SVG를 그려 넣지 않는다 — 아이콘은 생성물이 단일 출처다. * * 굵기는 시안이 `Weight=Duotone`이라 다섯 개 모두 `duotone`이다. 기본값(`regular`)으로 두면 * 속이 빈 선 그림이 되어 시안과 달라지므로 반드시 적는다. * * duotone은 연한 면(`opacity` 0.2)과 진한 선을 겹쳐 그리는데 **둘 다 `currentColor`다** — * 색은 스타일이 `.fox-alert__icon`에 준 하나를 쓰고, 연한 쪽만 알아서 흐려진다. */ const TYPE_ICON: Record = { default: , information: , success: , warning: , danger: , }; /** * @fox 알럿. 화면 안에 놓이는 띠 모양 알림이다 — 아이콘 상자 · 제목 · 본문이 한 줄로 선다. * * **모달이 아니다.** 화면을 덮지도, 포커스를 가두지도, 확인 버튼을 갖지도 않는다. 내용 흐름 * 안에 그대로 놓이고, 언제 나타나고 사라질지는 호출부가 정한다(`FoxToast`와 같은 방식). * * 상호작용이 없어 `"use client"`가 아니다 — 서버 컴포넌트로 렌더된다. * * ⚠️ 시안 주석: **본문은 두 줄 이내**로 쓴다. 길이를 코드가 막지는 않는다 — 세 줄이 되면 * 아이콘 상자만 가운데 남고 띠가 늘어난다. * * ⚠️ 스타일은 이 파일이 import하지 않는다 — 호스트 앱이 `@use "@fox/styles/components"` * (또는 개별 파티셜)로 한 번 불러와야 한다. */ export function FoxAlert({ type = "default", title, message, urgent = false, hidden = false, id, className, ref, }: FoxAlertProps) { if (hidden) { return null; } return (
{/* 아이콘이 정해지기 전에도 상자는 그린다 — 시안이 흰 판을 배치의 일부로 준다. */}
{title === undefined ? null : ( {title} )} {message === undefined ? null : ( {message} )}
); }