Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
MisRob committed Nov 22, 2024
1 parent 40eca53 commit c0d9538
Show file tree
Hide file tree
Showing 11 changed files with 467 additions and 238 deletions.
123 changes: 123 additions & 0 deletions docs/pages/kskeletonloader.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
<template>

<DocsPageTemplate apiDocs>
<DocsPageSection title="Usage" anchor="#usage">
In all the modes below, <code>KSkeletonLoader</code> provides delay and minimum loading time optimizations. What differs is only apperiance of skeletons. <code>KSkeletonLoader</code> is built to allow for experimentation and adding of new skeleton appearances easily.

<h4>Generic</h4>
<!-- eslint-disable -->
<DocsShowCode language="html">
<KSkeletonLoader
:loading="loading"
appearance="generic"
>
<p>Hi there, data is loaded!</p>
</KSkeletonLoader>
</DocsShowCode>
<!-- eslint-enable -->

<h4>Card skeletons over more sections</h4>
<p>If there are more sections on a page being loaded, in some situations it may be best to show only one skeleton grid to prevent section jumps.</p>

<!-- eslint-disable -->
<DocsShowCode language="html">
<KSkeletonLoader
:loading="loading"
:config="config"
appearance="cardGrid"
>
<h5>Section 1</h5>
<KCardGrid layout="1-2-3">
<KCard
v-for="i in 5"
...
/>
</KCardGrid>

<h5>Section 2</h5>
<KCardGrid layout="1-2-3">
<KCard
v-for="i in 5"
...
/>
</KCardGrid>
</KSkeletonLoader>
</DocsShowCode>
<!-- eslint-enable -->

<h4>Card skeletons for each section</h4>
<p>We can also show skeletons for each section individually.</p>

<!-- eslint-disable -->
<DocsShowCode language="html">
<KSkeletonLoader
:loading="loading"
:config="config"
appearance="cardGrid"
>
<h5>Section 1</h5>
<KCardGrid layout="1-2-3">
<KCard
v-for="i in 5"
...
/>
</KCardGrid>
</KSkeletonLoader>

<KSkeletonLoader
:loading="loading"
:config="config"
appearance="cardGrid"
>
<h5>Section 2</h5>
<KCardGrid layout="1-2-3">
<KCard
v-for="i in 5"
...
/>
</KCardGrid>
</KSkeletonLoader>
</DocsShowCode>
<!-- eslint-enable -->

<h4>Custom</h4>
<p>If generic or card skeletons are not suitable, it is possible to use a customized skeleton via the <code>#skeleton</code> slot. This can be used for experimentation with new skeleton elements that can later be moved to KDS as a new <code>appearance</code> mode if needed.</p>

<!-- eslint-disable -->
<DocsShowCode language="html">
<KSkeletonLoader
:loading="loading"
appearance="custom"
>
<div>TODO</div>
<template #skeleton>

</template>
</KSkeletonLoader>
</DocsShowCode>
<!-- eslint-enable -->

</DocsPageSection>
</DocsPageTemplate>

</template>


<script>
export default {
name: 'Kskeletonloader',
data: function() {
return {
config: {},
};
},
};
</script>


<style lang="scss" scoped>
</style>
5 changes: 5 additions & 0 deletions docs/tableOfContents.js
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,11 @@ export default [
title: 'KFocusTrap',
isCode: true,
}),
new Page({
path: '/kskeletonloader',
title: 'KSkeletonLoader',
isCode: true,
}),
],
}),
];
14 changes: 14 additions & 0 deletions lib/KSkeletonLoader/SkeleletonGeneric.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<template>

<div>TODO</div>

</template>


<script>
export default {
name: 'SkeletonGeneric',
};
</script>
File renamed without changes.
132 changes: 132 additions & 0 deletions lib/KSkeletonLoader/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<template>

<div v-if="show">
<template v-if="appearance === 'generic'">
<transition name="fade" mode="out-in" appear>
<SkeletonGeneric
v-if="isLoading"
key="loading"
/>
<div
v-else
key="loaded"
>
<slot></slot>
</div>
</transition>
</template>

