Skip to content

Commit

Permalink
UI-395: Spinner > Improvement new variants (#374)
Browse files Browse the repository at this point in the history
  • Loading branch information
mosarabi authored Jun 20, 2024
1 parent 82ed487 commit 6257e08
Show file tree
Hide file tree
Showing 16 changed files with 255 additions and 233 deletions.
113 changes: 6 additions & 107 deletions packages/alto/src/_dev/App.vue
Original file line number Diff line number Diff line change
@@ -1,126 +1,25 @@
<script setup lang="ts">
import 'uno.css';
import '../assets/main.css';
import { ref } from 'vue';
import { Dropdown, PaginationBar, Tag } from '~/components';
import type { DropdownValue, TagItemValue } from '~/types';
const multiple = ref(null);
const single = ref(null);
const value = ref(null);
const currentPage = ref(1);
const perPage = ref(10);
const preferredLanguages = ref<TagItemValue[]>([]);
const total = 50;
const totalPages = Math.ceil(total / perPage.value);
const perPageOptions = [5, 10, 20, 30, 50, 100];
const items: Array<DropdownValue> = [
{ label: '+1 stars', key: 3, groupName: 'Rating' },
{ label: 'Visible', key: 2, groupName: 'Visibility' },
{ label: 'Hidden', key: 5, groupName: 'Visibility' },
{ label: '+3 stars', key: 4, groupName: 'Rating' },
{ label: '+4 stars', key: 1, groupName: 'Rating' },
];
const singleItems = ref<DropdownValue[]>([
{ label: 'Shoes', key: 1 },
{ label: 'Cosmetics', key: 2 },
{ label: 'Gym', key: 3 },
]);
const languages: Array<DropdownValue> = [
{ label: 'Arabic', key: 1 },
{ label: 'English', key: 2 },
{ label: 'German', key: 3 },
{ label: 'French', key: 4 },
{ label: 'Dutch', key: 5 },
{ label: 'Hindi', key: 6 },
];
function handlePaginationNavigation(pageNumber: number) {
currentPage.value = pageNumber;
}
function search(value: string) {
console.log(value);
}
import { Loader } from '~/components';
</script>

<template>
<div class="container">
<div class="row">
<div>
<span>Default Dropdown : </span>
<Dropdown v-model="value" searchable :items="languages" placeholder="Select item" />
</div>
<div>
<span>Multiple Dropdown : </span>
<Dropdown v-model="multiple" :limit="4" :items="items" searchable multiple placeholder="Select items" />
</div>
<div>
<span>Single Dropdown :</span>
<Dropdown v-model="single" :items="singleItems" placeholder="Select item" />
</div>
</div>

<div class="row">
<div>
<span>Tags : </span>
<Tag
v-model="preferredLanguages"
placeholder="Select programming languages"
:max="3"
type="dropdown"
:items="languages"
search-input-placeholder="Search..."
:search="search"
/>
</div>
</div>

<div class="row">
<div>
<PaginationBar
v-model:perPage="perPage"
:current="currentPage"
:size="totalPages"
:count="perPage"
:total="total"
:per-page-options="perPageOptions"
@update:current="handlePaginationNavigation"
/>
</div>
</div>
<Loader variant="spinner" label="Loading..." />
<Loader variant="brand" />
<Loader variant="bar" />
</div>
</template>

<style scoped>
.container {
display: flex;
flex-direction: column;
flex-direction: row;
align-items: center;
justify-content: center;
width: 100vw;
height: 100vh;
gap: 40px;
}
.container .row {
display: flex;
flex-direction: column;
gap: 300px;
width: 80%;
}
.container .row > div {
flex: 1;
}
.container .row > div span {
margin: 0;
color: var(--gray-900);
font: var(--text-sm-medium);
gap: 80px;
}
</style>
4 changes: 2 additions & 2 deletions packages/alto/src/components/Dropdown/Dropdown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { elementChildrenNavigate } from './utils';
import type { DropdownGroupValue } from './types';
import type { DropdownProps, DropdownValue } from '~/types';
import { setPosition } from '~/helpers';
import { Spinner } from '~/components';
import { Loader } from '~/components';
const props = withDefaults(defineProps<DropdownProps>(), {
multiSelectLabel: 'Selected items',
Expand Down Expand Up @@ -342,7 +342,7 @@ onClickOutside(dropdown, () => show.value = false);
{{ noDataText }}
</div>
<div v-if="isLoading" class="loading">
<Spinner :size="15" />
<Loader :size="15" />
</div>
</div>
</Transition>
Expand Down
39 changes: 39 additions & 0 deletions packages/alto/src/components/Loader/Loader.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type { Meta, StoryObj } from '@storybook/vue3';
import { Loader } from '~/components';

type Story = StoryObj<typeof Loader>;
const meta: Meta<typeof Loader> = {
title: 'Application/Loader',
component: Loader,
tags: ['loader', 'loading', 'spinner'],
argTypes: {
variant: {
control: 'select',
options: ['spinner', 'brand', 'bar'],
},
labelFontSize: {
control: 'select',
options: ['xs', 'sm', 'md', 'lg', 'xl'],
},
},
args: {
variant: 'spinner',
size: 40,
label: '',
labelFontSize: 'md',
color: 'var(--brand-500)',
labelColor: 'var(--brand-500)',
},
};

export const Default: Story = {
render: args => ({
components: { Loader },
setup() {
return { args };
},
template: '<Loader v-bind="args" />',
}),
};

export default meta;
69 changes: 69 additions & 0 deletions packages/alto/src/components/Loader/Loader.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<script setup lang="ts">
import { computed, defineAsyncComponent } from 'vue';
import type { LoaderProps } from '~/types';
const props = withDefaults(
defineProps<LoaderProps>(),
{
color: 'var(--brand-500)',
size: 40,
labelColor: 'var(--brand-500)',
labelFontSize: 'md',
variant: 'spinner',
},
);
const loader = computed (() => {
switch (props.variant) {
case 'brand':
return defineAsyncComponent(() => import('./internal/BrandLoading.vue'));
case 'bar':
return defineAsyncComponent(() => import('./internal/BarLoading.vue'));
default:
return defineAsyncComponent(() => import('./internal/Spinner.vue'));
}
});
</script>

<template>
<div class="loader-block">
<component :is="loader" :color="color" :size="size" />

<p v-if="label" class="label" :class="[labelFontSize]">
{{ label }}
</p>
</div>
</template>

<style scoped>
.loader-block {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}
.loader-block .label {
margin: 0;
color: v-bind("labelColor");
font: var(--text-md-regular);
}
.loader-block .label.xs {
font: var(--text-xs-regular);
}
.loader-block .label.sm {
font: var(--text-sm-regular);
}
.loader-block .label.lg {
font: var(--text-lg-regular);
}
.loader-block .label.xl {
font: var(--text-xl-regular);
}
</style>
Binary file not shown.
35 changes: 35 additions & 0 deletions packages/alto/src/components/Loader/internal/BarLoading.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script setup lang="ts">
import type { BarLoadingProps } from '~/types';
defineProps<BarLoadingProps>();
</script>

<template>
<div class="bar-loading" />
</template>

<style scoped>
.bar-loading {
position: relative;
width: 160px;
height: 4px;
overflow: hidden;
border-radius: 2px;
background-color: var(--gray-100);
}
.bar-loading::before {
content: "";
display: block;
width: 100%;
height: 100%;
animation: progress 1200ms ease-in-out backwards alternate infinite;
border-radius: 2px;
background-color: v-bind(color);
}
@keyframes progress {
0% { transform: translateX(-93%); }
100% { transform: translateX(93%); }
}
</style>
43 changes: 43 additions & 0 deletions packages/alto/src/components/Loader/internal/BrandLoading.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<script setup lang="ts">
import { computed } from 'vue';
import type { BrandLoadingProps } from '~/types';
const props = withDefaults(defineProps<BrandLoadingProps>(), {
size: 67,
});
const percent = 59 / 67;
const height = computed(() => `${props.size * percent}px`);
const width = computed(() => `${props.size}px`);
</script>

<template>
<svg class="animated-svg" :width="width" :height="height" viewBox="0 0 67 59" :fill="color" :stroke="color" xmlns="http://www.w3.org/2000/svg">
<path d="M32.4472 28.5835H13.1062L0.765851 0.5H20.1169L32.4472 28.5835Z" />
<path d="M33.6705 29.2951L33.6705 29.295L46.319 0.5H65.6703L53.1985 28.8927L53.1984 28.8928L40.5501 57.667H21.1989L33.6705 29.2951Z" />
</svg>
</template>

<style scoped>
.animated-svg path {
animation: draw 1500ms linear forwards infinite;
stroke-dasharray: 163.58;
fill: var(--gray-100);
}
@keyframes draw {
0% { stroke-dashoffset: 163.58; }
40%,
50% {
stroke-dashoffset: 0;
fill: var(--gray-100);
}
85%,
100% {
stroke-dashoffset: 0;
fill: v-bind(color);
}
}
</style>
31 changes: 31 additions & 0 deletions packages/alto/src/components/Loader/internal/Spinner.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<script setup lang="ts">
import { computed } from 'vue';
import type { SpinnerProps } from '~/types';
const props = defineProps<SpinnerProps>();
const spinnerSize = computed(() => `${props.size}px`);
const borderWidth = computed(() => `${props.size * 0.1}px`);
</script>

<template>
<div class="spinner" />
</template>

<style scoped>
.spinner {
box-sizing: border-box;
width: v-bind(spinnerSize);
animation: s4 1s infinite linear;
border: v-bind(borderWidth) solid var(--gray-100);
border-radius: 50%;
border-right-color: v-bind(color);
aspect-ratio: 1;
}
@keyframes s4 {
100% {
transform: rotate(1turn);
}
}
</style>
23 changes: 23 additions & 0 deletions packages/alto/src/components/Loader/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export type SpinnerVariant = 'brand' | 'bar' | 'spinner';
export type LabelSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';

interface SharedProps {
size: number
color?: string
}
export interface BarLoadingProps {
color?: string
}

export interface BrandLoadingProps extends SharedProps {}

export interface SpinnerProps extends SharedProps {}

export interface LoaderProps {
label?: string
size?: number
color?: string
labelColor?: string
labelFontSize?: LabelSize
variant?: SpinnerVariant
}
Loading

0 comments on commit 6257e08

Please sign in to comment.