Skip to content

Commit

Permalink
Merge pull request #402 from PrestaShopCorp/332-feature-button-add-sp…
Browse files Browse the repository at this point in the history
…inner

332 feature button add spinner
  • Loading branch information
mattgoud authored Jan 14, 2025
2 parents a71de42 + d2dd254 commit ba8b01f
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 4 deletions.
6 changes: 6 additions & 0 deletions packages/components/button/src/button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ export enum PuikButtonSizes {
Medium = 'md',
Large = 'lg',
}
export enum PuikButtonLoaderPositions {
Left = 'left',
Right = 'right'
}

export interface ButtonProps {
variant?: PuikButtonVariants | `${PuikButtonVariants}`
Expand All @@ -32,6 +36,8 @@ export interface ButtonProps {
disabledReason?: string
leftIcon?: string
rightIcon?: string
loading?: boolean
loaderPosition?: `${PuikButtonLoaderPositions}`
to?: RouteLocationRaw
href?: string
value?: string | number | Record<string, any> | any[]
Expand Down
30 changes: 27 additions & 3 deletions packages/components/button/src/button.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@
:data-test="dataTest"
@click="setSelected"
>
<puik-spinner-loader
v-if="props.loading && props.loaderPosition === PuikButtonLoaderPositions.Left"
:size="props.size"
:color="loaderColor"
class="puik-button__loader puik-button__loader--left"
:data-test="dataTest != undefined ? `leftLoader-${dataTest}` : undefined"
/>
<puik-icon
v-if="leftIcon"
:icon="leftIcon"
Expand All @@ -37,6 +44,13 @@
:aria-hidden="true"
:data-test="dataTest != undefined ? `rightIcon-${dataTest}` : undefined"
/>
<puik-spinner-loader
v-if="props.loading && props.loaderPosition === PuikButtonLoaderPositions.Right"
:size="props.size"
:color="loaderColor"
class="puik-button__loader puik-button__loader--right"
:data-test="dataTest != undefined ? `rightLoader-${dataTest}` : undefined"
/>
<span
v-if="disabled"
:id="disabledId"
Expand All @@ -51,16 +65,18 @@
import { computed, inject } from 'vue';
import { useLocale } from '@prestashopcorp/puik-locale';
import { generateId } from '@prestashopcorp/puik-utils';
import { PuikIcon } from '@prestashopcorp/puik-components/icon';
import { PuikIcon, PuikSpinnerLoader } from '@prestashopcorp/puik-components';
import { ButtonGroupKey } from '../../button-group';
import { PuikButtonVariants, type ButtonProps, PuikButtonSizes } from './button';
import { PuikButtonVariants, PuikButtonLoaderPositions, type ButtonProps, PuikButtonSizes } from './button';
defineOptions({
name: 'PuikButton'
});
const props = withDefaults(defineProps<ButtonProps>(), {
variant: PuikButtonVariants.Primary,
size: PuikButtonSizes.Medium
size: PuikButtonSizes.Medium,
loading: false,
loaderPosition: PuikButtonLoaderPositions.Right
});
const { t } = useLocale();
Expand All @@ -86,10 +102,18 @@ const setSelected = () => {
buttonGroup.selected.value = props.value;
}
};
const loaderColor = computed(() => {
if (props.variant === 'primary' || props.variant === 'secondary-reverse' || props.variant === 'text-reverse' || props.variant === 'destructive' || props.disabled) {
return 'reverse';
}
return 'primary';
});
</script>

<style lang="scss">
@use '@prestashopcorp/puik-theme/src/base.scss';
@use '@prestashopcorp/puik-theme/src/puik-button.scss';
@use '@prestashopcorp/puik-theme/src/puik-icon.scss';
@use '@prestashopcorp/puik-theme/src/puik-spinner-loader.scss';
</style>
78 changes: 77 additions & 1 deletion packages/components/button/stories/button.stories.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { PuikButton, PuikButtonVariants, PuikButtonSizes } from '@prestashopcorp/puik-components';
import { PuikButton, PuikButtonVariants, PuikButtonSizes, PuikButtonLoaderPositions } from '@prestashopcorp/puik-components';
import type { StoryObj, Meta, StoryFn, Args } from '@storybook/vue3';

const buttonVariants = Object.values(PuikButtonVariants);
const buttonVariantsSummary = buttonVariants.join('|');
const buttonSizes = Object.values(PuikButtonSizes);
const buttonSizesSummary = buttonSizes.join('|');
const buttonLoaderPositions = Object.values(PuikButtonLoaderPositions);
const buttonLoaderPositionsSummary = buttonLoaderPositions.join('|');

export default {
title: 'Components/Button',
Expand Down Expand Up @@ -66,6 +68,31 @@ export default {
rightIcon: {
description: 'Sets the button right icon'
},
loading: {
control: 'boolean',
description: 'Sets the loading state of the button',
table: {
defaultValue: {
summary: false
},
type: {
summary: 'boolean'
}
}
},
loaderPosition: {
control: 'select',
description: 'Sets the loading position of the button',
options: buttonLoaderPositions,
table: {
defaultValue: {
summary: 'right'
},
type: {
summary: buttonLoaderPositionsSummary
}
}
},
default: {
control: 'text',
description: 'Label/Content of the button'
Expand Down Expand Up @@ -109,6 +136,8 @@ export default {
disabledReason: 'Reason not specified',
leftIcon: '',
rightIcon: '',
loading: false,
loaderPosition: PuikButtonLoaderPositions.Right,
to: undefined,
href: undefined,
default: 'Add to cart'
Expand Down Expand Up @@ -238,6 +267,53 @@ const AllReversedVariantsTemplate: StoryFn = (args: Args, storyContext) => ({
`
});

const LoadingTemplate: StoryFn = (args: Args, storyContext) => ({
components: { PuikButton },
args: {
loading: true
},
setup() {
const loaderPositions = storyContext.argTypes.loaderPosition.options;
console.log(storyContext.argTypes.loaderPosition.options);
return {
args,
loaderPositions
};
},
template: `
<div class="flex flex-row flex-wrap items-center gap-4">
<template v-for="(position, i) in loaderPositions" :key="i">
<puik-button loading :loaderPosition="position">
Loading ...
</puik-button>
</template>
</div>
`
});

export const LoadingState: StoryObj = {
render: LoadingTemplate,

parameters: {
docs: {
source: {
code: `
<!--VueJS Snippet -->
<puik-button loading loaderPosition="left">
Loading ...
</puik-button>
<puik-button loading loaderPosition="right">
Loading ...
</puik-button>
`,
language: 'html'
}
}
}
};

export const Primary: StoryObj = {
render: ButtonTemplate,

Expand Down
1 change: 1 addition & 0 deletions packages/components/button/style/css.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import '@prestashopcorp/puik-components/base/style/css';
import '@prestashopcorp/puik-theme/puik-button.css';
import '@prestashopcorp/puik-theme/puik-icon.css';
import '@prestashopcorp/puik-theme/puik-spinner-loader.css';
1 change: 1 addition & 0 deletions packages/components/button/style/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import '@prestashopcorp/puik-components/base/style';
import '@prestashopcorp/puik-theme/src/puik-button.scss';
import '@prestashopcorp/puik-theme/src/puik-icon.scss';
import '@prestashopcorp/puik-theme/src/puik-spinner-loader.scss';
36 changes: 36 additions & 0 deletions packages/components/button/test/button.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ describe('Button tests', () => {
const findButton = () => wrapper.find('.puik-button');
const findButtonLeftIcon = () => wrapper.find('.puik-button__left-icon');
const findButtonRightIcon = () => wrapper.find('.puik-button__right-icon');
const findLoader = () => wrapper.find('.puik-button__loader');
const findLeftLoader = () => wrapper.find('.puik-button__loader--left');
const findRightLoader = () => wrapper.find('.puik-button__loader--right');

const disabledId = 'puik-button-disabled-mocked-id';

Expand Down Expand Up @@ -142,4 +145,37 @@ describe('Button tests', () => {
factory();
expect(findButton().attributes('role')).toBe('button');
});

it('should display loader when loading is true', () => {
factory({ loading: true });
expect(findLoader().exists()).toBeTruthy();
});

it('should display loader on the left when loaderPosition is left', () => {
factory({ loading: true, loaderPosition: 'left' });
expect(findLoader().exists()).toBeTruthy();
expect(findLoader().classes()).toContain('puik-button__loader--left');
});

it('should display loader on the right when loaderPosition is right', () => {
factory({ loading: true, loaderPosition: 'right' });
expect(findLoader().exists()).toBeTruthy();
expect(findLoader().classes()).toContain('puik-button__loader--right');
});

it('should have a data-test attribute on left-loader and right-loader', () => {
factory({
loading: true,
loaderPosition: 'left',
dataTest: 'button'
});
expect(findLeftLoader().attributes('data-test')).toBe('leftLoader-button');

factory({
loading: true,
loaderPosition: 'right',
dataTest: 'button'
});
expect(findRightLoader().attributes('data-test')).toBe('rightLoader-button');
});
});

0 comments on commit ba8b01f

Please sign in to comment.