@fiscozen/icons 0.1.38 → 1.0.0
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/CHANGELOG.md +14 -0
- package/README.md +29 -3
- package/dist/icons.js +702 -684
- package/dist/icons.umd.cjs +1 -1
- package/dist/src/FzIconBackground.vue.d.ts +33 -0
- package/dist/src/__tests__/FzIconBackground.spec.d.ts +1 -0
- package/dist/src/index.d.ts +3 -2
- package/dist/src/types.d.ts +4 -1
- package/package.json +3 -3
- package/src/FzIcon.vue +18 -7
- package/src/FzIconBackground.vue +25 -0
- package/src/__tests__/FzIcon.spec.ts +12 -11
- package/src/__tests__/FzIconBackground.spec.ts +380 -0
- package/src/__tests__/__snapshots__/FzIcon.spec.ts.snap +5 -5
- package/src/__tests__/__snapshots__/FzIconBackground.spec.ts.snap +13 -0
- package/src/index.ts +4 -2
- package/src/types.ts +5 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { IconBackgroundProps } from './types';
|
|
2
|
+
|
|
3
|
+
declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<IconBackgroundProps>, {
|
|
4
|
+
size: string;
|
|
5
|
+
variant: string;
|
|
6
|
+
backgroundColor: string;
|
|
7
|
+
}>>, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<IconBackgroundProps>, {
|
|
8
|
+
size: string;
|
|
9
|
+
variant: string;
|
|
10
|
+
backgroundColor: string;
|
|
11
|
+
}>>> & Readonly<{}>, {
|
|
12
|
+
size: import('./types').IconSize;
|
|
13
|
+
variant: import('./types').IconVariant;
|
|
14
|
+
backgroundColor: string;
|
|
15
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
|
|
16
|
+
export default _default;
|
|
17
|
+
type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
|
|
18
|
+
type __VLS_TypePropsToRuntimeProps<T> = {
|
|
19
|
+
[K in keyof T]-?: {} extends Pick<T, K> ? {
|
|
20
|
+
type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
|
|
21
|
+
} : {
|
|
22
|
+
type: import('vue').PropType<T[K]>;
|
|
23
|
+
required: true;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
type __VLS_WithDefaults<P, D> = {
|
|
27
|
+
[K in keyof Pick<P, keyof P>]: K extends keyof D ? __VLS_Prettify<P[K] & {
|
|
28
|
+
default: D[K];
|
|
29
|
+
}> : P[K];
|
|
30
|
+
};
|
|
31
|
+
type __VLS_Prettify<T> = {
|
|
32
|
+
[K in keyof T]: T[K];
|
|
33
|
+
} & {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Plugin } from 'vue';
|
|
2
2
|
import { default as FzIcon } from './FzIcon.vue';
|
|
3
|
+
import { default as FzIconBackground } from './FzIconBackground.vue';
|
|
3
4
|
|
|
4
5
|
declare const IconPlugin: Plugin;
|
|
5
|
-
export { FzIcon, IconPlugin };
|
|
6
|
-
export type { IconVariant, IconSize, IconProps } from './types';
|
|
6
|
+
export { FzIcon, FzIconBackground, IconPlugin };
|
|
7
|
+
export type { IconVariant, IconSize, IconProps, IconBackgroundProps } from './types';
|
package/dist/src/types.d.ts
CHANGED
|
@@ -6,4 +6,7 @@ interface IconProps {
|
|
|
6
6
|
variant?: IconVariant;
|
|
7
7
|
spin?: boolean;
|
|
8
8
|
}
|
|
9
|
-
|
|
9
|
+
interface IconBackgroundProps extends IconProps {
|
|
10
|
+
backgroundColor?: string;
|
|
11
|
+
}
|
|
12
|
+
export type { IconVariant, IconSize, IconProps, IconBackgroundProps };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fiscozen/icons",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Design system icon plugin and component",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"vitest": "^1.2.0",
|
|
28
28
|
"vue-tsc": "^1.8.25",
|
|
29
29
|
"@fiscozen/eslint-config": "^0.1.0",
|
|
30
|
-
"@fiscozen/
|
|
31
|
-
"@fiscozen/
|
|
30
|
+
"@fiscozen/tsconfig": "^0.1.0",
|
|
31
|
+
"@fiscozen/prettier-config": "^0.1.0"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@awesome.me/kit-8137893ad3": "^1.0.401",
|
package/src/FzIcon.vue
CHANGED
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* FzIcon – Design system icon component (Font Awesome).
|
|
4
|
+
*
|
|
5
|
+
* Renders a single icon with configurable size and variant. The root element is a
|
|
6
|
+
* <span role="presentation"> so that v-color can be applied (e.g. <FzIcon v-color:blue="500" />)
|
|
7
|
+
* and the icon can be nested inside <p> or <span> without invalid HTML. role="presentation"
|
|
8
|
+
* removes semantics for accessibility.
|
|
9
|
+
*
|
|
10
|
+
* @component
|
|
11
|
+
* @example
|
|
12
|
+
* <FzIcon name="check" />
|
|
13
|
+
* <p v-color:blue>Ciao <FzIcon name="check" v-color:yellow /></p>
|
|
14
|
+
*/
|
|
2
15
|
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
|
3
16
|
import { byPrefixAndName } from '@awesome.me/kit-8137893ad3/icons'
|
|
4
17
|
import type { IconProps, IconSize } from './types'
|
|
5
18
|
|
|
6
|
-
withDefaults(
|
|
7
|
-
|
|
8
|
-
{ size: 'lg', variant: 'far' }
|
|
9
|
-
)
|
|
19
|
+
withDefaults(defineProps<IconProps>(), { size: 'lg', variant: 'far' })
|
|
20
|
+
|
|
10
21
|
const staticContainerClasses = ['flex', 'items-center', 'justify-center']
|
|
11
22
|
const containerClassSizeMap: Record<IconSize, string> = {
|
|
12
23
|
xs: 'size-[12.5px]',
|
|
@@ -27,12 +38,12 @@ const iconClassSizeMap: Record<IconSize, string> = {
|
|
|
27
38
|
</script>
|
|
28
39
|
|
|
29
40
|
<template>
|
|
30
|
-
<
|
|
31
|
-
<
|
|
41
|
+
<span role="presentation" :class="[staticContainerClasses, containerClassSizeMap[size]]">
|
|
42
|
+
<FontAwesomeIcon
|
|
32
43
|
:class="iconClassSizeMap[size]"
|
|
33
44
|
:icon="typeof name === 'string' ? byPrefixAndName[variant][name] : name"
|
|
34
45
|
:size="size !== 'md' ? size : undefined"
|
|
35
46
|
:spin="spin"
|
|
36
47
|
/>
|
|
37
|
-
</
|
|
48
|
+
</span>
|
|
38
49
|
</template>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import type { IconBackgroundProps } from './types'
|
|
4
|
+
import FzIcon from './FzIcon.vue'
|
|
5
|
+
|
|
6
|
+
const props = withDefaults(defineProps<IconBackgroundProps>(), {
|
|
7
|
+
size: 'lg',
|
|
8
|
+
variant: 'far',
|
|
9
|
+
backgroundColor: 'core-white'
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
const iconClasses = computed(() => {
|
|
13
|
+
return ['box-content', 'p-8', 'rounded-full', `bg-${props.backgroundColor}`]
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
/** Props passed to FzIcon; excludes backgroundColor to avoid fallthrough to DOM. */
|
|
17
|
+
const iconProps = computed(() => {
|
|
18
|
+
const { backgroundColor: _bg, ...rest } = props
|
|
19
|
+
return rest
|
|
20
|
+
})
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<template>
|
|
24
|
+
<FzIcon :class="iconClasses" v-bind="iconProps" />
|
|
25
|
+
</template>
|
|
@@ -46,7 +46,7 @@ describe('FzIcon', () => {
|
|
|
46
46
|
}
|
|
47
47
|
})
|
|
48
48
|
expect(wrapper.exists()).toBe(true)
|
|
49
|
-
expect(wrapper.find('
|
|
49
|
+
expect(wrapper.find('span').exists()).toBe(true)
|
|
50
50
|
})
|
|
51
51
|
|
|
52
52
|
it('should render with name prop', () => {
|
|
@@ -76,7 +76,7 @@ describe('FzIcon', () => {
|
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
})
|
|
79
|
-
const container = wrapper.find('
|
|
79
|
+
const container = wrapper.find('span')
|
|
80
80
|
expect(container.classes()).toContain('w-[25px]')
|
|
81
81
|
expect(container.classes()).toContain('h-[25px]')
|
|
82
82
|
})
|
|
@@ -95,7 +95,7 @@ describe('FzIcon', () => {
|
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
})
|
|
98
|
-
const container = wrapper.find('
|
|
98
|
+
const container = wrapper.find('span')
|
|
99
99
|
expect(container.classes()).toContain('custom-class')
|
|
100
100
|
})
|
|
101
101
|
})
|
|
@@ -154,7 +154,7 @@ describe('FzIcon', () => {
|
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
})
|
|
157
|
-
const container = wrapper.find('
|
|
157
|
+
const container = wrapper.find('span')
|
|
158
158
|
expect(container.classes()).toContain(containerClass)
|
|
159
159
|
|
|
160
160
|
// Verify icon class is passed via :class binding to FontAwesome component
|
|
@@ -178,7 +178,7 @@ describe('FzIcon', () => {
|
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
180
|
})
|
|
181
|
-
const container = wrapper.find('
|
|
181
|
+
const container = wrapper.find('span')
|
|
182
182
|
expect(container.classes()).toContain('w-[25px]')
|
|
183
183
|
expect(container.classes()).toContain('h-[25px]')
|
|
184
184
|
})
|
|
@@ -274,7 +274,7 @@ describe('FzIcon', () => {
|
|
|
274
274
|
}
|
|
275
275
|
}
|
|
276
276
|
})
|
|
277
|
-
const container = wrapper.find('
|
|
277
|
+
const container = wrapper.find('span')
|
|
278
278
|
expect(container.classes()).toContain('flex')
|
|
279
279
|
expect(container.classes()).toContain('items-center')
|
|
280
280
|
expect(container.classes()).toContain('justify-center')
|
|
@@ -292,7 +292,7 @@ describe('FzIcon', () => {
|
|
|
292
292
|
}
|
|
293
293
|
}
|
|
294
294
|
})
|
|
295
|
-
const container = wrapper.find('
|
|
295
|
+
const container = wrapper.find('span')
|
|
296
296
|
expect(container.classes()).toContain('w-[20px]')
|
|
297
297
|
expect(container.classes()).toContain('h-[20px]')
|
|
298
298
|
})
|
|
@@ -355,7 +355,7 @@ describe('FzIcon', () => {
|
|
|
355
355
|
}
|
|
356
356
|
}
|
|
357
357
|
})
|
|
358
|
-
const container = wrapper.find('
|
|
358
|
+
const container = wrapper.find('span')
|
|
359
359
|
expect(container.attributes('aria-label')).toBe('Notification bell')
|
|
360
360
|
})
|
|
361
361
|
|
|
@@ -374,7 +374,7 @@ describe('FzIcon', () => {
|
|
|
374
374
|
}
|
|
375
375
|
}
|
|
376
376
|
})
|
|
377
|
-
const container = wrapper.find('
|
|
377
|
+
const container = wrapper.find('span')
|
|
378
378
|
expect(container.attributes('role')).toBe('img')
|
|
379
379
|
})
|
|
380
380
|
})
|
|
@@ -391,8 +391,9 @@ describe('FzIcon', () => {
|
|
|
391
391
|
}
|
|
392
392
|
}
|
|
393
393
|
})
|
|
394
|
-
// Decorative
|
|
395
|
-
const container = wrapper.find('
|
|
394
|
+
// Decorative: root has role="presentation", no aria-label
|
|
395
|
+
const container = wrapper.find('span')
|
|
396
|
+
expect(container.attributes('role')).toBe('presentation')
|
|
396
397
|
expect(container.attributes('aria-label')).toBeUndefined()
|
|
397
398
|
})
|
|
398
399
|
})
|
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
2
|
+
import { mount } from '@vue/test-utils'
|
|
3
|
+
import FzIconBackground from '../FzIconBackground.vue'
|
|
4
|
+
|
|
5
|
+
vi.mock('@awesome.me/kit-8137893ad3/icons', () => ({
|
|
6
|
+
byPrefixAndName: {
|
|
7
|
+
fas: { bell: ['fas', 'bell'], 'user-circle': ['fas', 'user-circle'] },
|
|
8
|
+
far: { bell: ['far', 'bell'], 'user-circle': ['far', 'user-circle'] },
|
|
9
|
+
fal: { bell: ['fal', 'bell'] },
|
|
10
|
+
fat: { bell: ['fat', 'bell'] },
|
|
11
|
+
fad: { bell: ['fad', 'bell'] },
|
|
12
|
+
fass: { bell: ['fass', 'bell'] },
|
|
13
|
+
fasr: { bell: ['fasr', 'bell'] },
|
|
14
|
+
fasl: { bell: ['fasl', 'bell'] },
|
|
15
|
+
fast: { bell: ['fast', 'bell'] },
|
|
16
|
+
fak: { bell: ['fak', 'bell'] }
|
|
17
|
+
}
|
|
18
|
+
}))
|
|
19
|
+
|
|
20
|
+
const mockFontAwesomeIcon = {
|
|
21
|
+
name: 'FontAwesomeIcon',
|
|
22
|
+
template: '<svg :class="$attrs.class" data-testid="fa-icon" />',
|
|
23
|
+
props: ['icon', 'size', 'spin']
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
describe('FzIconBackground', () => {
|
|
27
|
+
beforeEach(() => {
|
|
28
|
+
vi.spyOn(console, 'warn').mockImplementation(() => {})
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const mountOptions = {
|
|
32
|
+
global: {
|
|
33
|
+
stubs: {
|
|
34
|
+
'font-awesome-icon': mockFontAwesomeIcon
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// ============================================
|
|
40
|
+
// RENDERING TESTS
|
|
41
|
+
// ============================================
|
|
42
|
+
describe('Rendering', () => {
|
|
43
|
+
it('should render with default props', () => {
|
|
44
|
+
const wrapper = mount(FzIconBackground, {
|
|
45
|
+
props: { name: 'bell' },
|
|
46
|
+
...mountOptions
|
|
47
|
+
})
|
|
48
|
+
expect(wrapper.exists()).toBe(true)
|
|
49
|
+
expect(wrapper.find('span').exists()).toBe(true)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
it('should render with name prop', () => {
|
|
53
|
+
const wrapper = mount(FzIconBackground, {
|
|
54
|
+
props: { name: 'bell' },
|
|
55
|
+
...mountOptions
|
|
56
|
+
})
|
|
57
|
+
const icon = wrapper.find('svg')
|
|
58
|
+
expect(icon.exists()).toBe(true)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it('should render correct container size', () => {
|
|
62
|
+
const wrapper = mount(FzIconBackground, {
|
|
63
|
+
props: { name: 'bell', size: 'lg' },
|
|
64
|
+
...mountOptions
|
|
65
|
+
})
|
|
66
|
+
const container = wrapper.find('span')
|
|
67
|
+
expect(container.classes()).toContain('w-[25px]')
|
|
68
|
+
expect(container.classes()).toContain('h-[25px]')
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
it('should apply custom class when provided', () => {
|
|
72
|
+
const wrapper = mount(FzIconBackground, {
|
|
73
|
+
props: { name: 'bell' },
|
|
74
|
+
attrs: { class: 'custom-class' },
|
|
75
|
+
...mountOptions
|
|
76
|
+
})
|
|
77
|
+
const container = wrapper.find('span')
|
|
78
|
+
expect(container.classes()).toContain('custom-class')
|
|
79
|
+
})
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
// ============================================
|
|
83
|
+
// PROPS TESTS
|
|
84
|
+
// ============================================
|
|
85
|
+
describe('Props', () => {
|
|
86
|
+
describe('name prop', () => {
|
|
87
|
+
it('should accept string name', () => {
|
|
88
|
+
const wrapper = mount(FzIconBackground, {
|
|
89
|
+
props: { name: 'bell' },
|
|
90
|
+
...mountOptions
|
|
91
|
+
})
|
|
92
|
+
expect(wrapper.props('name')).toBe('bell')
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
it('should accept array name', () => {
|
|
96
|
+
const wrapper = mount(FzIconBackground, {
|
|
97
|
+
props: { name: ['fas', 'bell'] },
|
|
98
|
+
...mountOptions
|
|
99
|
+
})
|
|
100
|
+
expect(wrapper.props('name')).toEqual(['fas', 'bell'])
|
|
101
|
+
})
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
describe('size prop', () => {
|
|
105
|
+
it.each([
|
|
106
|
+
['xs', 'size-[12.5px]', 'h-[10px]'],
|
|
107
|
+
['sm', 'w-[15px]', 'h-[12px]'],
|
|
108
|
+
['md', 'w-[20px]', 'h-[16px]'],
|
|
109
|
+
['lg', 'w-[25px]', 'h-[20px]'],
|
|
110
|
+
['xl', 'w-[32px]', 'h-[24px]'],
|
|
111
|
+
['2xl', 'w-[40px]', 'h-[32px]']
|
|
112
|
+
])('should apply correct classes for %s size', (size, containerClass, iconClass) => {
|
|
113
|
+
const wrapper = mount(FzIconBackground, {
|
|
114
|
+
props: { name: 'bell', size: size as 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' },
|
|
115
|
+
...mountOptions
|
|
116
|
+
})
|
|
117
|
+
const container = wrapper.find('span')
|
|
118
|
+
expect(container.classes()).toContain(containerClass)
|
|
119
|
+
const iconElement = wrapper.find('[data-testid="fa-icon"]')
|
|
120
|
+
const classAttr = iconElement.attributes('class') || ''
|
|
121
|
+
expect(classAttr.includes(iconClass) || iconElement.classes().includes(iconClass)).toBe(true)
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
it('should default to lg size', () => {
|
|
125
|
+
const wrapper = mount(FzIconBackground, {
|
|
126
|
+
props: { name: 'bell' },
|
|
127
|
+
...mountOptions
|
|
128
|
+
})
|
|
129
|
+
const container = wrapper.find('span')
|
|
130
|
+
expect(container.classes()).toContain('w-[25px]')
|
|
131
|
+
expect(container.classes()).toContain('h-[25px]')
|
|
132
|
+
})
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
describe('variant prop', () => {
|
|
136
|
+
it('should default to far variant', () => {
|
|
137
|
+
const wrapper = mount(FzIconBackground, {
|
|
138
|
+
props: { name: 'bell' },
|
|
139
|
+
...mountOptions
|
|
140
|
+
})
|
|
141
|
+
expect(wrapper.props('variant')).toBe('far')
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
it.each([['fas'], ['far'], ['fal'], ['fat'], ['fad']])(
|
|
145
|
+
'should accept %s variant',
|
|
146
|
+
(variant) => {
|
|
147
|
+
const wrapper = mount(FzIconBackground, {
|
|
148
|
+
props: { name: 'bell', variant: variant as 'fas' | 'far' | 'fal' | 'fat' | 'fad' },
|
|
149
|
+
...mountOptions
|
|
150
|
+
})
|
|
151
|
+
expect(wrapper.props('variant')).toBe(variant)
|
|
152
|
+
}
|
|
153
|
+
)
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
describe('spin prop', () => {
|
|
157
|
+
it('should not spin by default', () => {
|
|
158
|
+
const wrapper = mount(FzIconBackground, {
|
|
159
|
+
props: { name: 'bell' },
|
|
160
|
+
...mountOptions
|
|
161
|
+
})
|
|
162
|
+
const spinProp = wrapper.props('spin')
|
|
163
|
+
expect(spinProp === undefined || spinProp === false).toBe(true)
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
it('should apply spin when true', () => {
|
|
167
|
+
const wrapper = mount(FzIconBackground, {
|
|
168
|
+
props: { name: 'bell', spin: true },
|
|
169
|
+
...mountOptions
|
|
170
|
+
})
|
|
171
|
+
expect(wrapper.props('spin')).toBe(true)
|
|
172
|
+
const fontAwesomeComponent = wrapper.findComponent({ name: 'FontAwesomeIcon' })
|
|
173
|
+
expect(fontAwesomeComponent.exists()).toBe(true)
|
|
174
|
+
expect(fontAwesomeComponent.props('spin')).toBe(true)
|
|
175
|
+
})
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
describe('backgroundColor prop', () => {
|
|
179
|
+
it('should default to core-white', () => {
|
|
180
|
+
const wrapper = mount(FzIconBackground, {
|
|
181
|
+
props: { name: 'bell' },
|
|
182
|
+
...mountOptions
|
|
183
|
+
})
|
|
184
|
+
expect(wrapper.props('backgroundColor')).toBe('core-white')
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
it('should apply background class from backgroundColor', () => {
|
|
188
|
+
const wrapper = mount(FzIconBackground, {
|
|
189
|
+
props: { name: 'bell', backgroundColor: 'grey-100' },
|
|
190
|
+
...mountOptions
|
|
191
|
+
})
|
|
192
|
+
const container = wrapper.find('span')
|
|
193
|
+
expect(container.classes()).toContain('bg-grey-100')
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
it('should apply box-content, padding and rounded-full', () => {
|
|
197
|
+
const wrapper = mount(FzIconBackground, {
|
|
198
|
+
props: { name: 'bell' },
|
|
199
|
+
...mountOptions
|
|
200
|
+
})
|
|
201
|
+
const container = wrapper.find('span')
|
|
202
|
+
expect(container.classes()).toContain('box-content')
|
|
203
|
+
expect(container.classes()).toContain('p-8')
|
|
204
|
+
expect(container.classes()).toContain('rounded-full')
|
|
205
|
+
})
|
|
206
|
+
})
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
// ============================================
|
|
210
|
+
// CSS CLASSES TESTS
|
|
211
|
+
// ============================================
|
|
212
|
+
describe('CSS Classes', () => {
|
|
213
|
+
it('should apply static base classes from FzIcon', () => {
|
|
214
|
+
const wrapper = mount(FzIconBackground, {
|
|
215
|
+
props: { name: 'bell' },
|
|
216
|
+
...mountOptions
|
|
217
|
+
})
|
|
218
|
+
const container = wrapper.find('span')
|
|
219
|
+
expect(container.classes()).toContain('flex')
|
|
220
|
+
expect(container.classes()).toContain('items-center')
|
|
221
|
+
expect(container.classes()).toContain('justify-center')
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
it('should apply background wrapper classes', () => {
|
|
225
|
+
const wrapper = mount(FzIconBackground, {
|
|
226
|
+
props: { name: 'bell' },
|
|
227
|
+
...mountOptions
|
|
228
|
+
})
|
|
229
|
+
const container = wrapper.find('span')
|
|
230
|
+
expect(container.classes()).toContain('box-content')
|
|
231
|
+
expect(container.classes()).toContain('p-8')
|
|
232
|
+
expect(container.classes()).toContain('rounded-full')
|
|
233
|
+
expect(container.classes()).toContain('bg-core-white')
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
it('should apply size-specific container classes', () => {
|
|
237
|
+
const wrapper = mount(FzIconBackground, {
|
|
238
|
+
props: { name: 'bell', size: 'md' },
|
|
239
|
+
...mountOptions
|
|
240
|
+
})
|
|
241
|
+
const container = wrapper.find('span')
|
|
242
|
+
expect(container.classes()).toContain('w-[20px]')
|
|
243
|
+
expect(container.classes()).toContain('h-[20px]')
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
it('should apply size-specific icon classes', () => {
|
|
247
|
+
const wrapper = mount(FzIconBackground, {
|
|
248
|
+
props: { name: 'bell', size: 'xl' },
|
|
249
|
+
...mountOptions
|
|
250
|
+
})
|
|
251
|
+
const fontAwesomeComponent = wrapper.findComponent({ name: 'FontAwesomeIcon' })
|
|
252
|
+
expect(fontAwesomeComponent.exists()).toBe(true)
|
|
253
|
+
const icon = wrapper.find('[data-testid="fa-icon"]')
|
|
254
|
+
const classAttr = icon.attributes('class') || ''
|
|
255
|
+
expect(classAttr.includes('h-[24px]') || icon.classes().includes('h-[24px]')).toBe(true)
|
|
256
|
+
})
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
// ============================================
|
|
260
|
+
// ACCESSIBILITY TESTS
|
|
261
|
+
// ============================================
|
|
262
|
+
describe('Accessibility', () => {
|
|
263
|
+
describe('ARIA attributes', () => {
|
|
264
|
+
it('should have icon rendered for decorative use', () => {
|
|
265
|
+
const wrapper = mount(FzIconBackground, {
|
|
266
|
+
props: { name: 'bell' },
|
|
267
|
+
...mountOptions
|
|
268
|
+
})
|
|
269
|
+
const icon = wrapper.find('svg')
|
|
270
|
+
expect(icon.exists()).toBe(true)
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
it('should support aria-label when provided', () => {
|
|
274
|
+
const wrapper = mount(FzIconBackground, {
|
|
275
|
+
props: { name: 'bell' },
|
|
276
|
+
attrs: { 'aria-label': 'Notification bell' },
|
|
277
|
+
...mountOptions
|
|
278
|
+
})
|
|
279
|
+
const container = wrapper.find('span')
|
|
280
|
+
expect(container.attributes('aria-label')).toBe('Notification bell')
|
|
281
|
+
})
|
|
282
|
+
|
|
283
|
+
it('should support role="img" when accessible', () => {
|
|
284
|
+
const wrapper = mount(FzIconBackground, {
|
|
285
|
+
props: { name: 'bell' },
|
|
286
|
+
attrs: { role: 'img', 'aria-label': 'Notification bell' },
|
|
287
|
+
...mountOptions
|
|
288
|
+
})
|
|
289
|
+
const container = wrapper.find('span')
|
|
290
|
+
expect(container.attributes('role')).toBe('img')
|
|
291
|
+
})
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
describe('Decorative elements', () => {
|
|
295
|
+
it('should render icon without accessibility attributes when decorative', () => {
|
|
296
|
+
const wrapper = mount(FzIconBackground, {
|
|
297
|
+
props: { name: 'bell' },
|
|
298
|
+
...mountOptions
|
|
299
|
+
})
|
|
300
|
+
const container = wrapper.find('span')
|
|
301
|
+
expect(container.attributes('role')).toBe('presentation')
|
|
302
|
+
expect(container.attributes('aria-label')).toBeUndefined()
|
|
303
|
+
})
|
|
304
|
+
})
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
// ============================================
|
|
308
|
+
// EDGE CASES
|
|
309
|
+
// ============================================
|
|
310
|
+
describe('Edge Cases', () => {
|
|
311
|
+
it('should handle different icon name formats', () => {
|
|
312
|
+
const wrapper = mount(FzIconBackground, {
|
|
313
|
+
props: { name: 'user-circle' },
|
|
314
|
+
...mountOptions
|
|
315
|
+
})
|
|
316
|
+
expect(wrapper.exists()).toBe(true)
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
it('should handle array icon format', () => {
|
|
320
|
+
const wrapper = mount(FzIconBackground, {
|
|
321
|
+
props: { name: ['fas', 'bell'] },
|
|
322
|
+
...mountOptions
|
|
323
|
+
})
|
|
324
|
+
expect(wrapper.exists()).toBe(true)
|
|
325
|
+
})
|
|
326
|
+
})
|
|
327
|
+
|
|
328
|
+
// ============================================
|
|
329
|
+
// SNAPSHOTS
|
|
330
|
+
// ============================================
|
|
331
|
+
describe('Snapshots', () => {
|
|
332
|
+
it('should match snapshot - default state', () => {
|
|
333
|
+
const wrapper = mount(FzIconBackground, {
|
|
334
|
+
props: { name: 'bell' },
|
|
335
|
+
...mountOptions
|
|
336
|
+
})
|
|
337
|
+
expect(wrapper.html()).toMatchSnapshot()
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
it('should match snapshot - small size', () => {
|
|
341
|
+
const wrapper = mount(FzIconBackground, {
|
|
342
|
+
props: { name: 'bell', size: 'sm' },
|
|
343
|
+
...mountOptions
|
|
344
|
+
})
|
|
345
|
+
expect(wrapper.html()).toMatchSnapshot()
|
|
346
|
+
})
|
|
347
|
+
|
|
348
|
+
it('should match snapshot - large size', () => {
|
|
349
|
+
const wrapper = mount(FzIconBackground, {
|
|
350
|
+
props: { name: 'bell', size: 'xl' },
|
|
351
|
+
...mountOptions
|
|
352
|
+
})
|
|
353
|
+
expect(wrapper.html()).toMatchSnapshot()
|
|
354
|
+
})
|
|
355
|
+
|
|
356
|
+
it('should match snapshot - with spin', () => {
|
|
357
|
+
const wrapper = mount(FzIconBackground, {
|
|
358
|
+
props: { name: 'bell', spin: true },
|
|
359
|
+
...mountOptions
|
|
360
|
+
})
|
|
361
|
+
expect(wrapper.html()).toMatchSnapshot()
|
|
362
|
+
})
|
|
363
|
+
|
|
364
|
+
it('should match snapshot - with variant', () => {
|
|
365
|
+
const wrapper = mount(FzIconBackground, {
|
|
366
|
+
props: { name: 'bell', variant: 'fas' },
|
|
367
|
+
...mountOptions
|
|
368
|
+
})
|
|
369
|
+
expect(wrapper.html()).toMatchSnapshot()
|
|
370
|
+
})
|
|
371
|
+
|
|
372
|
+
it('should match snapshot - with backgroundColor', () => {
|
|
373
|
+
const wrapper = mount(FzIconBackground, {
|
|
374
|
+
props: { name: 'bell', backgroundColor: 'grey-100' },
|
|
375
|
+
...mountOptions
|
|
376
|
+
})
|
|
377
|
+
expect(wrapper.html()).toMatchSnapshot()
|
|
378
|
+
})
|
|
379
|
+
})
|
|
380
|
+
})
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
2
|
|
|
3
|
-
exports[`FzIcon > Snapshots > should match snapshot - default state 1`] = `"<
|
|
3
|
+
exports[`FzIcon > Snapshots > should match snapshot - default state 1`] = `"<span role="presentation" class="flex items-center justify-center w-[25px] h-[25px]"><svg class="h-[20px]" data-testid="fa-icon"></svg></span>"`;
|
|
4
4
|
|
|
5
|
-
exports[`FzIcon > Snapshots > should match snapshot - large size 1`] = `"<
|
|
5
|
+
exports[`FzIcon > Snapshots > should match snapshot - large size 1`] = `"<span role="presentation" class="flex items-center justify-center w-[32px] h-[32px]"><svg class="h-[24px]" data-testid="fa-icon"></svg></span>"`;
|
|
6
6
|
|
|
7
|
-
exports[`FzIcon > Snapshots > should match snapshot - small size 1`] = `"<
|
|
7
|
+
exports[`FzIcon > Snapshots > should match snapshot - small size 1`] = `"<span role="presentation" class="flex items-center justify-center w-[15px] h-[15px]"><svg class="h-[12px]" data-testid="fa-icon"></svg></span>"`;
|
|
8
8
|
|
|
9
|
-
exports[`FzIcon > Snapshots > should match snapshot - with spin 1`] = `"<
|
|
9
|
+
exports[`FzIcon > Snapshots > should match snapshot - with spin 1`] = `"<span role="presentation" class="flex items-center justify-center w-[25px] h-[25px]"><svg class="h-[20px]" data-testid="fa-icon"></svg></span>"`;
|
|
10
10
|
|
|
11
|
-
exports[`FzIcon > Snapshots > should match snapshot - with variant 1`] = `"<
|
|
11
|
+
exports[`FzIcon > Snapshots > should match snapshot - with variant 1`] = `"<span role="presentation" class="flex items-center justify-center w-[25px] h-[25px]"><svg class="h-[20px]" data-testid="fa-icon"></svg></span>"`;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`FzIconBackground > Snapshots > should match snapshot - default state 1`] = `"<span role="presentation" class="flex items-center justify-center w-[25px] h-[25px] box-content p-8 rounded-full bg-core-white"><svg class="h-[20px]" data-testid="fa-icon"></svg></span>"`;
|
|
4
|
+
|
|
5
|
+
exports[`FzIconBackground > Snapshots > should match snapshot - large size 1`] = `"<span role="presentation" class="flex items-center justify-center w-[32px] h-[32px] box-content p-8 rounded-full bg-core-white"><svg class="h-[24px]" data-testid="fa-icon"></svg></span>"`;
|
|
6
|
+
|
|
7
|
+
exports[`FzIconBackground > Snapshots > should match snapshot - small size 1`] = `"<span role="presentation" class="flex items-center justify-center w-[15px] h-[15px] box-content p-8 rounded-full bg-core-white"><svg class="h-[12px]" data-testid="fa-icon"></svg></span>"`;
|
|
8
|
+
|
|
9
|
+
exports[`FzIconBackground > Snapshots > should match snapshot - with backgroundColor 1`] = `"<span role="presentation" class="flex items-center justify-center w-[25px] h-[25px] box-content p-8 rounded-full bg-grey-100"><svg class="h-[20px]" data-testid="fa-icon"></svg></span>"`;
|
|
10
|
+
|
|
11
|
+
exports[`FzIconBackground > Snapshots > should match snapshot - with spin 1`] = `"<span role="presentation" class="flex items-center justify-center w-[25px] h-[25px] box-content p-8 rounded-full bg-core-white"><svg class="h-[20px]" data-testid="fa-icon"></svg></span>"`;
|
|
12
|
+
|
|
13
|
+
exports[`FzIconBackground > Snapshots > should match snapshot - with variant 1`] = `"<span role="presentation" class="flex items-center justify-center w-[25px] h-[25px] box-content p-8 rounded-full bg-core-white"><svg class="h-[20px]" data-testid="fa-icon"></svg></span>"`;
|
package/src/index.ts
CHANGED
|
@@ -2,15 +2,17 @@ import { Plugin } from 'vue'
|
|
|
2
2
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
|
3
3
|
import { all } from '@awesome.me/kit-8137893ad3/icons'
|
|
4
4
|
import FzIcon from './FzIcon.vue'
|
|
5
|
+
import FzIconBackground from './FzIconBackground.vue'
|
|
5
6
|
|
|
6
7
|
const IconPlugin : Plugin = {
|
|
7
8
|
install(app) {
|
|
8
9
|
// @ts-ignore
|
|
9
10
|
library.add(...all)
|
|
10
11
|
app.component('fz-icon', FzIcon)
|
|
12
|
+
app.component('fz-icon-background', FzIconBackground)
|
|
11
13
|
}
|
|
12
14
|
}
|
|
13
15
|
|
|
14
|
-
export { FzIcon, IconPlugin }
|
|
16
|
+
export { FzIcon, FzIconBackground, IconPlugin }
|
|
15
17
|
|
|
16
|
-
export type { IconVariant, IconSize, IconProps } from './types'
|
|
18
|
+
export type { IconVariant, IconSize, IconProps, IconBackgroundProps } from './types'
|