266 lines
7.8 KiB
Vue
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'"></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> |