Skip to content

Commit

Permalink
feat: content loader
Browse files Browse the repository at this point in the history
  • Loading branch information
kawamataryo committed Oct 11, 2024
1 parent 96fd6f2 commit ba1ca77
Show file tree
Hide file tree
Showing 3 changed files with 198 additions and 0 deletions.
53 changes: 53 additions & 0 deletions src/components/ContentLoader/ContentLoader.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import type { Meta, StoryObj } from '@storybook/vue3'
import ContentLoader from './ContentLoader.vue'

const meta: Meta<typeof ContentLoader> = {
title: 'ContentLoader',
component: ContentLoader,
argTypes: {
type: {
control: { type: 'select' },
options: ['PARAGRAPH', 'BULLET_LIST', 'CIRCLE'],
defaultValue: 'PARAGRAPH',
},
lineCount: {
control: { type: 'number' },
defaultValue: 5,
},
lineHeight: {
control: { type: 'number' },
defaultValue: 1,
},
randomLineWidth: {
control: { type: 'boolean' },
defaultValue: true,
},
gap: {
control: { type: 'number' },
defaultValue: 0.8,
},
},
render: (args) => ({
components: { ContentLoader },
setup() {
return { args }
},
template: `
<ContentLoader v-bind="args" />`,
}),
}

export default meta

type Story = StoryObj<typeof ContentLoader>

export const Default: Story = {
name: 'default',
args: {
type: 'PARAGRAPH',
lineCount: 5,
line: 1,
randomLineWidth: true,
gap: 0.8,
},
}
101 changes: 101 additions & 0 deletions src/components/ContentLoader/ContentLoader.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<template>
<div
class="content-loader"
:style="{
gap: `${gap}em`,
}"
>
<div
class="loader-group"
v-for="line in lines"
:key="line.id"
:style="{
gap: `${lineHeight / 2.5}em`,
}"
>
<div
v-if="['CIRCLE', 'BULLET_LIST'].includes(type)"
class="circle"
:style="{
width: `${lineHeight}em`,
height: `${lineHeight}em`,
}"
/>
<div
v-if="['PARAGRAPH', 'BULLET_LIST'].includes(type)"
class="line"
:style="{
maxWidth: `${line.maxWidth}%`,
height: `${lineHeight}em`,
}"
/>
</div>
</div>
</template>

<script lang="ts" setup>
import { computed } from 'vue'
defineOptions({
name: 'ContentLoader',
})
const props = withDefaults(
defineProps<{
type?: 'PARAGRAPH' | 'BULLET_LIST' | 'CIRCLE'
lineCount?: number
lineHeight?: number
randomLineWidth?: boolean
gap?: number
}>(),
{
type: 'PARAGRAPH',
lineCount: 5,
lineHeight: 1,
randomLineWidth: true,
gap: 0.8,
}
)
const lines = computed(() => {
return Array.from({ length: props.lineCount }, (_, i) => ({
id: i,
maxWidth: props.randomLineWidth ? 50 + Math.random() * 50 : 100,
}))
})
</script>

<style lang="scss" scoped>
.content-loader {
display: flex;
flex-direction: column;
}
.loader-group {
display: flex;
}
.line {
background-color: #ccc;
animation: pulse 1.5s ease-in-out infinite;
border-radius: 0.25rem;
flex-grow: 1;
}
.circle {
background-color: #ccc;
border-radius: 50%;
}
@keyframes pulse {
0% {
opacity: 1;
}
50% {
opacity: 0.5;
}
100% {
opacity: 1;
}
}
</style>
44 changes: 44 additions & 0 deletions types/components/ContentLoader/ContentLoader.vue.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
declare const _default: import("vue").DefineComponent<__VLS_WithDefaults<__VLS_TypePropsToOption<{
type?: "PARAGRAPH" | "BULLET_LIST" | "CIRCLE";
height?: number;
baseLineHeight?: number;
gap?: number;
}>, {
type: string;
height: number;
baseLineHeight: number;
gap: number;
}>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<{
type?: "PARAGRAPH" | "BULLET_LIST" | "CIRCLE";
height?: number;
baseLineHeight?: number;
gap?: number;
}>, {
type: string;
height: number;
baseLineHeight: number;
gap: number;
}>>>, {
type: "PARAGRAPH" | "BULLET_LIST" | "CIRCLE";
height: number;
gap: number;
baseLineHeight: number;
}, {}>;
export default _default;
type __VLS_WithDefaults<P, D> = {
[K in keyof Pick<P, keyof P>]: K extends keyof D ? __VLS_Prettify<P[K] & {
default: D[K];
}> : P[K];
};
type __VLS_Prettify<T> = {
[K in keyof T]: T[K];
} & {};
type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
type __VLS_TypePropsToOption<T> = {
[K in keyof T]-?: {} extends Pick<T, K> ? {
type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
} : {
type: import('vue').PropType<T[K]>;
required: true;
};
};

0 comments on commit ba1ca77

Please sign in to comment.