40 lines
1.9 KiB
Vue
40 lines
1.9 KiB
Vue
<script setup lang="ts">
|
|
import type { KbxAsyncState } from '@kbx/contracts'
|
|
import KbxDataState from './KbxDataState.vue'
|
|
|
|
withDefaults(defineProps<{
|
|
state?: KbxAsyncState
|
|
refreshing?: boolean
|
|
idleTitle?: string
|
|
idleDetail?: string
|
|
idleActionLabel?: string
|
|
emptyTitle?: string
|
|
emptyDetail?: string
|
|
errorTitle?: string
|
|
errorDetail?: string
|
|
retryLabel?: string
|
|
}>(), {
|
|
state:'ready', refreshing:false,
|
|
idleTitle:'조회 전입니다.', idleDetail:'조회조건을 확인한 후 조회하세요.', idleActionLabel:'',
|
|
emptyTitle:'', emptyDetail:'', errorTitle:'', errorDetail:'', retryLabel:'다시 조회',
|
|
})
|
|
const emit=defineEmits<{ retry:[]; idleAction:[] }>()
|
|
</script>
|
|
|
|
<template>
|
|
<div class="kbx-template-state" :data-template-state="state" :aria-busy="state==='loading' || refreshing">
|
|
<KbxDataState v-if="state==='idle'" state="idle" :title="idleTitle" :detail="idleDetail" :action-label="idleActionLabel" @action="emit('idleAction')" />
|
|
<KbxDataState v-else-if="state==='loading'" state="loading" />
|
|
<KbxDataState v-else-if="state==='empty'" state="empty" :title="emptyTitle" :detail="emptyDetail" />
|
|
<KbxDataState v-else-if="state==='error'" state="error" :title="errorTitle" :detail="errorDetail" :action-label="retryLabel" @action="emit('retry')" />
|
|
<template v-else>
|
|
<div v-if="refreshing" class="kbx-template-state__refresh" role="status" aria-live="polite">최신 내용을 조회 중입니다. 현재 화면은 유지됩니다.</div>
|
|
<slot />
|
|
</template>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.kbx-template-state{min-height:0;height:100%;display:flex;flex-direction:column}.kbx-template-state__refresh{min-height:var(--kbx-template-refresh-height);display:flex;align-items:center;padding:0 var(--kbx-space-2);border:var(--kbx-border-width) solid var(--kbx-color-info-border);background:var(--kbx-color-info-surface);color:var(--kbx-color-text-muted);font-size:var(--kbx-font-xs)}
|
|
</style>
|