Skip to content

Commit e09c3ce

Browse files
committed
wip
1 parent 40eca53 commit e09c3ce

12 files changed

Lines changed: 876 additions & 238 deletions

docs/pages/kskeletonloader.vue

Lines changed: 406 additions & 0 deletions
Large diffs are not rendered by default.

docs/tableOfContents.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,11 @@ export default [
448448
title: 'KFocusTrap',
449449
isCode: true,
450450
}),
451+
new Page({
452+
path: '/kskeletonloader',
453+
title: 'KSkeletonLoader',
454+
isCode: true,
455+
}),
451456
],
452457
}),
453458
];
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<template>
2+
3+
<div class="wrapper">
4+
<slot></slot>
5+
</div>
6+
7+
</template>
8+
9+
10+
<script>
11+
12+
export default {
13+
name: 'SkeletonCustom',
14+
};
15+
16+
</script>
17+
18+
19+
<style lang="scss" scoped>
20+
21+
@import '../styles/definitions';
22+
23+
@keyframes loading {
24+
0% {
25+
transform: translateX(-100%);
26+
}
27+
100% {
28+
transform: translateX(100%);
29+
}
30+
}
31+
32+
.wrapper {
33+
position: relative;
34+
}
35+
36+
.wrapper::before {
37+
position: absolute;
38+
top: 0;
39+
left: 0;
40+
z-index: 1;
41+
width: 100%;
42+
height: 100%;
43+
content: '';
44+
background: linear-gradient(270deg, rgba(255, 255, 255, 0.6) 0%, rgba(255, 255, 255, 0) 100%);
45+
animation: loading 1.5s infinite ease-in-out;
46+
}
47+
48+
</style>
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<template>
2+
3+
<div class="wrapper">
4+
<div
5+
class="shape-1"
6+
:style="{ backgroundColor: $themePalette.grey.v_100 }"
7+
></div>
8+
9+
<div
10+
class="shape-2"
11+
:style="{ backgroundColor: $themePalette.grey.v_100 }"
12+
></div>
13+
14+
<div
15+
class="shape-3"
16+
:style="{ backgroundColor: $themePalette.grey.v_100 }"
17+
></div>
18+
</div>
19+
20+
</template>
21+
22+
23+
<script>
24+
25+
export default {
26+
name: 'SkeletonGeneric',
27+
};
28+
29+
</script>
30+
31+
32+
<style lang="scss" scoped>
33+
34+
@import '../styles/definitions';
35+
36+
@keyframes loading {
37+
0% {
38+
transform: translateX(-100%);
39+
}
40+
100% {
41+
transform: translateX(100%);
42+
}
43+
}
44+
45+
.shape-1,
46+
.shape-2,
47+
.shape-3 {
48+
height: 28px;
49+
margin-top: 20px;
50+
margin-bottom: 20px;
51+
border-radius: 4px;
52+
}
53+
54+
.shape-1 {
55+
width: 100%;
56+
}
57+
58+
.shape-2 {
59+
width: 90%;
60+
}
61+
62+
.shape-3 {
63+
width: 80%;
64+
}
65+
66+
.wrapper {
67+
position: relative;
68+
}
69+
70+
.wrapper::before {
71+
position: absolute;
72+
top: 0;
73+
left: 0;
74+
z-index: 1;
75+
width: 100%;
76+
height: 100%;
77+
content: '';
78+
background: linear-gradient(270deg, rgba(255, 255, 255, 0.6) 0%, rgba(255, 255, 255, 0) 100%);
79+
animation: loading 1.5s infinite ease-in-out;
80+
}
81+
82+
</style>

