feat: provide reusable UI and state galleries
This commit is contained in:
@@ -1,23 +1,40 @@
|
||||
import { useId } from "react";
|
||||
|
||||
import { errorMessage } from "./error-copy.js";
|
||||
import { Button } from "./ui/button.jsx";
|
||||
|
||||
/** @param {{ label?: string }} props */
|
||||
export function LoadingSurface({ label = "불러오는 중" }) {
|
||||
return (
|
||||
<section
|
||||
className="state-surface state-surface--loading"
|
||||
aria-busy="true"
|
||||
aria-label={label}
|
||||
aria-live="polite"
|
||||
aria-atomic="true"
|
||||
>
|
||||
<div className="ui-skeleton" aria-hidden="true" />
|
||||
<span className="sr-only">{label}</span>
|
||||
<span className="visually-hidden">{label}</span>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
/** @param {{ title?: string, action?: React.ReactNode }} props */
|
||||
export function EmptySurface({ title = "표시할 항목이 없습니다.", action }) {
|
||||
/**
|
||||
* @param {{
|
||||
* title?: string,
|
||||
* description?: string,
|
||||
* action?: React.ReactNode
|
||||
* }} props
|
||||
*/
|
||||
export function EmptySurface({
|
||||
title = "표시할 항목이 없습니다.",
|
||||
description,
|
||||
action,
|
||||
}) {
|
||||
return (
|
||||
<section className="ui-empty" aria-live="polite">
|
||||
<p>{title}</p>
|
||||
<section className="ui-empty state-surface" aria-live="polite">
|
||||
<h2>{title}</h2>
|
||||
{description ? <p>{description}</p> : null}
|
||||
{action}
|
||||
</section>
|
||||
);
|
||||
@@ -32,17 +49,24 @@ export function EmptySurface({ title = "표시할 항목이 없습니다.", acti
|
||||
* }} props
|
||||
*/
|
||||
export function TerminalErrorSurface({ userMessageKey, action, onAction }) {
|
||||
const messageId = useId();
|
||||
const actionLabels = Object.freeze({
|
||||
retry: "다시 시도",
|
||||
reauth: "로그인",
|
||||
navigate: "안전한 화면으로 이동",
|
||||
"reload-once": "한 번 새로고침",
|
||||
"contact-support": "지원 정보 확인",
|
||||
});
|
||||
return (
|
||||
<section
|
||||
className="ui-terminal-error"
|
||||
className="ui-terminal-error state-surface state-surface--danger"
|
||||
role="alert"
|
||||
aria-labelledby="terminal-error-message"
|
||||
aria-labelledby={messageId}
|
||||
data-message-key={userMessageKey}
|
||||
>
|
||||
<p id="terminal-error-message">{userMessageKey}</p>
|
||||
<h2 id={messageId}>{errorMessage(userMessageKey)}</h2>
|
||||
{action !== "none" && (
|
||||
<button className="ui-button" type="button" onClick={onAction}>
|
||||
{action}
|
||||
</button>
|
||||
<Button onClick={onAction}>{actionLabels[action]}</Button>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user