starwait/components/Ni/Button.vue
2025-04-27 04:17:35 +08:00

266 lines
7.8 KiB
Vue

<script setup lang="ts">
const props = defineProps({
type: {
// 按钮类型
type: String,
default: 'default',
validator: (value: string) => ['default', 'primary', 'info', 'success', 'warning', 'error'].includes(value)
},
strong: {
// 加粗
type: Boolean,
default: false,
},
grade: {
// 重要等级
type: String,
default: 'default', // 深色,浅色,半透明,全透明,虚线
validator: (value: string) => ['default', 'light', 'halfTransparent', 'transparent', 'dotted'].includes(value)
},
angle: {
// 圆角程度
type: String,
default: 'default', // 正常角,圆角,圆形
validator: (value: string) => ['default', 'round', 'circle'].includes(value)
},
loading: {
// 加载中
type: Boolean,
default: false,
},
disabled: {
// 禁用
type: Boolean,
default: false,
}
})
const emit = defineEmits(['click']);
const handleClick = () => {
if (!props.disabled && !props.loading) {
emit('click');
}
};
const typeS = ref(props.type);
const strong = ref(props.strong);
const grade = ref(props.grade);
const angle = ref(props.angle);
const loading = ref(props.loading);
const disabled = ref(props.disabled);
watchEffect(() => {
typeS.value = props.type;
strong.value = props.strong;
grade.value = props.grade;
angle.value = props.angle;
loading.value = props.loading;
disabled.value = props.disabled;
})
const NiButtonClass = computed(() => {
return ['angle-' + angle.value ,
disabled.value ? 'disabled' : '',
strong.value ? 'strong' : '',
grade.value == 'dotted' ? 'dotted' : '',
grade.value == 'light' ? 'light' : '',
grade.value == 'halfTransparent' ? 'halfTransparent' : '',
grade.value == 'transparent' ? 'transparent' : '',
typeS.value == 'default' ? 'defaultType' : '',
].join(' ');
})
const style = computed(() => {
let data;
function makeTypeData(type: string) {
return {
'--NiButton-bg-default': `var(--Ni-button-${type}-bg-default)`,
'--NiButton-bg-hover': `var(--Ni-button-${type}-bg-hover)`,
'--NiButton-bg-click': `var(--Ni-button-${type}-bg-click)`,
'--NiButton-color-default': `var(--Ni-button-color)`,
'--NiButton-color-hover': `var(--Ni-button-color)`,
'--NiButton-color-click': `var(--Ni-button-color)`,
}
}
data = makeTypeData(typeS.value)
if(grade.value == 'light'){
data = {
'--NiButton-bg-default': `var(--Ni-button-${typeS.value}-bg-default-light)`,
'--NiButton-bg-hover': `var(--Ni-button-${typeS.value}-bg-hover-light)`,
'--NiButton-bg-click': `var(--Ni-button-${typeS.value}-bg-click-light)`,
'--NiButton-color-default': `var(--Ni-button-${typeS.value}-bg-default)`,
'--NiButton-color-hover': `var(--Ni-button-${typeS.value}-bg-default)`,
'--NiButton-color-click': `var(--Ni-button-${typeS.value}-bg-default)`,
}
}
return data;
})
</script>
<template data-prefix="Ni">
<div class="NiButton"
:style
:class="NiButtonClass"
@click="handleClick"
>
<slot name="icons"/>
<span v-if="loading" class="sxIconFont" :class="loading && 'loading'">&#xe687;</span>
<slot v-if="!(loading && angle == 'circle')"/>
</div>
</template>
<style scoped lang="scss">
.NiButton{
// ===背景
// 默认背景色
--NiButton-bg-default: var('');
// hover色
--NiButton-bg-hover: var('');
// 点击色
--NiButton-bg-click: var('');
// ===文字
// 默认背景色
--NiButton-color-default: var('');
// hover色
--NiButton-color-hover: var('');
// 点击色
--NiButton-color-click: var('');
position: relative;
display: inline-flex;
align-items: center;
background-color: var(--NiButton-bg-default);
color: var(--NiButton-color-default);
border: 1px solid var(--NiButton-bg-default);
padding: var(--Ni-button-padding);
width: fit-content;
height: var(--Ni-button-height);
cursor: pointer;
transition: color .3s ease-in-out, background-color .3s ease-in-out, border-color .3s ease-in-out, width .3s ease-in-out;
//height: var(--Ni-button-height);
box-sizing: border-box;
user-select: none;
font-weight: 400;
&:hover {
background-color: var(--NiButton-bg-hover);
color: var(--NiButton-color-hover);
border: 1px solid var(--NiButton-bg-hover);
}
&:active {
background-color: var(--NiButton-bg-click);
color: var(--NiButton-color-click);
border: 1px solid var(--NiButton-bg-click);
}
}
.NiButton.defaultType{
background-color: rgba(0, 0, 0, 0);
color: var(--Ni-theme-color-T1);
border: 1px solid var(--Ni-theme-border-color);
&:hover {
background-color: rgba(0, 0, 0, 0);
color: var(--Ni-theme-color-T2);
border: 1px solid var(--Ni-theme-border-color-hover);
}
&:active {
background-color: rgba(0, 0, 0, 0);
color: var(--Ni-theme-color-T0);
border: 1px solid var(--Ni-theme-color-T0);
}
}
.NiButton.disabled{
opacity: var(--Ni-button-disable-opacity);
cursor: not-allowed;
&:hover {
background-color: var(--NiButton-bg-default);
color: var(--NiButton-color-default);
border: 1px solid var(--NiButton-bg-default);
}
&:active {
background-color: var(--NiButton-bg-default);
color: var(--NiButton-color-default);
border: 1px solid var(--NiButton-bg-default);
}
}
.NiButton.angle-default{
border-radius: var(--Ni-button-border-radius);
}
.NiButton.angle-round{
border-radius: var(--Ni-button-height);
height: var(--Ni-button-height);
}
.NiButton.angle-circle{
border-radius: 100%;
padding: .2rem;
aspect-ratio: 1;
width: var(--Ni-button-height);
height: var(--Ni-button-height);
justify-content: center;
}
.NiButton.strong{
font-weight: bold;
}
.NiButton.angle-circle > .loading{
margin-right: 0;
}
.loading{
position: relative;
font-size: 1.2em;
margin-right: 5px;
animation: opacityUp .3s linear forwards, spinX 1.5s infinite linear ;
}
// 浅色
.NiButton.light{
//border-color: var(--NiButton-bg-default);
border: 1px solid transparent;
}
// 半透明
.NiButton.halfTransparent{
background-color: var(--Ni-button-bg-halfTransparent-default);
color: var(--NiButton-bg-default);
border: 1px solid transparent;
&:hover {
background-color: var(--Ni-button-bg-halfTransparent-hover);
color: var(--NiButton-bg-default);
border: 1px solid transparent;
}
&:active {
background-color: var(--Ni-button-bg-halfTransparent-click);
color: var(--NiButton-bg-default);
border: 1px solid transparent;
}
}
// 半透明
.NiButton.transparent{
background-color: rgba(0,0,0,0);
color: var(--NiButton-bg-default);
border: 1px solid transparent;
&:hover {
background-color: var(--Ni-button-bg-halfTransparent-hover);
color: var(--NiButton-bg-default);
border: 1px solid transparent;
}
&:active {
background-color: var(--Ni-button-bg-halfTransparent-click);
color: var(--NiButton-bg-default);
border: 1px solid transparent;
}
}
// 虚线
.NiButton.dotted{
border: 1px dashed var(--NiButton-bg-default);
background-color: transparent;
color: var(--NiButton-bg-default);
&:active {
color: var(--NiButton-bg-click);
border: 1px dashed var(--NiButton-bg-click);
}
}
//旋转
@keyframes spinX {
from { transform: rotate(0deg); }
to { transform: rotate(-360deg); }
}
@keyframes opacityUp {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
</style>