mirror of https://github.com/halo-dev/halo-admin
Ryan Wang
3 years ago
6 changed files with 313 additions and 0 deletions
@ -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"; |
Loading…
Reference in new issue