@volverjs/ui-vue 0.0.5 → 0.0.6-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/components/VvAvatar/VvAvatar.es.js +279 -0
- package/dist/components/VvAvatar/VvAvatar.umd.js +1 -0
- package/dist/components/VvAvatar/VvAvatar.vue.d.ts +15 -0
- package/dist/components/VvAvatar/index.d.ts +7 -0
- package/dist/components/VvAvatarGroup/VvAvatarGroup.es.js +361 -0
- package/dist/components/VvAvatarGroup/VvAvatarGroup.umd.js +1 -0
- package/dist/components/VvAvatarGroup/VvAvatarGroup.vue.d.ts +68 -0
- package/dist/components/VvAvatarGroup/index.d.ts +38 -0
- package/dist/icons.es.js +3 -3
- package/dist/icons.umd.js +1 -1
- package/dist/stories/Avatar/Avatar.settings.d.ts +36 -0
- package/dist/stories/Avatar/Avatar.test.d.ts +2 -0
- package/dist/stories/AvatarGroup/AvatarGroup.settings.d.ts +56 -0
- package/dist/stories/AvatarGroup/AvatarGroup.test.d.ts +2 -0
- package/dist/test/expect.d.ts +3 -0
- package/package.json +17 -1
- package/src/assets/icons/detailed.json +1 -1
- package/src/assets/icons/normal.json +1 -1
- package/src/assets/icons/simple.json +1 -1
- package/src/components/VvAvatar/VvAvatar.vue +21 -0
- package/src/components/VvAvatar/index.ts +9 -0
- package/src/components/VvAvatarGroup/VvAvatarGroup.vue +65 -0
- package/src/components/VvAvatarGroup/index.ts +28 -0
- package/src/stories/Avatar/Avatar.settings.ts +36 -0
- package/src/stories/Avatar/Avatar.stories.mdx +40 -0
- package/src/stories/Avatar/Avatar.test.ts +34 -0
- package/src/stories/Avatar/AvatarBadge.stories.mdx +41 -0
- package/src/stories/Avatar/AvatarModifiers.stories.mdx +87 -0
- package/src/stories/Avatar/AvatarSlotDefault.stories.mdx +29 -0
- package/src/stories/AvatarGroup/AvatarGroup.settings.ts +60 -0
- package/src/stories/AvatarGroup/AvatarGroup.stories.mdx +30 -0
- package/src/stories/AvatarGroup/AvatarGroup.test.ts +36 -0
- package/src/stories/AvatarGroup/AvatarGroupModifiers.stories.mdx +24 -0
- package/src/stories/AvatarGroup/AvatarGroupSlotDefault.stories.mdx +45 -0
- package/src/test/expect.ts +15 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { VvAvatarProps } from '@/components/VvAvatar'
|
|
3
|
+
|
|
4
|
+
const props = defineProps(VvAvatarProps)
|
|
5
|
+
const { modifiers } = toRefs(props)
|
|
6
|
+
|
|
7
|
+
// bem css classes
|
|
8
|
+
const bemCssClasses = useModifiers('vv-avatar', modifiers)
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<template>
|
|
12
|
+
<span
|
|
13
|
+
:class="bemCssClasses"
|
|
14
|
+
:role="imgSrc ? undefined : 'img'"
|
|
15
|
+
:aria-label="imgSrc ? undefined : 'avatar'"
|
|
16
|
+
>
|
|
17
|
+
<slot name="default">
|
|
18
|
+
<img v-if="imgSrc" :src="imgSrc" alt="avatar" />
|
|
19
|
+
</slot>
|
|
20
|
+
</span>
|
|
21
|
+
</template>
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { VvAvatarGroupProps } from '@/components/VvAvatarGroup'
|
|
3
|
+
import VvAvatar from '@/components/VvAvatar/VvAvatar.vue'
|
|
4
|
+
|
|
5
|
+
const props = defineProps(VvAvatarGroupProps)
|
|
6
|
+
const { modifiers, items, toShow, totalItems, avatarModifiers } =
|
|
7
|
+
toRefs(props)
|
|
8
|
+
|
|
9
|
+
// bem css classes
|
|
10
|
+
const bemCssClasses = useModifiers('vv-avatar-group', modifiers)
|
|
11
|
+
|
|
12
|
+
const stringModifiers = computed(() => {
|
|
13
|
+
if (avatarModifiers?.value && Array.isArray(avatarModifiers?.value)) {
|
|
14
|
+
return avatarModifiers.value.join(' ')
|
|
15
|
+
}
|
|
16
|
+
return avatarModifiers?.value || ''
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
const avatarItems = computed(() => {
|
|
20
|
+
return items.value.slice(0, toShow.value).map((item, index) => {
|
|
21
|
+
let modifiers: string[] = []
|
|
22
|
+
let itemModifiers: string[] = []
|
|
23
|
+
|
|
24
|
+
if (avatarModifiers?.value) {
|
|
25
|
+
modifiers = Array.isArray(avatarModifiers?.value)
|
|
26
|
+
? avatarModifiers?.value
|
|
27
|
+
: [avatarModifiers?.value]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (item.modifiers) {
|
|
31
|
+
itemModifiers = Array.isArray(item.modifiers)
|
|
32
|
+
? item.modifiers
|
|
33
|
+
: [item.modifiers]
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
...item,
|
|
38
|
+
key: item.key || `${index}_${new Date().getTime()}`,
|
|
39
|
+
modifiers: [...modifiers, ...itemModifiers],
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<template>
|
|
46
|
+
<span :class="bemCssClasses">
|
|
47
|
+
<slot name="default">
|
|
48
|
+
<VvAvatar
|
|
49
|
+
v-for="avatarItem in avatarItems"
|
|
50
|
+
:key="avatarItem.key"
|
|
51
|
+
v-bind="{
|
|
52
|
+
modifiers: avatarItem.modifiers,
|
|
53
|
+
imgSrc: avatarItem.imgSrc,
|
|
54
|
+
}"
|
|
55
|
+
>
|
|
56
|
+
<span v-if="avatarItem.text">{{ avatarItem.text }}</span>
|
|
57
|
+
</VvAvatar>
|
|
58
|
+
<VvAvatar
|
|
59
|
+
v-if="(totalItems || items.length) > toShow"
|
|
60
|
+
:modifiers="`${stringModifiers} surface bordered`"
|
|
61
|
+
>{{ `+${(totalItems || items.length) - toShow}` }}</VvAvatar
|
|
62
|
+
>
|
|
63
|
+
</slot>
|
|
64
|
+
</span>
|
|
65
|
+
</template>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ModifiersProps } from '@/props'
|
|
2
|
+
|
|
3
|
+
export type AvatarItem = {
|
|
4
|
+
key?: string
|
|
5
|
+
text?: string
|
|
6
|
+
imgSrc?: string
|
|
7
|
+
modifiers?: string | string[]
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const VvAvatarGroupProps = {
|
|
11
|
+
...ModifiersProps,
|
|
12
|
+
/**
|
|
13
|
+
* avatar items
|
|
14
|
+
*/
|
|
15
|
+
items: {
|
|
16
|
+
type: Array<AvatarItem>,
|
|
17
|
+
default: () => [],
|
|
18
|
+
required: true,
|
|
19
|
+
},
|
|
20
|
+
toShow: {
|
|
21
|
+
type: Number,
|
|
22
|
+
default: 3,
|
|
23
|
+
},
|
|
24
|
+
totalItems: {
|
|
25
|
+
type: Number,
|
|
26
|
+
},
|
|
27
|
+
avatarModifiers: [String, Array] as PropType<string | Array<string>>,
|
|
28
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { VvAvatarProps } from '@/components/VvAvatar'
|
|
2
|
+
import { DefaultSlotArgTypes, ModifiersArgTypes } from '@/stories/argTypes'
|
|
3
|
+
|
|
4
|
+
export const defaultArgs = {
|
|
5
|
+
...propsToObject(VvAvatarProps),
|
|
6
|
+
imgSrc: 'https://i.pravatar.cc/300',
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const argTypes = {
|
|
10
|
+
...DefaultSlotArgTypes,
|
|
11
|
+
default: {
|
|
12
|
+
description: 'Content slot',
|
|
13
|
+
control: {
|
|
14
|
+
type: 'text',
|
|
15
|
+
},
|
|
16
|
+
table: {
|
|
17
|
+
category: 'Slots',
|
|
18
|
+
type: {
|
|
19
|
+
summary: 'html',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
modifiers: {
|
|
24
|
+
...ModifiersArgTypes.modifiers,
|
|
25
|
+
options: ['rounded', 'square', 'bordered', 'ring', 'lg', 'md'],
|
|
26
|
+
},
|
|
27
|
+
imgSrc: {
|
|
28
|
+
type: {
|
|
29
|
+
summary: 'string',
|
|
30
|
+
},
|
|
31
|
+
control: {
|
|
32
|
+
type: 'text',
|
|
33
|
+
},
|
|
34
|
+
description: 'The image url',
|
|
35
|
+
},
|
|
36
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Meta, Story, Canvas } from '@storybook/addon-docs'
|
|
2
|
+
import VvAvatar from '@/components/VvAvatar/VvAvatar.vue'
|
|
3
|
+
import { defaultArgs, argTypes } from './Avatar.settings'
|
|
4
|
+
import { defaultTest } from './Avatar.test'
|
|
5
|
+
|
|
6
|
+
<Meta
|
|
7
|
+
title="Components/Avatar"
|
|
8
|
+
component={VvAvatar}
|
|
9
|
+
args={defaultArgs}
|
|
10
|
+
argTypes={argTypes}
|
|
11
|
+
/>
|
|
12
|
+
|
|
13
|
+
export const Template = (args) => ({
|
|
14
|
+
components: { VvAvatar },
|
|
15
|
+
setup() {
|
|
16
|
+
return { args }
|
|
17
|
+
},
|
|
18
|
+
template: /* html */ `
|
|
19
|
+
<div class="m-md">
|
|
20
|
+
<vv-avatar v-bind="args" data-testId="element">
|
|
21
|
+
<template v-if="args.default">{{ args.default }}</template>
|
|
22
|
+
</vv-avatar>
|
|
23
|
+
</div>`,
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
<Canvas>
|
|
27
|
+
<Story name="Default" play={defaultTest}>
|
|
28
|
+
{Template.bind()}
|
|
29
|
+
</Story>
|
|
30
|
+
</Canvas>
|
|
31
|
+
|
|
32
|
+
<Canvas>
|
|
33
|
+
<Story
|
|
34
|
+
name="Image"
|
|
35
|
+
play={defaultTest}
|
|
36
|
+
args={{ imgSrc: 'https://i.pravatar.cc/300' }}
|
|
37
|
+
>
|
|
38
|
+
{Template.bind({})}
|
|
39
|
+
</Story>
|
|
40
|
+
</Canvas>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { PlayAttributes } from '@/test/types'
|
|
2
|
+
import { expect } from '@/test/expect'
|
|
3
|
+
import { within } from '@storybook/testing-library'
|
|
4
|
+
|
|
5
|
+
export async function defaultTest({ canvasElement, args }: PlayAttributes) {
|
|
6
|
+
const element = (await within(canvasElement).findByTestId(
|
|
7
|
+
'element',
|
|
8
|
+
)) as HTMLElement
|
|
9
|
+
|
|
10
|
+
// slot default
|
|
11
|
+
if (!args.default && !args.imgSrc) {
|
|
12
|
+
throw new Error('Default slot or imgSrc is required!')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const modifiers =
|
|
16
|
+
!args.modifiers || Array.isArray(args.modifiers)
|
|
17
|
+
? args.modifiers
|
|
18
|
+
: [args.modifiers]
|
|
19
|
+
|
|
20
|
+
// modifiers
|
|
21
|
+
if (modifiers) {
|
|
22
|
+
for (const modifier of modifiers) {
|
|
23
|
+
expect(element).toHaveClass(`vv-avatar--${modifier}`)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// check img tag exist
|
|
28
|
+
if (args.imgSrc && !args.default) {
|
|
29
|
+
expect(element).toHaveImgChild('img')
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// check accessibility
|
|
33
|
+
await expect(element).toHaveNoViolations()
|
|
34
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Meta, Story, Canvas } from '@storybook/addon-docs'
|
|
2
|
+
import VvAvatar from '@/components/VvAvatar/VvAvatar.vue'
|
|
3
|
+
import VvBadge from '@/components/VvBadge/VvBadge.vue'
|
|
4
|
+
import { defaultArgs, argTypes } from './Avatar.settings'
|
|
5
|
+
import { defaultTest } from './Avatar.test'
|
|
6
|
+
|
|
7
|
+
<Meta
|
|
8
|
+
title="Components/Avatar/Badge"
|
|
9
|
+
component={VvAvatar}
|
|
10
|
+
args={defaultArgs}
|
|
11
|
+
argTypes={argTypes}
|
|
12
|
+
/>
|
|
13
|
+
|
|
14
|
+
export const Template = (args) => ({
|
|
15
|
+
components: { VvAvatar, VvBadge },
|
|
16
|
+
setup() {
|
|
17
|
+
return { args }
|
|
18
|
+
},
|
|
19
|
+
template: /* html */ `
|
|
20
|
+
<div class="m-md">
|
|
21
|
+
<vv-avatar v-bind="args" data-testId="element">
|
|
22
|
+
{{ args.default }}
|
|
23
|
+
<sup>
|
|
24
|
+
<vv-badge :modifiers="['danger', 'rounded']">99+</vv-badge>
|
|
25
|
+
</sup>
|
|
26
|
+
</vv-avatar>
|
|
27
|
+
</div>`,
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
<Canvas>
|
|
31
|
+
<Story
|
|
32
|
+
name="Badge"
|
|
33
|
+
play={defaultTest}
|
|
34
|
+
args={{
|
|
35
|
+
default: 'MR',
|
|
36
|
+
modifiers: 'lg',
|
|
37
|
+
}}
|
|
38
|
+
>
|
|
39
|
+
{Template.bind()}
|
|
40
|
+
</Story>
|
|
41
|
+
</Canvas>
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Meta, Story, Canvas } from '@storybook/addon-docs'
|
|
2
|
+
import VvAvatar from '@/components/VvAvatar/VvAvatar.vue'
|
|
3
|
+
import { defaultArgs, argTypes } from './Avatar.settings'
|
|
4
|
+
import { defaultTest } from './Avatar.test'
|
|
5
|
+
import { Template } from './Avatar.stories.mdx'
|
|
6
|
+
|
|
7
|
+
<Meta
|
|
8
|
+
title="Components/Avatar/Modifiers"
|
|
9
|
+
component={VvAvatar}
|
|
10
|
+
args={defaultArgs}
|
|
11
|
+
argTypes={argTypes}
|
|
12
|
+
/>
|
|
13
|
+
|
|
14
|
+
<Canvas>
|
|
15
|
+
<Story name="Small" play={defaultTest} args={{ modifiers: '' }}>
|
|
16
|
+
{Template.bind({})}
|
|
17
|
+
</Story>
|
|
18
|
+
</Canvas>
|
|
19
|
+
|
|
20
|
+
<Canvas>
|
|
21
|
+
<Story name="Medium" play={defaultTest} args={{ modifiers: 'md' }}>
|
|
22
|
+
{Template.bind({})}
|
|
23
|
+
</Story>
|
|
24
|
+
</Canvas>
|
|
25
|
+
|
|
26
|
+
<Canvas>
|
|
27
|
+
<Story name="Large" play={defaultTest} args={{ modifiers: 'lg' }}>
|
|
28
|
+
{Template.bind({})}
|
|
29
|
+
</Story>
|
|
30
|
+
</Canvas>
|
|
31
|
+
|
|
32
|
+
<Canvas>
|
|
33
|
+
<Story
|
|
34
|
+
name="Rounded"
|
|
35
|
+
play={defaultTest}
|
|
36
|
+
args={{ modifiers: 'rounded', default: 'MR' }}
|
|
37
|
+
>
|
|
38
|
+
{Template.bind({})}
|
|
39
|
+
</Story>
|
|
40
|
+
</Canvas>
|
|
41
|
+
|
|
42
|
+
<Canvas>
|
|
43
|
+
<Story
|
|
44
|
+
name="Square"
|
|
45
|
+
play={defaultTest}
|
|
46
|
+
args={{ modifiers: ['square', 'md'] }}
|
|
47
|
+
>
|
|
48
|
+
{Template.bind({})}
|
|
49
|
+
</Story>
|
|
50
|
+
</Canvas>
|
|
51
|
+
|
|
52
|
+
<Canvas>
|
|
53
|
+
<Story
|
|
54
|
+
name="Bordered"
|
|
55
|
+
play={defaultTest}
|
|
56
|
+
args={{ modifiers: ['bordered', 'md'], default: 'MR' }}
|
|
57
|
+
>
|
|
58
|
+
{Template.bind({})}
|
|
59
|
+
</Story>
|
|
60
|
+
</Canvas>
|
|
61
|
+
|
|
62
|
+
<Canvas>
|
|
63
|
+
<Story
|
|
64
|
+
name="Ring"
|
|
65
|
+
play={defaultTest}
|
|
66
|
+
args={{ modifiers: ['ring', 'md'], default: 'MR' }}
|
|
67
|
+
>
|
|
68
|
+
{Template.bind({})}
|
|
69
|
+
</Story>
|
|
70
|
+
</Canvas>
|
|
71
|
+
|
|
72
|
+
<Canvas>
|
|
73
|
+
<Story
|
|
74
|
+
name="CustomColors"
|
|
75
|
+
play={defaultTest}
|
|
76
|
+
args={{ modifiers: ['accent', 'md'], default: 'MR' }}
|
|
77
|
+
argTypes={{
|
|
78
|
+
...argTypes,
|
|
79
|
+
modifiers: {
|
|
80
|
+
...argTypes.modifiers,
|
|
81
|
+
options: [...argTypes.modifiers.options, 'accent'],
|
|
82
|
+
},
|
|
83
|
+
}}
|
|
84
|
+
>
|
|
85
|
+
{Template.bind({})}
|
|
86
|
+
</Story>
|
|
87
|
+
</Canvas>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Meta, Story, Canvas } from '@storybook/addon-docs'
|
|
2
|
+
import VvAvatar from '@/components/VvAvatar/VvAvatar.vue'
|
|
3
|
+
import { defaultArgs, argTypes } from './Avatar.settings'
|
|
4
|
+
import { defaultTest } from './Avatar.test'
|
|
5
|
+
import { Template } from './Avatar.stories.mdx'
|
|
6
|
+
|
|
7
|
+
<Meta
|
|
8
|
+
title="Components/Avatar/Slots"
|
|
9
|
+
component={VvAvatar}
|
|
10
|
+
args={defaultArgs}
|
|
11
|
+
argTypes={argTypes}
|
|
12
|
+
/>
|
|
13
|
+
|
|
14
|
+
<Canvas>
|
|
15
|
+
<Story
|
|
16
|
+
name="Default"
|
|
17
|
+
play={defaultTest}
|
|
18
|
+
args={{ default: 'MR' }}
|
|
19
|
+
argTypes={{
|
|
20
|
+
default: {
|
|
21
|
+
control: {
|
|
22
|
+
disable: true,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
}}
|
|
26
|
+
>
|
|
27
|
+
{Template.bind({})}
|
|
28
|
+
</Story>
|
|
29
|
+
</Canvas>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { VvAvatarGroupProps } from '@/components/VvAvatarGroup'
|
|
2
|
+
import { DefaultSlotArgTypes, ModifiersArgTypes } from '@/stories/argTypes'
|
|
3
|
+
|
|
4
|
+
export const defaultArgs = {
|
|
5
|
+
...propsToObject(VvAvatarGroupProps),
|
|
6
|
+
items: [
|
|
7
|
+
{
|
|
8
|
+
text: 'MR',
|
|
9
|
+
imgSrc: 'https://i.pravatar.cc/300',
|
|
10
|
+
modifiers: 'rounded',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
imgSrc: 'https://i.pravatar.cc/300',
|
|
14
|
+
modifiers: 'rounded',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
imgSrc: 'https://i.pravatar.cc/300',
|
|
18
|
+
modifiers: 'rounded',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
imgSrc: 'https://i.pravatar.cc/300',
|
|
22
|
+
modifiers: 'rounded',
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
avatarModifiers: 'rounded',
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const argTypes = {
|
|
29
|
+
...DefaultSlotArgTypes,
|
|
30
|
+
default: {
|
|
31
|
+
description: 'Default slot',
|
|
32
|
+
control: {
|
|
33
|
+
type: 'text',
|
|
34
|
+
},
|
|
35
|
+
table: {
|
|
36
|
+
category: 'Slots',
|
|
37
|
+
type: {
|
|
38
|
+
summary: 'html',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
modifiers: {
|
|
43
|
+
...ModifiersArgTypes.modifiers,
|
|
44
|
+
options: ['tight', 'relaxed'],
|
|
45
|
+
},
|
|
46
|
+
avatarModifiers: {
|
|
47
|
+
...ModifiersArgTypes.modifiers,
|
|
48
|
+
options: ['rounded', 'square', 'bordered', 'ring', 'lg', 'md'],
|
|
49
|
+
},
|
|
50
|
+
toShow: {
|
|
51
|
+
control: {
|
|
52
|
+
type: 'number',
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
totalItems: {
|
|
56
|
+
control: {
|
|
57
|
+
type: 'number',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Meta, Story, Canvas } from '@storybook/addon-docs'
|
|
2
|
+
import VvAvatarGroup from '@/components/VvAvatarGroup/VvAvatarGroup.vue'
|
|
3
|
+
import { defaultArgs, argTypes } from './AvatarGroup.settings'
|
|
4
|
+
import { defaultTest } from './AvatarGroup.test'
|
|
5
|
+
|
|
6
|
+
<Meta
|
|
7
|
+
title="Components/AvatarGroup"
|
|
8
|
+
component={VvAvatarGroup}
|
|
9
|
+
args={defaultArgs}
|
|
10
|
+
argTypes={argTypes}
|
|
11
|
+
/>
|
|
12
|
+
|
|
13
|
+
export const Template = (args) => ({
|
|
14
|
+
components: { VvAvatarGroup },
|
|
15
|
+
setup() {
|
|
16
|
+
return { args }
|
|
17
|
+
},
|
|
18
|
+
template: /* html */ `
|
|
19
|
+
<div class="m-md">
|
|
20
|
+
<vv-avatar-group v-bind="args" data-testId="element">
|
|
21
|
+
<template v-if="args.default">{{ args.default }}</template>
|
|
22
|
+
</vv-avatar-group>
|
|
23
|
+
</div>`,
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
<Canvas>
|
|
27
|
+
<Story name="Default" play={defaultTest}>
|
|
28
|
+
{Template.bind()}
|
|
29
|
+
</Story>
|
|
30
|
+
</Canvas>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { PlayAttributes } from '@/test/types'
|
|
2
|
+
import { expect } from '@/test/expect'
|
|
3
|
+
import { within } from '@storybook/testing-library'
|
|
4
|
+
|
|
5
|
+
export async function defaultTest({ canvasElement, args }: PlayAttributes) {
|
|
6
|
+
const element = (await within(canvasElement).findByTestId(
|
|
7
|
+
'element',
|
|
8
|
+
)) as HTMLElement
|
|
9
|
+
|
|
10
|
+
// slot default
|
|
11
|
+
if (!args.default && !args.items && !args.items?.length) {
|
|
12
|
+
throw new Error('Default slot or items is required!')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const modifiers =
|
|
16
|
+
!args.modifiers || Array.isArray(args.modifiers)
|
|
17
|
+
? args.modifiers
|
|
18
|
+
: [args.modifiers]
|
|
19
|
+
|
|
20
|
+
// modifiers
|
|
21
|
+
if (modifiers) {
|
|
22
|
+
for (const modifier of modifiers) {
|
|
23
|
+
expect(element).toHaveClass(`vv-avatar-group--${modifier}`)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// check children numbers
|
|
28
|
+
if (args.items && args.items.length && !args.default) {
|
|
29
|
+
if ((args.totalItems || args.items.length) > args.toShow) {
|
|
30
|
+
expect(element.children.length).toEqual(args.toShow + 1)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// check accessibility
|
|
35
|
+
await expect(element).toHaveNoViolations()
|
|
36
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Meta, Story, Canvas } from '@storybook/addon-docs'
|
|
2
|
+
import VvAvatarGroup from '@/components/VvAvatarGroup/VvAvatarGroup.vue'
|
|
3
|
+
import { defaultArgs, argTypes } from './AvatarGroup.settings'
|
|
4
|
+
import { defaultTest } from './AvatarGroup.test'
|
|
5
|
+
import { Template } from './AvatarGroup.stories.mdx'
|
|
6
|
+
|
|
7
|
+
<Meta
|
|
8
|
+
title="Components/AvatarGroup/Modifiers"
|
|
9
|
+
component={VvAvatarGroup}
|
|
10
|
+
args={defaultArgs}
|
|
11
|
+
argTypes={argTypes}
|
|
12
|
+
/>
|
|
13
|
+
|
|
14
|
+
<Canvas>
|
|
15
|
+
<Story name="Tight" play={defaultTest} args={{ modifiers: 'tight' }}>
|
|
16
|
+
{Template.bind({})}
|
|
17
|
+
</Story>
|
|
18
|
+
</Canvas>
|
|
19
|
+
|
|
20
|
+
<Canvas>
|
|
21
|
+
<Story name="Relaxed" play={defaultTest} args={{ modifiers: 'relaxed' }}>
|
|
22
|
+
{Template.bind({})}
|
|
23
|
+
</Story>
|
|
24
|
+
</Canvas>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Meta, Story, Canvas } from '@storybook/addon-docs'
|
|
2
|
+
import VvAvatarGroup from '@/components/VvAvatarGroup/VvAvatarGroup.vue'
|
|
3
|
+
import VvAvatar from '@/components/VvAvatar/VvAvatar.vue'
|
|
4
|
+
import { defaultArgs, argTypes } from './AvatarGroup.settings'
|
|
5
|
+
import { defaultTest } from './AvatarGroup.test'
|
|
6
|
+
import { Template } from './AvatarGroup.stories.mdx'
|
|
7
|
+
|
|
8
|
+
<Meta
|
|
9
|
+
title="Components/AvatarGroup/Slots"
|
|
10
|
+
component={VvAvatarGroup}
|
|
11
|
+
args={defaultArgs}
|
|
12
|
+
argTypes={argTypes}
|
|
13
|
+
/>
|
|
14
|
+
|
|
15
|
+
export const TemplateSlot = (args) => ({
|
|
16
|
+
components: { VvAvatarGroup, VvAvatar },
|
|
17
|
+
setup() {
|
|
18
|
+
return { args }
|
|
19
|
+
},
|
|
20
|
+
template: /* html */ `
|
|
21
|
+
<div class="m-md">
|
|
22
|
+
<vv-avatar-group v-bind="args" data-testId="element" modifiers="relaxed">
|
|
23
|
+
<vv-avatar modifiers="rounded">MR</vv-avatar>
|
|
24
|
+
<vv-avatar modifiers="rounded accent">PB</vv-avatar>
|
|
25
|
+
<vv-avatar imgSrc="https://i.pravatar.cc/300" modifiers="rounded" />
|
|
26
|
+
<vv-avatar modifiers="rounded surface">+3</vv-avatar>
|
|
27
|
+
</vv-avatar-group>
|
|
28
|
+
</div>`,
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
<Canvas>
|
|
32
|
+
<Story
|
|
33
|
+
name="Default"
|
|
34
|
+
play={defaultTest}
|
|
35
|
+
argTypes={{
|
|
36
|
+
default: {
|
|
37
|
+
control: {
|
|
38
|
+
disable: true,
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
}}
|
|
42
|
+
>
|
|
43
|
+
{TemplateSlot.bind({})}
|
|
44
|
+
</Story>
|
|
45
|
+
</Canvas>
|
package/src/test/expect.ts
CHANGED
|
@@ -21,6 +21,13 @@ declare global {
|
|
|
21
21
|
expected?: HTMLElement,
|
|
22
22
|
) => CustomMatcherResult
|
|
23
23
|
}
|
|
24
|
+
// eslint-disable-next-line
|
|
25
|
+
interface Matchers<R> {
|
|
26
|
+
toHaveImgChild: (
|
|
27
|
+
imgTag: string,
|
|
28
|
+
expected?: HTMLElement,
|
|
29
|
+
) => CustomMatcherResult
|
|
30
|
+
}
|
|
24
31
|
}
|
|
25
32
|
}
|
|
26
33
|
|
|
@@ -68,6 +75,14 @@ expect.extend({
|
|
|
68
75
|
`One of these classes doesn't exist: ${classes.join(', ')}`,
|
|
69
76
|
}
|
|
70
77
|
},
|
|
78
|
+
async toHaveImgChild(element: HTMLElement, imgTag: string) {
|
|
79
|
+
const img = element.getElementsByTagName(imgTag)
|
|
80
|
+
return {
|
|
81
|
+
pass: img.length === 1,
|
|
82
|
+
message: () =>
|
|
83
|
+
`${imgTag} not exist!`,
|
|
84
|
+
}
|
|
85
|
+
},
|
|
71
86
|
})
|
|
72
87
|
|
|
73
88
|
export { expect }
|