mirror of https://github.com/halo-dev/halo-admin
parent
f522c4bbde
commit
db32465a04
|
@ -0,0 +1,91 @@
|
|||
<script lang="ts" setup>
|
||||
import { VAlert } from "./index";
|
||||
import { VButton } from "@/components/base/button";
|
||||
import { IconMessage } from "@/core/icons";
|
||||
|
||||
function initState() {
|
||||
return {
|
||||
type: "default",
|
||||
title: "提示",
|
||||
description: "这是一个提示",
|
||||
closable: true,
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Story title="Alert">
|
||||
<Variant title="Show Cases">
|
||||
<template #default>
|
||||
<div class="p-3">
|
||||
<VAlert type="default" title="default" />
|
||||
</div>
|
||||
<div class="p-3">
|
||||
<VAlert type="success" title="default" />
|
||||
</div>
|
||||
<div class="p-3">
|
||||
<VAlert type="info" title="default" />
|
||||
</div>
|
||||
<div class="p-3">
|
||||
<VAlert type="warning" title="default" />
|
||||
</div>
|
||||
<div class="p-3">
|
||||
<VAlert type="error" title="default" />
|
||||
</div>
|
||||
<div class="p-3">
|
||||
<VAlert type="default" title="提示">
|
||||
<template #description>
|
||||
目前仅支持远程 Git 仓库和 ZIP 下载链接。更多主题可以访问:
|
||||
<a href="https://halo.run/themes">https://halo.run/themes</a>
|
||||
</template>
|
||||
<template #actions>
|
||||
<div class="flex justify-end">
|
||||
<VButton type="default">访问</VButton>
|
||||
</div>
|
||||
</template>
|
||||
</VAlert>
|
||||
</div>
|
||||
</template>
|
||||
</Variant>
|
||||
|
||||
<Variant title="Playground" :init-state="initState">
|
||||
<template #default="{ state }">
|
||||
<div class="p-3">
|
||||
<VAlert
|
||||
:type="state.type"
|
||||
:title="state.title"
|
||||
:description="state.description"
|
||||
:closable="state.closable"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #controls="{ state }">
|
||||
<HstText v-model="state.type" title="Type" />
|
||||
<HstText v-model="state.title" title="Title" />
|
||||
<HstText v-model="state.description" title="Description" />
|
||||
<HstCheckbox v-model="state.closable" title="Closable" />
|
||||
</template>
|
||||
</Variant>
|
||||
|
||||
<Variant title="Slots">
|
||||
<template #default>
|
||||
<div class="p-3">
|
||||
<VAlert type="default" title="你有新的消息">
|
||||
<template #icon>
|
||||
<IconMessage />
|
||||
</template>
|
||||
<template #description>
|
||||
@Ryan Wang 在你的站点创建了新评论
|
||||
</template>
|
||||
<template #actions>
|
||||
<div class="flex justify-end">
|
||||
<VButton type="default">查看</VButton>
|
||||
</div>
|
||||
</template>
|
||||
</VAlert>
|
||||
</div>
|
||||
</template>
|
||||
</Variant>
|
||||
</Story>
|
||||
</template>
|
|
@ -0,0 +1,200 @@
|
|||
<script lang="ts" setup>
|
||||
import type { Component, PropType } from "vue";
|
||||
import { computed } from "vue";
|
||||
import type { Type } from "@/components/base/alert/interface";
|
||||
import {
|
||||
IconCheckboxCircle,
|
||||
IconClose,
|
||||
IconCloseCircle,
|
||||
IconErrorWarning,
|
||||
IconInformation,
|
||||
} from "@/core/icons";
|
||||
|
||||
const TypeIcons: Record<Type, Component> = {
|
||||
success: IconCheckboxCircle,
|
||||
info: IconInformation,
|
||||
default: IconInformation,
|
||||
warning: IconErrorWarning,
|
||||
error: IconCloseCircle,
|
||||
};
|
||||
|
||||
const props = defineProps({
|
||||
type: {
|
||||
type: String as PropType<Type>,
|
||||
default: "default",
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
},
|
||||
closable: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(["close"]);
|
||||
|
||||
const classes = computed(() => {
|
||||
return [`alert-${props.type}`];
|
||||
});
|
||||
|
||||
const handleClose = () => {
|
||||
emit("close");
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="classes" class="alert-wrapper">
|
||||
<div class="alert-header">
|
||||
<div class="alert-icon">
|
||||
<slot name="icon">
|
||||
<component :is="TypeIcons[type]" />
|
||||
</slot>
|
||||
</div>
|
||||
<div class="alert-title">
|
||||
{{ title }}
|
||||
</div>
|
||||
<div v-if="closable" class="alert-close" @click="handleClose">
|
||||
<IconClose />
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="description || $slots.description" class="alert-description">
|
||||
<slot name="description">
|
||||
{{ description }}
|
||||
</slot>
|
||||
</div>
|
||||
<div v-if="$slots.actions" class="alert-actions">
|
||||
<slot name="actions" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.alert-wrapper {
|
||||
@apply flex;
|
||||
@apply flex-col;
|
||||
@apply box-border;
|
||||
@apply border;
|
||||
padding: 12px 16px;
|
||||
border-radius: 4px;
|
||||
|
||||
.alert-header {
|
||||
@apply flex;
|
||||
|
||||
.alert-icon {
|
||||
@apply self-center;
|
||||
@apply mr-3;
|
||||
@apply text-lg;
|
||||
}
|
||||
|
||||
.alert-title {
|
||||
@apply self-center;
|
||||
@apply mr-3;
|
||||
@apply flex-1;
|
||||
@apply font-medium;
|
||||
@apply text-base;
|
||||
}
|
||||
|
||||
.alert-close {
|
||||
@apply self-center;
|
||||
@apply cursor-pointer;
|
||||
@apply rounded-full;
|
||||
@apply p-0.5;
|
||||
|
||||
&:hover {
|
||||
@apply transition-all;
|
||||
@apply bg-gray-300;
|
||||
@apply text-white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.alert-description {
|
||||
@apply text-sm;
|
||||
@apply mt-2;
|
||||
}
|
||||
|
||||
.alert-actions {
|
||||
@apply border-t;
|
||||
@apply pt-2 mt-3;
|
||||
}
|
||||
|
||||
&.alert-default {
|
||||
@apply bg-gray-50;
|
||||
@apply border-gray-300;
|
||||
|
||||
.alert-icon,
|
||||
.alert-description {
|
||||
@apply text-gray-600;
|
||||
}
|
||||
|
||||
.alert-close,
|
||||
.alert-title {
|
||||
@apply text-gray-700;
|
||||
}
|
||||
}
|
||||
|
||||
&.alert-success {
|
||||
@apply bg-green-50;
|
||||
@apply border-green-300;
|
||||
|
||||
.alert-icon,
|
||||
.alert-description {
|
||||
@apply text-green-600;
|
||||
}
|
||||
|
||||
.alert-close,
|
||||
.alert-title {
|
||||
@apply text-green-700;
|
||||
}
|
||||
}
|
||||
|
||||
&.alert-info {
|
||||
@apply bg-sky-50;
|
||||
@apply border-sky-300;
|
||||
|
||||
.alert-icon,
|
||||
.alert-description {
|
||||
@apply text-sky-600;
|
||||
}
|
||||
|
||||
.alert-close,
|
||||
.alert-title {
|
||||
@apply text-sky-700;
|
||||
}
|
||||
}
|
||||
|
||||
&.alert-warning {
|
||||
@apply bg-orange-50;
|
||||
@apply border-orange-300;
|
||||
|
||||
.alert-icon,
|
||||
.alert-description {
|
||||
@apply text-orange-600;
|
||||
}
|
||||
|
||||
.alert-close,
|
||||
.alert-title {
|
||||
@apply text-orange-700;
|
||||
}
|
||||
}
|
||||
|
||||
&.alert-error {
|
||||
@apply bg-red-50;
|
||||
@apply border-red-300;
|
||||
|
||||
.alert-icon,
|
||||
.alert-description {
|
||||
@apply text-red-600;
|
||||
}
|
||||
|
||||
.alert-close,
|
||||
.alert-title {
|
||||
@apply text-red-700;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,8 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { VAlert } from "../index";
|
||||
|
||||
describe("Alert", () => {
|
||||
it("should render", () => {
|
||||
expect(VAlert).toBeDefined();
|
||||
});
|
||||
});
|
|
@ -0,0 +1 @@
|
|||
export { default as VAlert } from "./Alert.vue";
|
|
@ -0,0 +1 @@
|
|||
export type Type = "default" | "success" | "info" | "warning" | "error";
|
|
@ -28,6 +28,14 @@ import IconFolder from "~icons/ri/folder-2-line";
|
|||
import IconMore from "~icons/ri/more-line";
|
||||
// @ts-ignore
|
||||
import IconClose from "~icons/ri/close-line";
|
||||
// @ts-ignore
|
||||
import IconErrorWarning from "~icons/ri/error-warning-line";
|
||||
// @ts-ignore
|
||||
import IconCheckboxCircle from "~icons/ri/checkbox-circle-line";
|
||||
// @ts-ignore
|
||||
import IconInformation from "~icons/ri/information-line";
|
||||
// @ts-ignore
|
||||
import IconCloseCircle from "~icons/ri/close-circle-line";
|
||||
|
||||
export {
|
||||
IconDashboard,
|
||||
|
@ -45,4 +53,8 @@ export {
|
|||
IconFolder,
|
||||
IconMore,
|
||||
IconClose,
|
||||
IconErrorWarning,
|
||||
IconCheckboxCircle,
|
||||
IconInformation,
|
||||
IconCloseCircle,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue