Loading src/common/interfaces/componentsProps.ts +10 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,16 @@ export interface IPaginatorProps { darknessTheme?: TDarkness; } export interface ICarouselProps { itemsProps: unknown[]; width?: string; size?: TSize; perView?: number; perScroll?: number; theme?: TThemeColor; darknessTheme?: TDarkness; } export interface IMDProps { items: IMDItemProps[]; size?: TSize; Loading src/components/Carousel/Carousel.stories.ts 0 → 100644 +105 −0 Original line number Diff line number Diff line import type { Meta, StoryObj } from '@storybook/vue3'; import Carousel from './Carousel.vue'; const meta: Meta = { title: 'Components/Carousel', component: Carousel, tags: ['pick'], parameters: { docs: { description: { component: 'A component to define number inputs with a dial.', }, }, }, argTypes: { buttons: { control: 'boolean' }, showLabel: { control: 'boolean' }, colorAsTheme: { control: 'boolean' }, textBold: { control: 'boolean' }, min: { control: 'number' }, max: { control: 'number' }, step: { control: 'number' }, fontSize: { control: 'text' }, textBefore: { control: 'text' }, textAfter: { control: 'text' }, colorGaps: { control: 'object' }, size: { control: 'select', options: ['small', 'normal', 'large', 'huge'] }, background: { control: 'color' }, darknessTheme: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'] }, darknessNegativeTheme: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'], }, darknessColor: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'] }, theme: { control: 'select', options: [ 'white', 'blue', 'sky', 'cyan', 'teal', 'green', 'yellow', 'orange', 'pink', 'fuchsia', 'purple', 'indigo', 'rose', 'red', 'black', ], }, negativeTheme: { control: 'select', options: [ 'white', 'blue', 'sky', 'cyan', 'teal', 'green', 'yellow', 'orange', 'pink', 'fuchsia', 'purple', 'indigo', 'rose', 'red', 'black', ], }, color: { control: 'select', options: [ 'white', 'blue', 'sky', 'cyan', 'teal', 'green', 'yellow', 'orange', 'pink', 'fuchsia', 'purple', 'indigo', 'rose', 'red', 'black', ], }, }, } satisfies Meta<typeof Carousel>; export default meta; type Story = StoryObj<typeof meta>; export const Simple: Story = { args: {}, }; src/components/Carousel/Carousel.vue 0 → 100644 +46 −0 Original line number Diff line number Diff line <script setup lang="ts"> import type { ICarouselProps } from '@interfaces/componentsProps'; import CarouselArrowContainer from '@components/Carousel/CarouselArrowContainer.vue'; import { computed, ref } from 'vue'; import { convertThemeToColor, convertThemeToTextColor } from '@helpers/common'; import ArrowLeftShortIcon from '@icons/Mono/ArrowLeftShortIcon.vue'; import ArrowRightShortIcon from '@icons/Mono/ArrowRightShortIcon.vue'; const props = withDefaults(defineProps<ICarouselProps>(), { itemsProps: () => [], size: 'normal', }); const current = ref(1); const itemsLength = computed(() => Math.ceil(props.itemsProps.length / props.perView)); const color = computed(() => convertThemeToColor(props.theme, props.darknessTheme)); const textColor = computed(() => convertThemeToTextColor(props.theme, props.darknessTheme)); const isStartDisabled = computed(() => current.value === 1); const isEndDisabled = computed(() => current.value === itemsLength.value); const iconSize = computed(() => { const size = props.size; if (size === 'normal') return '10'; if (size === 'large') return '15'; if (size === 'huge') return '18'; return '7'; }); </script> <template> <section :style="`width: ${width}; min-height: 100px`" class="carouselContainer"> <CarouselArrowContainer :textColor="textColor" :color="color" :disable="isStartDisabled"> <ArrowLeftShortIcon :color="isStartDisabled ? '#aaa' : textColor" :size="iconSize" /> </CarouselArrowContainer> <slot /> <CarouselArrowContainer :textColor="textColor" :color="color" :disable="isEndDisabled"> <ArrowRightShortIcon :color="isEndDisabled ? '#aaa' : textColor" :size="iconSize" /> </CarouselArrowContainer> </section> </template> <style scoped> .carouselContainer { display: flex; } </style> src/components/Carousel/CarouselArrowContainer.vue 0 → 100644 +86 −0 Original line number Diff line number Diff line <script setup lang="ts"> defineProps<{ disable?: boolean; textColor: string; color: string; }>(); </script> <template> <div class="arrowContainer"> <div :class="[ 'icon', { disable, }, ]" > <div :class="[ 'bg', { disableBg: disable, }, ]" ></div> <slot /> </div> </div> </template> <style scoped> .arrowContainer { width: 50px; min-height: 100%; display: flex; justify-content: center; align-items: center; } .icon { position: relative; display: flex; justify-content: center; align-items: center; cursor: pointer; line-height: 1.2; color: v-bind(textColor); } .icon::before { content: ''; position: absolute; width: 100%; height: 100%; border-radius: 50%; z-index: -1; background-color: v-bind(color); } .icon:hover > .bg { background-color: v-bind(textColor); opacity: 0.1; } .icon:active > .bg { opacity: 0.2; } .bg { width: 100%; height: 100%; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); padding: 10px; z-index: 5; border-radius: 50%; background-color: transparent; opacity: 0; transition: all 0.2s ease; } .disable { cursor: auto; pointer-events: none; } .disableBg { background-color: white !important; } </style> Loading
src/common/interfaces/componentsProps.ts +10 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,16 @@ export interface IPaginatorProps { darknessTheme?: TDarkness; } export interface ICarouselProps { itemsProps: unknown[]; width?: string; size?: TSize; perView?: number; perScroll?: number; theme?: TThemeColor; darknessTheme?: TDarkness; } export interface IMDProps { items: IMDItemProps[]; size?: TSize; Loading
src/components/Carousel/Carousel.stories.ts 0 → 100644 +105 −0 Original line number Diff line number Diff line import type { Meta, StoryObj } from '@storybook/vue3'; import Carousel from './Carousel.vue'; const meta: Meta = { title: 'Components/Carousel', component: Carousel, tags: ['pick'], parameters: { docs: { description: { component: 'A component to define number inputs with a dial.', }, }, }, argTypes: { buttons: { control: 'boolean' }, showLabel: { control: 'boolean' }, colorAsTheme: { control: 'boolean' }, textBold: { control: 'boolean' }, min: { control: 'number' }, max: { control: 'number' }, step: { control: 'number' }, fontSize: { control: 'text' }, textBefore: { control: 'text' }, textAfter: { control: 'text' }, colorGaps: { control: 'object' }, size: { control: 'select', options: ['small', 'normal', 'large', 'huge'] }, background: { control: 'color' }, darknessTheme: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'] }, darknessNegativeTheme: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'], }, darknessColor: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'] }, theme: { control: 'select', options: [ 'white', 'blue', 'sky', 'cyan', 'teal', 'green', 'yellow', 'orange', 'pink', 'fuchsia', 'purple', 'indigo', 'rose', 'red', 'black', ], }, negativeTheme: { control: 'select', options: [ 'white', 'blue', 'sky', 'cyan', 'teal', 'green', 'yellow', 'orange', 'pink', 'fuchsia', 'purple', 'indigo', 'rose', 'red', 'black', ], }, color: { control: 'select', options: [ 'white', 'blue', 'sky', 'cyan', 'teal', 'green', 'yellow', 'orange', 'pink', 'fuchsia', 'purple', 'indigo', 'rose', 'red', 'black', ], }, }, } satisfies Meta<typeof Carousel>; export default meta; type Story = StoryObj<typeof meta>; export const Simple: Story = { args: {}, };
src/components/Carousel/Carousel.vue 0 → 100644 +46 −0 Original line number Diff line number Diff line <script setup lang="ts"> import type { ICarouselProps } from '@interfaces/componentsProps'; import CarouselArrowContainer from '@components/Carousel/CarouselArrowContainer.vue'; import { computed, ref } from 'vue'; import { convertThemeToColor, convertThemeToTextColor } from '@helpers/common'; import ArrowLeftShortIcon from '@icons/Mono/ArrowLeftShortIcon.vue'; import ArrowRightShortIcon from '@icons/Mono/ArrowRightShortIcon.vue'; const props = withDefaults(defineProps<ICarouselProps>(), { itemsProps: () => [], size: 'normal', }); const current = ref(1); const itemsLength = computed(() => Math.ceil(props.itemsProps.length / props.perView)); const color = computed(() => convertThemeToColor(props.theme, props.darknessTheme)); const textColor = computed(() => convertThemeToTextColor(props.theme, props.darknessTheme)); const isStartDisabled = computed(() => current.value === 1); const isEndDisabled = computed(() => current.value === itemsLength.value); const iconSize = computed(() => { const size = props.size; if (size === 'normal') return '10'; if (size === 'large') return '15'; if (size === 'huge') return '18'; return '7'; }); </script> <template> <section :style="`width: ${width}; min-height: 100px`" class="carouselContainer"> <CarouselArrowContainer :textColor="textColor" :color="color" :disable="isStartDisabled"> <ArrowLeftShortIcon :color="isStartDisabled ? '#aaa' : textColor" :size="iconSize" /> </CarouselArrowContainer> <slot /> <CarouselArrowContainer :textColor="textColor" :color="color" :disable="isEndDisabled"> <ArrowRightShortIcon :color="isEndDisabled ? '#aaa' : textColor" :size="iconSize" /> </CarouselArrowContainer> </section> </template> <style scoped> .carouselContainer { display: flex; } </style>
src/components/Carousel/CarouselArrowContainer.vue 0 → 100644 +86 −0 Original line number Diff line number Diff line <script setup lang="ts"> defineProps<{ disable?: boolean; textColor: string; color: string; }>(); </script> <template> <div class="arrowContainer"> <div :class="[ 'icon', { disable, }, ]" > <div :class="[ 'bg', { disableBg: disable, }, ]" ></div> <slot /> </div> </div> </template> <style scoped> .arrowContainer { width: 50px; min-height: 100%; display: flex; justify-content: center; align-items: center; } .icon { position: relative; display: flex; justify-content: center; align-items: center; cursor: pointer; line-height: 1.2; color: v-bind(textColor); } .icon::before { content: ''; position: absolute; width: 100%; height: 100%; border-radius: 50%; z-index: -1; background-color: v-bind(color); } .icon:hover > .bg { background-color: v-bind(textColor); opacity: 0.1; } .icon:active > .bg { opacity: 0.2; } .bg { width: 100%; height: 100%; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); padding: 10px; z-index: 5; border-radius: 50%; background-color: transparent; opacity: 0; transition: all 0.2s ease; } .disable { cursor: auto; pointer-events: none; } .disableBg { background-color: white !important; } </style>