advent22/ui/src/components/bulma/Drawer.vue

90 lines
2 KiB
Vue
Raw Normal View History

<!-- eslint-disable vue/multi-word-component-names -->
2023-09-09 22:18:16 +00:00
<template>
2023-09-10 03:38:24 +00:00
<div class="card">
2023-10-27 15:09:44 +00:00
<header class="card-header is-unselectable" style="cursor: pointer">
2023-09-12 15:39:54 +00:00
<p class="card-header-title" @click="toggle">{{ header }}</p>
2023-09-13 15:58:15 +00:00
2023-09-12 15:46:45 +00:00
<p v-if="refreshable" class="card-header-icon px-0">
<BulmaButton class="is-small is-primary" @click="refresh">
<FontAwesomeIcon
:icon="['fas', 'arrows-rotate']"
:spin="is_open && state === 'loading'"
2023-09-12 20:39:31 +00:00
/>
2023-09-14 13:54:23 +00:00
</BulmaButton>
2023-09-12 15:46:45 +00:00
</p>
2023-09-13 15:58:15 +00:00
2023-09-12 15:39:54 +00:00
<button class="card-header-icon" @click="toggle">
2023-09-09 23:19:46 +00:00
<span class="icon">
<FontAwesomeIcon
:icon="['fas', is_open ? 'angle-down' : 'angle-right']"
2023-09-09 22:18:16 +00:00
/>
</span>
2023-09-10 03:38:24 +00:00
</button>
</header>
2023-09-12 15:10:54 +00:00
<template v-if="is_open">
<div v-if="state === 'loading'" class="card-content">
<progress class="progress is-primary" />
2023-09-14 03:59:33 +00:00
</div>
<div
v-else-if="state === 'failed'"
2023-09-14 03:59:33 +00:00
class="card-content has-text-danger has-text-centered"
>
2023-09-13 15:58:15 +00:00
<span class="icon is-large">
<FontAwesomeIcon :icon="['fas', 'ban']" size="3x" />
2023-09-13 15:58:15 +00:00
</span>
</div>
<slot v-else name="default" />
2023-09-12 15:10:54 +00:00
</template>
2023-09-09 22:18:16 +00:00
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
2023-09-14 13:54:23 +00:00
import BulmaButton from "./Button.vue";
withDefaults(
defineProps<{
header: string;
refreshable?: boolean;
}>(),
{ refreshable: false },
);
2023-09-14 03:59:33 +00:00
const emit = defineEmits<{
open: [
{
ready(): void;
fail(): void;
2023-09-12 15:39:54 +00:00
},
];
}>();
2023-09-14 12:51:30 +00:00
const is_open = ref(false);
const state = ref<"loading" | "ready" | "failed">("loading");
2023-09-14 12:51:30 +00:00
function toggle() {
is_open.value = !is_open.value;
2023-09-12 15:39:54 +00:00
if (is_open.value) {
state.value = "loading";
2023-09-14 03:59:33 +00:00
emit("open", {
ready: () => (state.value = "ready"),
fail: () => (state.value = "failed"),
});
2023-09-14 03:59:33 +00:00
}
}
2023-09-14 03:59:33 +00:00
function refresh() {
is_open.value = false;
toggle();
2023-09-09 22:18:16 +00:00
}
</script>
2023-10-27 15:09:44 +00:00
<style scoped>
div.card:not(:last-child) {
margin-bottom: 1.5rem;
2023-09-09 22:18:16 +00:00
}
</style>