mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
feat(skeleton-item): add skeleton-item component (#11173)
* feat(skeleton-item): add skeleton-item component * docs(Skeleton): update docs * feat(Skeleton): add skeleton title avatar paragraph image componets * chore: add uncommit files * test(Skeleton): fix skeleton test case failed * feat(Skeleton-Image): add skeleton-image style * test(Skeleton): fix failed test case * docs(Skeleton): update skeleton docs * fix(Skeleton): add skeleton image theme vars * perf(Skeleton): use Icon componet in Skeleton image to reduce bundle size * docs(Skeleton): update skeleton docs * docs(Skeleton): fix wrong component name
This commit is contained in:
parent
3991f27a02
commit
19cd0667e4
35
packages/vant/src/skeleton/Avatar.tsx
Normal file
35
packages/vant/src/skeleton/Avatar.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import { defineComponent, ExtractPropTypes } from 'vue';
|
||||
|
||||
// Utils
|
||||
import {
|
||||
numericProp,
|
||||
getSizeStyle,
|
||||
makeStringProp,
|
||||
createNamespace,
|
||||
} from '../utils';
|
||||
|
||||
const [name, bem] = createNamespace('skeleton-avatar');
|
||||
|
||||
export type SkeletonAvatarShape = 'square' | 'round';
|
||||
|
||||
export const skeletonAvatarProps = {
|
||||
avatarSize: numericProp,
|
||||
avatarShape: makeStringProp<SkeletonAvatarShape>('round'),
|
||||
};
|
||||
|
||||
export type SkeletonAvatarProps = ExtractPropTypes<typeof skeletonAvatarProps>;
|
||||
|
||||
export default defineComponent({
|
||||
name,
|
||||
|
||||
props: skeletonAvatarProps,
|
||||
|
||||
setup(props) {
|
||||
return () => (
|
||||
<div
|
||||
class={bem([props.avatarShape])}
|
||||
style={getSizeStyle(props.avatarSize)}
|
||||
/>
|
||||
);
|
||||
},
|
||||
});
|
38
packages/vant/src/skeleton/Image.tsx
Normal file
38
packages/vant/src/skeleton/Image.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
import { defineComponent, type ExtractPropTypes } from 'vue';
|
||||
|
||||
import {
|
||||
numericProp,
|
||||
getSizeStyle,
|
||||
makeStringProp,
|
||||
createNamespace,
|
||||
} from '../utils';
|
||||
|
||||
import { Icon } from '../icon';
|
||||
|
||||
const [name, bem] = createNamespace('skeleton-image');
|
||||
|
||||
export type SkeletonImageShape = 'square' | 'round';
|
||||
|
||||
export const skeletonImageProps = {
|
||||
imageSize: numericProp,
|
||||
imageShape: makeStringProp<SkeletonImageShape>('square'),
|
||||
};
|
||||
|
||||
export type SkeletonImageProps = ExtractPropTypes<typeof skeletonImageProps>;
|
||||
|
||||
export default defineComponent({
|
||||
name,
|
||||
|
||||
props: skeletonImageProps,
|
||||
|
||||
setup(props) {
|
||||
return () => (
|
||||
<div
|
||||
class={bem([props.imageShape])}
|
||||
style={getSizeStyle(props.imageSize)}
|
||||
>
|
||||
<Icon name={'photo'} class={bem('icon')} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
34
packages/vant/src/skeleton/Paragraph.tsx
Normal file
34
packages/vant/src/skeleton/Paragraph.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import { defineComponent, ExtractPropTypes } from 'vue';
|
||||
|
||||
import { createNamespace, numericProp } from '../utils';
|
||||
|
||||
export const DEFAULT_ROW_WIDTH = '100%';
|
||||
|
||||
export const skeletonParagraphProps = {
|
||||
round: Boolean,
|
||||
rowWidth: {
|
||||
type: numericProp,
|
||||
default: DEFAULT_ROW_WIDTH,
|
||||
},
|
||||
};
|
||||
|
||||
export type SkeletonParagraphProps = ExtractPropTypes<
|
||||
typeof skeletonParagraphProps
|
||||
>;
|
||||
|
||||
const [name, bem] = createNamespace('skeleton-paragraph');
|
||||
|
||||
export default defineComponent({
|
||||
name,
|
||||
|
||||
props: skeletonParagraphProps,
|
||||
|
||||
setup(props) {
|
||||
return () => (
|
||||
<div
|
||||
class={bem([{ round: props.round }])}
|
||||
style={{ width: props.rowWidth }}
|
||||
/>
|
||||
);
|
||||
},
|
||||
});
|
@ -10,10 +10,20 @@ Register component globally via `app.use`, refer to [Component Registration](#/e
|
||||
|
||||
```js
|
||||
import { createApp } from 'vue';
|
||||
import { Skeleton } from 'vant';
|
||||
import {
|
||||
Skeleton,
|
||||
VanSkeletonTitle,
|
||||
VanSkeletonImage,
|
||||
VanSkeletonAvatar,
|
||||
VanSkeletonParagraph,
|
||||
} from 'vant';
|
||||
|
||||
const app = createApp();
|
||||
app.use(Skeleton);
|
||||
app.use(VanSkeletonTitle);
|
||||
app.use(VanSkeletonImage);
|
||||
app.use(VanSkeletonAvatar);
|
||||
app.use(VanSkeletonParagraph);
|
||||
```
|
||||
|
||||
## Usage
|
||||
@ -56,9 +66,29 @@ export default {
|
||||
};
|
||||
```
|
||||
|
||||
### Custom Content
|
||||
|
||||
Using `template` slots to display custom content.
|
||||
|
||||
```html
|
||||
<van-skeleton>
|
||||
<template #template>
|
||||
<div class="template-slot">
|
||||
<van-skeleton-image />
|
||||
<div :style="{ flex: 1 }">
|
||||
<van-skeleton-paragraph row-width="60%" />
|
||||
<van-skeleton-paragraph />
|
||||
<van-skeleton-paragraph />
|
||||
<van-skeleton-paragraph />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</van-skeleton>
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
### Skeleton Props
|
||||
|
||||
| Attribute | Description | Type | Default |
|
||||
| --- | --- | --- | --- |
|
||||
@ -68,17 +98,58 @@ export default {
|
||||
| avatar | Whether to show avatar placeholder | _boolean_ | `false` |
|
||||
| loading | Whether to show skeleton, pass `false` to show child component | _boolean_ | `true` |
|
||||
| animate | Whether to enable animation | _boolean_ | `true` |
|
||||
| round | Whether to show round title and row | _boolean_ | `false` |
|
||||
| round | Whether to show round title and paragraph | _boolean_ | `false` |
|
||||
| title-width | Title width | _number \| string_ | `40%` |
|
||||
| avatar-size | Size of avatar placeholder | _number \| string_ | `32px` |
|
||||
| avatar-shape | Shape of avatar placeholder, can be set to `square` | _string_ | `round` |
|
||||
|
||||
### SkeletonParagraph Props
|
||||
|
||||
| Attribute | Description | Type | Default |
|
||||
| --------- | ------------------------------- | --------- | ------- |
|
||||
| round | Whether to show round paragraph | _boolean_ | `false` |
|
||||
| row-width | Paragraph width | _string_ | `100%` |
|
||||
|
||||
### SkeletonTitle Props
|
||||
|
||||
| Attribute | Description | Type | Default |
|
||||
| ----------- | --------------------------- | ------------------ | ------- |
|
||||
| round | Whether to show round title | _boolean_ | `false` |
|
||||
| title-width | Title width | _number \| string_ | `40%` |
|
||||
|
||||
### SkeletonAvatar Props
|
||||
|
||||
| Attribute | Description | Type | Default |
|
||||
| --- | --- | --- | --- |
|
||||
| avatar-size | Size of avatar placeholder | _number \| string_ | `32px` |
|
||||
| avatar-shape | Shape of avatar placeholder, can be set to `square` | _string_ | `round` |
|
||||
|
||||
### SkeletonImage Props
|
||||
|
||||
| Attribute | Description | Type | Default |
|
||||
| --- | --- | --- | --- |
|
||||
| image-size | Size of image placeholder | _number \| string_ | `32px` |
|
||||
| image-shape | Shape of image placeholder, can be set to `square` | _string_ | `round` |
|
||||
|
||||
### Skeleton Slots
|
||||
|
||||
| Name | Description |
|
||||
| -------- | -------------- |
|
||||
| default | Default slot |
|
||||
| template | Custom content |
|
||||
|
||||
### Types
|
||||
|
||||
The component exports the following type definitions:
|
||||
|
||||
```ts
|
||||
import type { SkeletonProps, SkeletonAvatarShape } from 'vant';
|
||||
import type {
|
||||
SkeletonProps,
|
||||
SkeletonImageProps,
|
||||
SkeletonTitleProps,
|
||||
SkeletonAvatarShape,
|
||||
SkeletonParagraphProps,
|
||||
} from 'vant';
|
||||
```
|
||||
|
||||
## Theming
|
||||
@ -96,3 +167,5 @@ The component provides the following CSS variables, which can be used to customi
|
||||
| --van-skeleton-avatar-size | _32px_ | - |
|
||||
| --van-skeleton-avatar-background | _var(--van-active-color)_ | - |
|
||||
| --van-skeleton-duration | _1.2s_ | - |
|
||||
| --van-skeleton-image-size | _96px_ |
|
||||
| --van-skeleton-image-radius | _24px_ | - |
|
||||
|
@ -10,10 +10,20 @@
|
||||
|
||||
```js
|
||||
import { createApp } from 'vue';
|
||||
import { Skeleton } from 'vant';
|
||||
import {
|
||||
Skeleton,
|
||||
VanSkeletonTitle,
|
||||
VanSkeletonImage,
|
||||
VanSkeletonAvatar,
|
||||
VanSkeletonParagraph,
|
||||
} from 'vant';
|
||||
|
||||
const app = createApp();
|
||||
app.use(Skeleton);
|
||||
app.use(VanSkeletonTitle);
|
||||
app.use(VanSkeletonImage);
|
||||
app.use(VanSkeletonAvatar);
|
||||
app.use(VanSkeletonParagraph);
|
||||
```
|
||||
|
||||
## 代码演示
|
||||
@ -62,9 +72,29 @@ export default {
|
||||
};
|
||||
```
|
||||
|
||||
### 自定义展示内容
|
||||
|
||||
通过 `template` 插槽完成自定义内容的展示。
|
||||
|
||||
```html
|
||||
<van-skeleton>
|
||||
<template #template>
|
||||
<div class="template-slot">
|
||||
<van-skeleton-image />
|
||||
<div :style="{ flex: 1 }">
|
||||
<van-skeleton-paragraph row-width="60%" />
|
||||
<van-skeleton-paragraph />
|
||||
<van-skeleton-paragraph />
|
||||
<van-skeleton-paragraph />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</van-skeleton>
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
### Skeleton Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
@ -79,12 +109,53 @@ export default {
|
||||
| avatar-size | 头像占位图大小 | _number \| string_ | `32px` |
|
||||
| avatar-shape | 头像占位图形状,可选值为 `square` | _string_ | `round` |
|
||||
|
||||
### SkeletonParagraph Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --------- | ------------------------ | --------- | ------- |
|
||||
| round | 是否将段落显示为圆角风格 | _boolean_ | `false` |
|
||||
| row-width | 段落占位图宽度 | _string_ | `100%` |
|
||||
|
||||
### SkeletonTitle Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| ----------- | ------------------------ | ------------------ | ------- |
|
||||
| round | 是否将标题显示为圆角风格 | _boolean_ | `false` |
|
||||
| title-width | 标题占位图宽度 | _number \| string_ | `40%` |
|
||||
|
||||
### SkeletonAvatar Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| avatar-size | 头像占位图大小 | _number \| string_ | `32px` |
|
||||
| avatar-shape | 头像占位图形状,可选值为 `square` | _string_ | `round` |
|
||||
|
||||
### SkeletonImage Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| image-size | 图片占位图大小 | _number \| string_ | `32px` |
|
||||
| image-shape | 图片占位图形状,可选值为 `square` | _string_ | `round` |
|
||||
|
||||
### Skeleton Slots
|
||||
|
||||
| 名称 | 说明 |
|
||||
| -------- | ---------- |
|
||||
| default | 骨架屏内容 |
|
||||
| template | 自定义内容 |
|
||||
|
||||
### 类型定义
|
||||
|
||||
组件导出以下类型定义:
|
||||
|
||||
```ts
|
||||
import type { SkeletonProps, SkeletonAvatarShape } from 'vant';
|
||||
import type {
|
||||
SkeletonProps,
|
||||
SkeletonImageProps,
|
||||
SkeletonTitleProps,
|
||||
SkeletonAvatarShape,
|
||||
SkeletonParagraphProps,
|
||||
} from 'vant';
|
||||
```
|
||||
|
||||
## 主题定制
|
||||
@ -93,12 +164,14 @@ import type { SkeletonProps, SkeletonAvatarShape } from 'vant';
|
||||
|
||||
组件提供了下列 CSS 变量,可用于自定义样式,使用方法请参考 [ConfigProvider 组件](#/zh-CN/config-provider)。
|
||||
|
||||
| 名称 | 默认值 | 描述 |
|
||||
| -------------------------------- | ------------------------- | ---- |
|
||||
| --van-skeleton-row-height | _16px_ | - |
|
||||
| --van-skeleton-row-background | _var(--van-active-color)_ | - |
|
||||
| --van-skeleton-row-margin-top | _var(--van-padding-sm)_ | - |
|
||||
| --van-skeleton-title-width | _40%_ | - |
|
||||
| --van-skeleton-avatar-size | _32px_ | - |
|
||||
| --van-skeleton-avatar-background | _var(--van-active-color)_ | - |
|
||||
| --van-skeleton-duration | _1.2s_ | - |
|
||||
| 名称 | 默认值 | 描述 |
|
||||
| ----------------------------------- | ------------------------- | ---- |
|
||||
| --van-skeleton-paragraph-height | _16px_ | - |
|
||||
| --van-skeleton-paragraph-background | _var(--van-active-color)_ | - |
|
||||
| --van-skeleton-paragraph-margin-top | _var(--van-padding-sm)_ | - |
|
||||
| --van-skeleton-title-width | _40%_ | - |
|
||||
| --van-skeleton-avatar-size | _32px_ | - |
|
||||
| --van-skeleton-avatar-background | _var(--van-active-color)_ | - |
|
||||
| --van-skeleton-duration | _1.2s_ | - |
|
||||
| --van-skeleton-image-size | _96px_ |
|
||||
| --van-skeleton-image-radius | _24px_ | - |
|
||||
|
@ -1,31 +1,34 @@
|
||||
import { defineComponent, type PropType, type ExtractPropTypes } from 'vue';
|
||||
|
||||
// Utils
|
||||
import {
|
||||
addUnit,
|
||||
truthProp,
|
||||
numericProp,
|
||||
getSizeStyle,
|
||||
makeStringProp,
|
||||
makeNumericProp,
|
||||
createNamespace,
|
||||
type Numeric,
|
||||
} from '../utils';
|
||||
|
||||
const [name, bem] = createNamespace('skeleton');
|
||||
const DEFAULT_ROW_WIDTH = '100%';
|
||||
const DEFAULT_LAST_ROW_WIDTH = '60%';
|
||||
// Components
|
||||
import SkeletonTitle from './Title';
|
||||
import SkeletonAvatar, { type SkeletonAvatarShape } from './Avatar';
|
||||
import SkeletonParagraph, { DEFAULT_ROW_WIDTH } from './Paragraph';
|
||||
|
||||
export type SkeletonAvatarShape = 'square' | 'round';
|
||||
const [name, bem] = createNamespace('skeleton');
|
||||
const DEFAULT_LAST_ROW_WIDTH = '60%';
|
||||
|
||||
export const skeletonProps = {
|
||||
row: makeNumericProp(0),
|
||||
title: Boolean,
|
||||
round: Boolean,
|
||||
title: Boolean,
|
||||
titleWidth: numericProp,
|
||||
avatar: Boolean,
|
||||
avatarSize: numericProp,
|
||||
avatarShape: makeStringProp<SkeletonAvatarShape>('round'),
|
||||
loading: truthProp,
|
||||
animate: truthProp,
|
||||
avatarSize: numericProp,
|
||||
titleWidth: numericProp,
|
||||
avatarShape: makeStringProp<SkeletonAvatarShape>('round'),
|
||||
rowWidth: {
|
||||
type: [Number, String, Array] as PropType<Numeric | Numeric[]>,
|
||||
default: DEFAULT_ROW_WIDTH,
|
||||
@ -45,9 +48,9 @@ export default defineComponent({
|
||||
const renderAvatar = () => {
|
||||
if (props.avatar) {
|
||||
return (
|
||||
<div
|
||||
class={bem('avatar', props.avatarShape)}
|
||||
style={getSizeStyle(props.avatarSize)}
|
||||
<SkeletonAvatar
|
||||
avatarShape={props.avatarShape}
|
||||
avatarSize={props.avatarSize}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -56,10 +59,7 @@ export default defineComponent({
|
||||
const renderTitle = () => {
|
||||
if (props.title) {
|
||||
return (
|
||||
<h3
|
||||
class={bem('title')}
|
||||
style={{ width: addUnit(props.titleWidth) }}
|
||||
/>
|
||||
<SkeletonTitle round={props.round} titleWidth={props.titleWidth} />
|
||||
);
|
||||
}
|
||||
};
|
||||
@ -82,9 +82,29 @@ export default defineComponent({
|
||||
Array(+props.row)
|
||||
.fill('')
|
||||
.map((_, i) => (
|
||||
<div class={bem('row')} style={{ width: addUnit(getRowWidth(i)) }} />
|
||||
<SkeletonParagraph
|
||||
key={i}
|
||||
round={props.round}
|
||||
rowWidth={addUnit(getRowWidth(i))}
|
||||
/>
|
||||
));
|
||||
|
||||
const renderContents = () => {
|
||||
if (slots.template) {
|
||||
return slots.template();
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{renderAvatar()}
|
||||
<div class={bem('content')}>
|
||||
{renderTitle()}
|
||||
{renderRows()}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
return () => {
|
||||
if (!props.loading) {
|
||||
return slots.default?.();
|
||||
@ -95,11 +115,7 @@ export default defineComponent({
|
||||
class={bem({ animate: props.animate, round: props.round })}
|
||||
{...attrs}
|
||||
>
|
||||
{renderAvatar()}
|
||||
<div class={bem('content')}>
|
||||
{renderTitle()}
|
||||
{renderRows()}
|
||||
</div>
|
||||
{renderContents()}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
27
packages/vant/src/skeleton/Title.tsx
Normal file
27
packages/vant/src/skeleton/Title.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
import { defineComponent, type ExtractPropTypes } from 'vue';
|
||||
|
||||
import { createNamespace, numericProp, addUnit } from '../utils';
|
||||
|
||||
const [name, bem] = createNamespace('skeleton-title');
|
||||
|
||||
export const skeletonTitleProps = {
|
||||
round: Boolean,
|
||||
titleWidth: numericProp,
|
||||
};
|
||||
|
||||
export type SkeletonTitleProps = ExtractPropTypes<typeof skeletonTitleProps>;
|
||||
|
||||
export default defineComponent({
|
||||
name,
|
||||
|
||||
props: skeletonTitleProps,
|
||||
|
||||
setup(props) {
|
||||
return () => (
|
||||
<h3
|
||||
class={bem([{ round: props.round }])}
|
||||
style={{ width: addUnit(props.titleWidth) }}
|
||||
/>
|
||||
);
|
||||
},
|
||||
});
|
@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import VanSkeleton from '..';
|
||||
import VanSkeleton, { VanSkeletonParagraph, VanSkeletonImage } from '..';
|
||||
import VanSwitch from '../../switch';
|
||||
import { ref } from 'vue';
|
||||
import { cdnURL, useTranslate } from '../../../docs/site';
|
||||
@ -10,12 +10,14 @@ const t = useTranslate({
|
||||
showChildren: '显示子组件',
|
||||
title: '关于 Vant',
|
||||
desc: 'Vant 是一套轻量、可靠的移动端 Vue 组件库,提供了丰富的基础组件和业务组件,帮助开发者快速搭建移动应用。',
|
||||
customContent: '自定义展示内容',
|
||||
},
|
||||
'en-US': {
|
||||
showAvatar: 'Show Avatar',
|
||||
showChildren: 'Show Children',
|
||||
title: 'About Vant',
|
||||
desc: 'Vant is a set of Mobile UI Components built on Vue.',
|
||||
customContent: 'Custom Content',
|
||||
},
|
||||
});
|
||||
|
||||
@ -43,6 +45,22 @@ const show = ref(false);
|
||||
</div>
|
||||
</van-skeleton>
|
||||
</demo-block>
|
||||
|
||||
<demo-block :title="t('customContent')">
|
||||
<van-skeleton>
|
||||
<template #template>
|
||||
<div class="template-slot">
|
||||
<van-skeleton-image />
|
||||
<div :style="{ flex: 1 }">
|
||||
<van-skeleton-paragraph row-width="60%" />
|
||||
<van-skeleton-paragraph />
|
||||
<van-skeleton-paragraph />
|
||||
<van-skeleton-paragraph />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</van-skeleton>
|
||||
</demo-block>
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
@ -80,5 +98,14 @@ const show = ref(false);
|
||||
margin-right: var(--van-padding-md);
|
||||
}
|
||||
}
|
||||
|
||||
.template-slot {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
.van-skeleton-image {
|
||||
margin-right: var(--van-padding-md);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -1,10 +1,12 @@
|
||||
:root {
|
||||
--van-skeleton-row-height: 16px;
|
||||
--van-skeleton-row-background: var(--van-active-color);
|
||||
--van-skeleton-row-margin-top: var(--van-padding-sm);
|
||||
--van-skeleton-paragraph-height: 16px;
|
||||
--van-skeleton-paragraph-background: var(--van-active-color);
|
||||
--van-skeleton-paragraph-margin-top: var(--van-padding-sm);
|
||||
--van-skeleton-title-width: 40%;
|
||||
--van-skeleton-avatar-size: 32px;
|
||||
--van-skeleton-avatar-background: var(--van-active-color);
|
||||
--van-skeleton-image-size: 96px;
|
||||
--van-skeleton-image-radius: 24px;
|
||||
--van-skeleton-duration: 1.2s;
|
||||
}
|
||||
|
||||
@ -12,7 +14,7 @@
|
||||
display: flex;
|
||||
padding: 0 var(--van-padding-md);
|
||||
|
||||
&__avatar {
|
||||
&-avatar {
|
||||
flex-shrink: 0;
|
||||
width: var(--van-skeleton-avatar-size);
|
||||
height: var(--van-skeleton-avatar-size);
|
||||
@ -28,28 +30,28 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__avatar + &__content {
|
||||
&-avatar + &__content {
|
||||
padding-top: var(--van-padding-xs);
|
||||
}
|
||||
|
||||
&__row,
|
||||
&__title {
|
||||
height: var(--van-skeleton-row-height);
|
||||
background: var(--van-skeleton-row-background);
|
||||
&-paragraph,
|
||||
&-title {
|
||||
height: var(--van-skeleton-paragraph-height);
|
||||
background: var(--van-skeleton-paragraph-background);
|
||||
}
|
||||
|
||||
&__title {
|
||||
&-title {
|
||||
width: var(--van-skeleton-title-width);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&__row {
|
||||
&-paragraph {
|
||||
&:not(:first-child) {
|
||||
margin-top: var(--van-skeleton-row-margin-top);
|
||||
margin-top: var(--van-skeleton-paragraph-margin-top);
|
||||
}
|
||||
}
|
||||
|
||||
&__title + &__row {
|
||||
&-title + &-paragraph {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
@ -59,11 +61,31 @@
|
||||
}
|
||||
|
||||
&--round {
|
||||
.van-skeleton__row,
|
||||
.van-skeleton__title {
|
||||
.van-skeleton-paragraph,
|
||||
.van-skeleton-title {
|
||||
border-radius: var(--van-radius-max);
|
||||
}
|
||||
}
|
||||
|
||||
&-image {
|
||||
display: flex;
|
||||
width: var(--van-skeleton-image-size);
|
||||
height: var(--van-skeleton-image-size);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: var(--van-active-color);
|
||||
|
||||
&--round {
|
||||
border-radius: var(--van-skeleton-image-radius);
|
||||
}
|
||||
|
||||
&__icon {
|
||||
width: calc(var(--van-skeleton-image-size) / 2);
|
||||
height: calc(var(--van-skeleton-image-size) / 2);
|
||||
font-size: calc(var(--van-skeleton-image-size) / 2);
|
||||
color: var(--van-gray-5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes van-skeleton-blink {
|
||||
|
@ -1,14 +1,47 @@
|
||||
import { withInstall } from '../utils';
|
||||
import _Skeleton from './Skeleton';
|
||||
import _SkeletonImage from './Image';
|
||||
import _SkeletonTitle from './Title';
|
||||
import _SkeletonAvatar from './Avatar';
|
||||
import _SkeletonParagraph from './Paragraph';
|
||||
|
||||
import { withInstall } from '../utils';
|
||||
|
||||
export const VanSkeletonImage = withInstall(_SkeletonImage);
|
||||
export const VanSkeletonTitle = withInstall(_SkeletonTitle);
|
||||
export const VanSkeletonAvatar = withInstall(_SkeletonAvatar);
|
||||
export const VanSkeletonParagraph = withInstall(_SkeletonParagraph);
|
||||
export const Skeleton = withInstall(_Skeleton);
|
||||
|
||||
export default Skeleton;
|
||||
|
||||
// Skeleton
|
||||
export { skeletonProps } from './Skeleton';
|
||||
export type { SkeletonProps, SkeletonAvatarShape } from './Skeleton';
|
||||
export type { SkeletonProps } from './Skeleton';
|
||||
|
||||
// SkeletonImage
|
||||
export { skeletonImageProps } from './Image';
|
||||
export type { SkeletonImageProps, SkeletonImageShape } from './Image';
|
||||
|
||||
// SkeletonAvatar
|
||||
export { skeletonAvatarProps } from './Avatar';
|
||||
export type { SkeletonAvatarProps, SkeletonAvatarShape } from './Avatar';
|
||||
|
||||
// SkeletonParagraph
|
||||
export { skeletonParagraphProps } from './Paragraph';
|
||||
export type { SkeletonParagraphProps } from './Paragraph';
|
||||
|
||||
// SkeletonTitle
|
||||
export { skeletonTitleProps } from './Title';
|
||||
export type { SkeletonTitleProps } from './Title';
|
||||
|
||||
export type { SkeletonThemeVars } from './types';
|
||||
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
VanSkeleton: typeof Skeleton;
|
||||
VanSkeletonImage: typeof VanSkeletonImage;
|
||||
VanSkeletonTitle: typeof VanSkeletonTitle;
|
||||
VanSkeletonAvatar: typeof VanSkeletonAvatar;
|
||||
VanSkeletonParagraph: typeof VanSkeletonParagraph;
|
||||
}
|
||||
}
|
||||
|
@ -4,17 +4,17 @@ exports[`should render demo and match snapshot 1`] = `
|
||||
<div>
|
||||
<div class="van-skeleton van-skeleton--animate">
|
||||
<div class="van-skeleton__content">
|
||||
<h3 class="van-skeleton__title">
|
||||
<h3 class="van-skeleton-title">
|
||||
</h3>
|
||||
<div class="van-skeleton__row"
|
||||
<div class="van-skeleton-paragraph"
|
||||
style="width: 100%;"
|
||||
>
|
||||
</div>
|
||||
<div class="van-skeleton__row"
|
||||
<div class="van-skeleton-paragraph"
|
||||
style="width: 100%;"
|
||||
>
|
||||
</div>
|
||||
<div class="van-skeleton__row"
|
||||
<div class="van-skeleton-paragraph"
|
||||
style="width: 60%;"
|
||||
>
|
||||
</div>
|
||||
@ -23,20 +23,20 @@ exports[`should render demo and match snapshot 1`] = `
|
||||
</div>
|
||||
<div>
|
||||
<div class="van-skeleton van-skeleton--animate">
|
||||
<div class="van-skeleton__avatar van-skeleton__avatar--round">
|
||||
<div class="van-skeleton-avatar van-skeleton-avatar--round">
|
||||
</div>
|
||||
<div class="van-skeleton__content">
|
||||
<h3 class="van-skeleton__title">
|
||||
<h3 class="van-skeleton-title">
|
||||
</h3>
|
||||
<div class="van-skeleton__row"
|
||||
<div class="van-skeleton-paragraph"
|
||||
style="width: 100%;"
|
||||
>
|
||||
</div>
|
||||
<div class="van-skeleton__row"
|
||||
<div class="van-skeleton-paragraph"
|
||||
style="width: 100%;"
|
||||
>
|
||||
</div>
|
||||
<div class="van-skeleton__row"
|
||||
<div class="van-skeleton-paragraph"
|
||||
style="width: 60%;"
|
||||
>
|
||||
</div>
|
||||
@ -53,24 +53,52 @@ exports[`should render demo and match snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div class="van-skeleton van-skeleton--animate">
|
||||
<div class="van-skeleton__avatar van-skeleton__avatar--round">
|
||||
<div class="van-skeleton-avatar van-skeleton-avatar--round">
|
||||
</div>
|
||||
<div class="van-skeleton__content">
|
||||
<h3 class="van-skeleton__title">
|
||||
<h3 class="van-skeleton-title">
|
||||
</h3>
|
||||
<div class="van-skeleton__row"
|
||||
<div class="van-skeleton-paragraph"
|
||||
style="width: 100%;"
|
||||
>
|
||||
</div>
|
||||
<div class="van-skeleton__row"
|
||||
<div class="van-skeleton-paragraph"
|
||||
style="width: 100%;"
|
||||
>
|
||||
</div>
|
||||
<div class="van-skeleton__row"
|
||||
<div class="van-skeleton-paragraph"
|
||||
style="width: 60%;"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="van-skeleton van-skeleton--animate">
|
||||
<div class="template-slot">
|
||||
<div class="van-skeleton-image van-skeleton-image--square">
|
||||
<i class="van-badge__wrapper van-icon van-icon-photo van-skeleton-image__icon">
|
||||
</i>
|
||||
</div>
|
||||
<div style="flex: 1;">
|
||||
<div class="van-skeleton-paragraph"
|
||||
style="width: 60%;"
|
||||
>
|
||||
</div>
|
||||
<div class="van-skeleton-paragraph"
|
||||
style="width: 100%;"
|
||||
>
|
||||
</div>
|
||||
<div class="van-skeleton-paragraph"
|
||||
style="width: 100%;"
|
||||
>
|
||||
</div>
|
||||
<div class="van-skeleton-paragraph"
|
||||
style="width: 100%;"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -1,7 +1,13 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`should Skeleton works with template slots 1`] = `
|
||||
<div class="van-skeleton van-skeleton--animate">
|
||||
custom content
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`should change avatar shape when using avatar-shape prop 1`] = `
|
||||
<div class="van-skeleton__avatar van-skeleton__avatar--square">
|
||||
<div class="van-skeleton-avatar van-skeleton-avatar--square">
|
||||
</div>
|
||||
`;
|
||||
|
||||
@ -18,20 +24,29 @@ exports[`should render default slot when loading is false 1`] = `
|
||||
exports[`should render with row width array correctly 1`] = `
|
||||
<div class="van-skeleton van-skeleton--animate">
|
||||
<div class="van-skeleton__content">
|
||||
<div class="van-skeleton__row"
|
||||
<div class="van-skeleton-paragraph"
|
||||
style="width: 100%;"
|
||||
>
|
||||
</div>
|
||||
<div class="van-skeleton__row"
|
||||
<div class="van-skeleton-paragraph"
|
||||
style="width: 30px;"
|
||||
>
|
||||
</div>
|
||||
<div class="van-skeleton__row"
|
||||
<div class="van-skeleton-paragraph"
|
||||
style="width: 5rem;"
|
||||
>
|
||||
</div>
|
||||
<div class="van-skeleton__row">
|
||||
<div class="van-skeleton-paragraph"
|
||||
style="width: 100%;"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`should skeleton image render correctly 1`] = `
|
||||
<div class="van-skeleton-image van-skeleton-image--square">
|
||||
<i class="van-badge__wrapper van-icon van-icon-photo van-skeleton-image__icon">
|
||||
</i>
|
||||
</div>
|
||||
`;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { mount } from '../../../test';
|
||||
import { Skeleton } from '..';
|
||||
import { Skeleton, VanSkeletonImage } from '..';
|
||||
|
||||
test('should render with row width array correctly', () => {
|
||||
const wrapper = mount(Skeleton, {
|
||||
@ -30,7 +30,7 @@ test('should change avatar size when using avatar-size prop', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const avatar = wrapper.find('.van-skeleton__avatar');
|
||||
const avatar = wrapper.find('.van-skeleton-avatar');
|
||||
expect(avatar.style.width).toMatchSnapshot('20rem');
|
||||
expect(avatar.style.height).toMatchSnapshot('20ren');
|
||||
});
|
||||
@ -42,7 +42,7 @@ test('should change avatar shape when using avatar-shape prop', () => {
|
||||
avatarShape: 'square',
|
||||
},
|
||||
});
|
||||
expect(wrapper.find('.van-skeleton__avatar').html()).toMatchSnapshot();
|
||||
expect(wrapper.find('.van-skeleton-avatar').html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should be round when using round prop', () => {
|
||||
@ -56,6 +56,16 @@ test('should be round when using round prop', () => {
|
||||
expect(wrapper.find('.van-skeleton--round').exists()).toBeTruthy();
|
||||
});
|
||||
|
||||
test('should Skeleton works with template slots', () => {
|
||||
const wrapper = mount(Skeleton, {
|
||||
slots: {
|
||||
template: () => 'custom content',
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should allow to disable animation', async () => {
|
||||
const wrapper = mount(Skeleton, {
|
||||
props: {
|
||||
@ -68,3 +78,31 @@ test('should allow to disable animation', async () => {
|
||||
await wrapper.setProps({ animate: false });
|
||||
expect(wrapper.find('.van-skeleton--animate').exists()).toBeFalsy();
|
||||
});
|
||||
|
||||
test('should skeleton image render correctly', () => {
|
||||
const wrapper = mount(VanSkeletonImage);
|
||||
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should skeleton image works with imageSize prop', () => {
|
||||
const wrapper = mount(VanSkeletonImage, {
|
||||
props: {
|
||||
imageSize: '20rem',
|
||||
},
|
||||
});
|
||||
const dom = wrapper.find('.van-skeleton-image');
|
||||
|
||||
expect(dom.style.width).toBe('20rem');
|
||||
expect(dom.style.height).toBe('20rem');
|
||||
});
|
||||
|
||||
test('should skeleton image worsk with imageShape prop', () => {
|
||||
const wrapper = mount(VanSkeletonImage, {
|
||||
props: {
|
||||
imageShape: 'round',
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.find('.van-skeleton-image--round')).toBeTruthy();
|
||||
});
|
||||
|
@ -1,9 +1,11 @@
|
||||
export type SkeletonThemeVars = {
|
||||
skeletonRowHeight?: string;
|
||||
skeletonRowBackground?: string;
|
||||
skeletonRowMarginTop?: string;
|
||||
skeletonParagraphHeight?: string;
|
||||
skeletonParagraphBackground?: string;
|
||||
skeletonParagraphMarginTop?: string;
|
||||
skeletonTitleWidth?: string;
|
||||
skeletonAvatarSize?: string;
|
||||
skeletonAvatarBackground?: string;
|
||||
SkeletonImageSize?: string;
|
||||
SkeletonImageRadius?: string;
|
||||
skeletonDuration?: string;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user