본문으로 건너뛰기
Amineslab UI

Component

StateFallback

빈 상태·검색 결과 없음·오류·직접 구성한 안내를 하나의 컴포넌트로 표시합니다.

Playground

옵션을 조절하며 화면과 사용 코드를 함께 확인하세요.

PC 1280px
Controls

auto는 preset 기본 의미색

비우면 preset 기본 제목

비우면 preset 기본 설명

primaryActionOptions.show

primaryActionOptions.children

secondaryActionOptions.show

actions가 버튼 옵션보다 우선

Code
import { StateFallback, Button, Input } from '@amineslab/ui'

import { AlertCircle, Info } from '@amineslab/ui/icons'

export default function ExamplePreview() {
  return ((<StateFallback color={undefined} preset={"empty"} variant={"plain"} size={"md"} title={undefined} description={undefined} icon={<Info />} primaryActionOptions={{
    show: Boolean(true),
    children: "다시 시도",
    onClick: () => undefined
}} secondaryActionOptions={{
    show: Boolean(false),
    children: "돌아가기",
    variant: "ghost"
}} actions={undefined}/>))
}

Props

@amineslab/ui에서 StateFallback, stateFallbackVariants를 가져옵니다.

import { StateFallback, stateFallbackVariants } from '@amineslab/ui'

StateFallback

상태 안내와 하단 action을 단계별로 확장합니다.

NameTypeDefaultDescription
preset'empty' | 'filtered' | 'error' | 'custom''empty'상태별 기본 아이콘·제목·설명·의미 색입니다. custom은 기본 문구가 없습니다.
variant'plain' | 'dashed' | 'panel''plain'상태 표면의 여백입니다.
size'sm' | 'md' | 'lg''md'콘텐츠 간격과 밀도입니다.
color'neutral' | 'danger'-error preset은 danger, 나머지는 neutral입니다. 직접 덮어쓸 수 있습니다.
title / descriptionReactNode-preset 문구를 덮어씁니다. null·false로 숨길 수 있습니다.
icon / illustration / extraReactNode-시각 보조와 부가 콘텐츠입니다. illustration이 icon보다 우선합니다.
primaryActionOptions / secondaryActionOptionsActionButtonProps-ButtonProps & { show?: boolean }. 기본 type=button, variant=outline, size=md. 옵션을 전달했을 때만 표시합니다.
actions(ActionButtonProps | ReactNode)[]-기본 옵션 대신 표시할 버튼·노드 목록. []는 모든 action을 숨깁니다.
className / role / aria-liveHTMLAttributes<HTMLDivElement>-기본 role=status, aria-live=polite. 영역 속성과 ref를 전달합니다.

Examples

자주 쓰는 조합을 살펴보고, 필요한 예시의 코드를 펼쳐 확인하세요.

직접 구성한 안내

업로드할 파일을 선택하세요
지원 형식은 PNG와 JPG입니다.
최대 10MB
import { StateFallback, Badge } from '@amineslab/ui'

import { Info } from '@amineslab/ui/icons'

function DirectStateExample() {
    return (<div className="grid w-full gap-3">
      <StateFallback preset="custom" variant="dashed" size="sm" icon={<Info aria-hidden="true"/>} title="업로드할 파일을 선택하세요" description="지원 형식은 PNG와 JPG입니다." extra={<Badge variant="outline">최대 10MB</Badge>}/>
    </div>);
}

export default function ExamplePreview() {
  return (<DirectStateExample />)
}

초기 빈 상태

아직 항목이 없습니다
import { StateFallback, AppliedFilters } from '@amineslab/ui'

import { AlertCircle, Search } from '@amineslab/ui/icons'

function StatesExample({ mode }: {
    mode: 'empty' | 'filtered' | 'error';
}) {
    return (<StateFallback preset={mode} icon={mode === 'error' ? <AlertCircle /> : <Search />} extra={mode === 'filtered' ? (<AppliedFilters chips={[{ id: 'status', label: '상태: 진행 중', onRemove: () => undefined }]}/>) : undefined} primaryActionOptions={{
            children: mode === 'filtered' ? '필터 초기화' : mode === 'error' ? '다시 시도' : '구성원 추가',
            onClick: () => undefined,
        }}/>);
}

export default function ExamplePreview() {
  return (<StatesExample mode="empty"/>)
}

필터 결과 없음

조건에 맞는 항목이 없습니다
필터를 비우거나 다른 조건으로 다시 시도해 보세요.
상태: 진행 중
import { StateFallback, AppliedFilters } from '@amineslab/ui'

import { AlertCircle, Search } from '@amineslab/ui/icons'

