Replace the inline SVG icon set with the vuesax linear pack, add skeleton primitives for loading states, and keep page scroll inside the app shell. Co-authored-by: Cursor <cursoragent@cursor.com>
56 lines
1.2 KiB
Vue
56 lines
1.2 KiB
Vue
<script setup lang="ts">
|
|
import { computed, toRef } from 'vue';
|
|
import { Skeleton, theme } from 'ant-design-vue';
|
|
import { useCrmSkeletonLoading } from './context';
|
|
|
|
const ASkeletonButton = Skeleton.Button;
|
|
|
|
const props = withDefaults(
|
|
defineProps<{
|
|
loading?: boolean;
|
|
width?: string | number;
|
|
/** Typography title level approximation: 1≈38, 2≈30, 3≈24, 4≈20, 5≈16 */
|
|
level?: 1 | 2 | 3 | 4 | 5;
|
|
}>(),
|
|
{ level: 3, width: 180 },
|
|
);
|
|
|
|
const { token } = theme.useToken();
|
|
const isLoading = useCrmSkeletonLoading(toRef(props, 'loading'));
|
|
|
|
const height = computed(() => {
|
|
switch (props.level) {
|
|
case 1:
|
|
return 38;
|
|
case 2:
|
|
return 30;
|
|
case 3:
|
|
return 24;
|
|
case 4:
|
|
return 20;
|
|
default:
|
|
return 16;
|
|
}
|
|
});
|
|
|
|
const widthCss = computed(() =>
|
|
typeof props.width === 'number' ? `${props.width}px` : props.width,
|
|
);
|
|
</script>
|
|
|
|
<template>
|
|
<a-skeleton-button
|
|
v-if="isLoading"
|
|
active
|
|
:style="{
|
|
width: widthCss,
|
|
minWidth: widthCss,
|
|
height: `${height}px`,
|
|
borderRadius: `${token.borderRadiusSM}px`,
|
|
}"
|
|
/>
|
|
<div v-else :style="{ minHeight: `${height}px` }">
|
|
<slot />
|
|
</div>
|
|
</template>
|