lib/KSkeletonLoader/index.vue

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
<template>
2+
3+
<div v-if="show">
4+
<template v-if="appearance === 'generic'">
5+
<transition name="fade" mode="out-in" appear>
6+
<SkeletonGeneric
7+
v-if="isLoading"
8+
key="loading"
9+
/>
10+
<div
11+
v-else
12+
key="loaded"
13+
>
14+
<slot></slot>
15+
</div>
16+
</transition>
17+
</template>
18+
19+
<template v-else-if="appearance === 'cardGrid'">
20+
<transition name="fade" mode="out-in" appear>
21+
<KCardGrid
22+
v-if="isLoading"
23+
key="loading"
24+
:layout="grid.layout"
25+
:layoutOverride="grid.layoutOverride"
26+
>
27+
<SkeletonCard
28+
v-for="i in grid.skeletonCount"
29+
:key="i"
30+
:height="grid.skeletonHeight"
31+
:orientation="grid.skeletonOrientation"
32+
:thumbnailDisplay="grid.skeletonThumbnailDisplay"
33+
:thumbnailAlign="grid.skeletonThumbnailAlign"
34+
/>
35+
</KCardGrid>
36+
<div
37+
v-else
38+
key="loaded"
39+
>
40+
<slot></slot>
41+
</div>
42+
</transition>
43+
</template>
44+
45+
<template v-else-if="appearance === 'custom'">
46+
<transition name="fade" mode="out-in" appear>
47+
<div
48+
v-if="isLoading"
49+
key="loading"
50+
>
51+
<SkeletonCustom>
52+
<slot name="skeleton"></slot>
53+
</SkeletonCustom>
54+
</div>
55+
<div
56+
v-else
57+
key="loaded"
58+
>
59+
60+
<slot></slot>
61+
</div>
62+
</transition>
63+
</template>
64+
</div>
65+
66+
</template>
67+
68+
69+
<script>
70+
71+
import SkeletonCard from './SkeletonCard';
72+
import SkeletonGeneric from './SkeletonGeneric';
73+
import SkeletonCustom from './SkeletonCustom';
74+
import useLoading from './useLoading';
75+
76+
export default {
77+
name: 'KSkeletonLoader',
78+
components: {
79+
SkeletonCard,
80+
SkeletonCustom,
81+
SkeletonGeneric,
82+
},
83+
setup(props) {
84+
const { show, isLoading, grid } = useLoading(props);
85+
86+
return {
87+
show,
88+
isLoading,
89+
grid,
90+
};
91+
},
92+
props: {
93+
// eslint-disable-next-line kolibri/vue-no-unused-properties
94+
loading: {
95+
type: Boolean,
96+
required: false,
97+
default: false,
98+
},
99+
// eslint-enable-next-line kolibri/vue-no-unused-properties
100+
// 'generic', 'cardGrid', 'custom'
101+
appearance: {
102+
required: false,
103+
type: String,
104+
default: 'generic',
105+
},
106+
// for grid: { `layout`, `layoutOverride`, `skeletonsConfig` }
107+
// eslint-disable-next-line kolibri/vue-no-unused-properties
108+
config: {
109+
type: Object,
110+
required: false,
111+
default: null,
112+
},
113+
// eslint-enable-next-line kolibri/vue-no-unused-properties
114+
},
115+
};
116+
117+
</script>
118+
119+
120+
<style lang="scss" scoped>
121+
122+
.fade-leave-active {
123+
transition: opacity 0.3s ease;
124+
}
125+
126+
.fade-enter-active,
127+
.fade-appear-active {
128+
transition: opacity 0.5s ease;
129+
}
130+
131+
.fade-leave-to {
132+
opacity: 0.2;
133+
}
134+
135+
.fade-enter,
136+
.fade-appear {
137+
opacity: 0;
138+
}
139+
140+
</style>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { ref, watch } from '@vue/composition-api';
2+
3+
import useGridLayout from '../cards/useGridLayout';
4+
import { getBreakpointConfig } from '../cards/utils';
5+
6+
const DEFAULT_SKELETON = {
7+
count: undefined, // default determined by the grid layout and the current breakpoint
8+
height: '200px',
9+
orientation: 'horizontal',
10+
thumbnailDisplay: 'none',
11+
thumbnailAlign: 'left',
12+
};
13+
14+
export default function useGridLoading(skeletonsConfig, layout, layoutOverride) {
15+
const { currentBreakpointConfig, windowBreakpoint } = useGridLayout(layout, layoutOverride);
16+
17+
const skeletonCount = ref(DEFAULT_SKELETON.count);
18+
const skeletonHeight = ref(DEFAULT_SKELETON.height);
19+
const skeletonOrientation = ref(DEFAULT_SKELETON.orientation);
20+
const skeletonThumbnailDisplay = ref(DEFAULT_SKELETON.thumbnailDisplay);
21+
const skeletonThumbnailAlign = ref(DEFAULT_SKELETON.thumbnailAlign);
22+
23+
// Updates the loading skeleton configuration
24+
//for the current breakpoint
25+
watch(
26+
[windowBreakpoint, skeletonsConfig, currentBreakpointConfig],
27+
([newBreakpoint]) => {
28+
skeletonCount.value = currentBreakpointConfig.value.cardsPerRow;
29+
30+
const breakpointSkeletonConfig = getBreakpointConfig(skeletonsConfig.value, newBreakpoint);
31+
if (breakpointSkeletonConfig) {
32+
if (breakpointSkeletonConfig.count) {
33+
skeletonCount.value = breakpointSkeletonConfig.count;
34+
}
35+
if (breakpointSkeletonConfig.height) {
36+
skeletonHeight.value = breakpointSkeletonConfig.height;
37+
}
38+
if (breakpointSkeletonConfig.orientation) {
39+
skeletonOrientation.value = breakpointSkeletonConfig.orientation;
40+
}
41+
if (breakpointSkeletonConfig.thumbnailDisplay) {
42+
skeletonThumbnailDisplay.value = breakpointSkeletonConfig.thumbnailDisplay;
43+
}
44+
if (breakpointSkeletonConfig.thumbnailAlign) {
45+
skeletonThumbnailAlign.value = breakpointSkeletonConfig.thumbnailAlign;
46+
}
47+
}
48+
},
49+
{ immediate: true, deep: true }
50+
);
51+
52+
return {
53+
skeletonCount,
54+
skeletonHeight,
55+
skeletonOrientation,
56+
skeletonThumbnailDisplay,
57+
skeletonThumbnailAlign,
58+
};
59+
}

0 commit comments

Comments
 (0)