function StatesExample({ mode }: {
    mode: 'empty' | 'filtered' | 'error';
}) {
    return (<StateFallback preset={mode} icon={mode === 'error' ? <AlertCircle /> : <Search />} extra={mode === 'filtered' ? (<AppliedFilters chips={[{ id: 'status', label: '상태: 진행 중', onRemove: () => undefined }]}/>) : undefined} primaryActionOptions={{
            children: mode === 'filtered' ? '필터 초기화' : mode === 'error' ? '다시 시도' : '구성원 추가',
            onClick: () => undefined,
        }}/>);
}

export default function ExamplePreview() {
  return (<StatesExample mode="filtered"/>)
}

오류 상태

불러오지 못했어요
잠시 후 다시 시도해 주세요.
import { StateFallback, AppliedFilters } from '@amineslab/ui'

import { AlertCircle, Search } from '@amineslab/ui/icons'

function StatesExample({ mode }: {
    mode: 'empty' | 'filtered' | 'error';
}) {
    return (<StateFallback preset={mode} icon={mode === 'error' ? <AlertCircle /> : <Search />} extra={mode === 'filtered' ? (<AppliedFilters chips={[{ id: 'status', label: '상태: 진행 중', onRemove: () => undefined }]}/>) : undefined} primaryActionOptions={{
            children: mode === 'filtered' ? '필터 초기화' : mode === 'error' ? '다시 시도' : '구성원 추가',
            onClick: () => undefined,
        }}/>);
}

export default function ExamplePreview() {
  return (<StatesExample mode="error"/>)
}

비동기 재시도

실패 응답을 끄면 재시도 후 성공합니다. 요청 중 중복 실행을 막고 실패하면 다시 시도할 수 있습니다.

불러오지 못했어요
다시 시도해 주세요.
import { useState } from 'react'

import { useQueryRetry, Checkbox, StateFallback } from '@amineslab/ui'

function RetryStateExample() {
    const [failed, setFailed] = useState(true);
    const [rejectRequest, setRejectRequest] = useState(true);
    const [description, setDescription] = useState('다시 시도해 주세요.');
    const { retry, retrying, showError } = useQueryRetry(failed, async () => {
        await new Promise((resolve) => setTimeout(resolve, 800));
        if (rejectRequest)
            throw new Error('요청이 실패했습니다. 연결을 확인하고 다시 시도해 주세요.');
        setFailed(false);
    });
    return (<div className="grid w-full gap-3">
      <Checkbox label="실패 응답 시뮬레이션" checked={rejectRequest} onCheckedChange={(value) => setRejectRequest(value === true)}/>
      {showError ? (<StateFallback preset="error" description={description} primaryActionOptions={{
                children: '다시 시도',
                loading: retrying,
                loadingLabel: '다시 시도 중…',
                onClick: () => {
                    void retry().catch((error: unknown) => setDescription(error instanceof Error ? error.message : '다시 시도해 주세요.'));
                },
            }}/>) : (<StateFallback preset="custom" title="불러왔습니다" primaryActionOptions={{
                children: '오류 상태로 되돌리기',
                onClick: () => setFailed(true),
            }}/>)}
    </div>);
}

export default function ExamplePreview() {
  return (<RetryStateExample />)
}

사용 기준

권장하는 사용
  • preset은 상태 의미, variant는 표면, size는 밀도를 선택합니다.
  • title과 description으로 기본 문구를 바꾸고 null로 숨깁니다. icon과 illustration은 필요한 시각 보조를 직접 넣습니다.
  • primaryActionOptions와 secondaryActionOptions에 ButtonProps를 전달합니다. show=false로 숨기고 children으로 버튼 내용을 지정합니다.
  • actions를 명시하면 기본 버튼 옵션은 무시합니다. 옵션 객체와 입력창 같은 ReactNode를 혼합할 수 있으며 빈 배열은 action을 숨깁니다.
  • useQueryRetry의 showError로 오류 영역을 표시하면 재시도 중에도 안내를 유지합니다. 기존 데이터가 있는 오류는 데이터 화면을 유지하세요.
  • 필터 chip은 extra에 AppliedFilters로 조합합니다. 비동기 재시도는 useQueryRetry의 retry·retrying을 primaryActionOptions.onClick·loading에 연결합니다. retry()의 실패는 사용처에서 catch로 처리합니다.
피해야 할 사용
  • 겉모양만으로 사용을 결정하지 마세요.
  • 의미와 키보드 동작, 모바일에서의 흐름을 함께 확인하세요.

접근성

화면에 맞는 이름을 제공하고, 키보드만으로 작업을 마칠 수 있는지 확인하세요.

  • Tab: 하단 action의 실제 버튼·링크·입력으로 이동합니다.