<template v-else-if="appearance === 'cardGrid'">
<transition name="fade" mode="out-in" appear>
<KCardGrid
v-if="isLoading"
key="loading"
:layout="grid.layout"
:layoutOverride="grid.layoutOverride"
>
<SkeletonCard
v-for="i in grid.skeletonCount"
:key="i"
:height="grid.skeletonHeight"
:orientation="grid.skeletonOrientation"
:thumbnailDisplay="grid.skeletonThumbnailDisplay"
:thumbnailAlign="grid.skeletonThumbnailAlign"
/>
</KCardGrid>
<div
v-else
key="loaded"
>
<slot></slot>
</div>
</transition>
</template>

<template v-else-if="appearance === 'custom'">
<template v-if="appearance === 'generic'">
<div
v-if="isLoading"
key="loading"
>
<slot name="skeleton"></slot>
</div>
<div
v-else
key="loaded"
>
<slot></slot>
</div>
</template>
</template>
</div>

</template>


<script>
import SkeletonCard from './SkeletonCard';
import useLoading from './useLoading';
export default {
name: 'KSkeletonLoader',
components: {
SkeletonCard,
},
setup(props) {
const { show, isLoading, grid } = useLoading(props);
return {
show,
isLoading,
grid,
};
},
props: {
// eslint-disable-next-line kolibri/vue-no-unused-properties
loading: {
type: Boolean,
required: false,
default: false,
},
// eslint-enable-next-line kolibri/vue-no-unused-properties
// 'generic', 'cardGrid', 'custom'
appearance: {
required: false,
type: String,
default: 'generic',
},
// for grid: { `layout`, `layoutOverride`, `skeletonsConfig` }
// eslint-disable-next-line kolibri/vue-no-unused-properties
config: {
type: Array,
required: false,
default: null,
},
// eslint-enable-next-line kolibri/vue-no-unused-properties
},
};
</script>


<style lang="scss" scoped>
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-active,
.fade-appear-active {
transition: opacity 0.5s ease;
}
.fade-leave-to {
opacity: 0.2;
}
.fade-enter,
.fade-appear {
opacity: 0;
}
</style>
59 changes: 59 additions & 0 deletions lib/KSkeletonLoader/useGridLoading.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { ref, watch } from '@vue/composition-api';

import useGridLayout from '../cards/useGridLayout';
import { getBreakpointConfig } from '../cards/utils';

const DEFAULT_SKELETON = {
count: undefined, // default determined by the grid layout and the current breakpoint
height: '200px',
orientation: 'horizontal',
thumbnailDisplay: 'none',
thumbnailAlign: 'left',
};

export default function useGridLoading(skeletonsConfig, layout, layoutOverride) {
const { currentBreakpointConfig, windowBreakpoint } = useGridLayout(layout, layoutOverride);

const skeletonCount = ref(DEFAULT_SKELETON.count);
const skeletonHeight = ref(DEFAULT_SKELETON.height);
const skeletonOrientation = ref(DEFAULT_SKELETON.orientation);
const skeletonThumbnailDisplay = ref(DEFAULT_SKELETON.thumbnailDisplay);
const skeletonThumbnailAlign = ref(DEFAULT_SKELETON.thumbnailAlign);

// Updates the loading skeleton configuration
//for the current breakpoint
watch(
[windowBreakpoint, skeletonsConfig, currentBreakpointConfig],
([newBreakpoint]) => {
skeletonCount.value = currentBreakpointConfig.value.cardsPerRow;

const breakpointSkeletonConfig = getBreakpointConfig(skeletonsConfig.value, newBreakpoint);
if (breakpointSkeletonConfig) {
if (breakpointSkeletonConfig.count) {
skeletonCount.value = breakpointSkeletonConfig.count;
}
if (breakpointSkeletonConfig.height) {
skeletonHeight.value = breakpointSkeletonConfig.height;
}
if (breakpointSkeletonConfig.orientation) {
skeletonOrientation.value = breakpointSkeletonConfig.orientation;
}
if (breakpointSkeletonConfig.thumbnailDisplay) {
skeletonThumbnailDisplay.value = breakpointSkeletonConfig.thumbnailDisplay;
}
if (breakpointSkeletonConfig.thumbnailAlign) {
skeletonThumbnailAlign.value = breakpointSkeletonConfig.thumbnailAlign;
}
}
},
{ immediate: true, deep: true }
);

return {
skeletonCount,
skeletonHeight,
skeletonOrientation,
skeletonThumbnailDisplay,
skeletonThumbnailAlign,
};
}
Loading

0 comments on commit c0d9538

Please sign in to comment.