Loading src/App.vue +2 −0 Original line number Diff line number Diff line Loading @@ -110,6 +110,7 @@ import TriangleIcon from '@stories/icons/Mono/TriangleIcon.vue'; import Playground from '@/Playground.vue'; import ArrowShortDownIcon from '@stories/icons/Mono/ArrowShortDownIcon.vue'; import StarIcon from '@stories/icons/Mono/StarIcon.vue'; import StarFilledIcon from '@stories/icons/Mono/StarFilledIcon.vue'; const gentleIcons = { Age18Icon, Loading Loading @@ -214,6 +215,7 @@ const gentleIcons = { SearchIcon, SettingsIcon, StarIcon, StarFilledIcon, SortDownIcon, SortHorizontalIcon, SortUpIcon, Loading src/Playground.vue +10 −1 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ import Tag from '@stories/components/Tag/Tag.vue'; import Select from '@stories/components/Select/Select.vue'; import AtIcon from '@stories/icons/Mono/AtIcon.vue'; import Knob from '@stories/components/Knob/Knob.vue'; import Rating from '@stories/components/Rating/Rating.vue'; import HomeIcon from '@stories/icons/Mono/HomeIcon.vue'; const visibleDrawer = ref(false); const sliderOptions: ISliderOptions[] = [ Loading Loading @@ -197,7 +199,14 @@ const knob = ref(0); <template> <h2 class="title gradient-text">Playground</h2> {{ knob }} <Rating theme="red"> <template #offIcon> <CrossIcon color="red" /> </template> <template #onIcon> <HomeIcon color="blue" /> </template> </Rating> <Knob v-model="knob" /> <Select :options="selectOptions" theme="sky"> <template #icon-left-First> Loading src/common/constants/icons.ts +2 −0 Original line number Diff line number Diff line Loading @@ -110,6 +110,7 @@ import SortVerticalIcon from '@stories/icons/Mono/SortVerticalIcon.vue'; import ArrowShortDownIcon from '@stories/icons/Mono/ArrowShortDownIcon.vue'; import SearchIcon from '@stories/icons/Mono/SearchIcon.vue'; import StarIcon from '@stories/icons/Mono/StarIcon.vue'; import StarFilledIcon from '@stories/icons/Mono/StarFilledIcon.vue'; export const iconsSet: Record<string, Component> = { Age18: Age18Icon, Loading Loading @@ -214,6 +215,7 @@ export const iconsSet: Record<string, Component> = { Search: SearchIcon, Settings: SettingsIcon, Star: StarIcon, StarFilled: StarFilledIcon, SortDown: SortDownIcon, SortHorizontal: SortHorizontalIcon, SortUp: SortUpIcon, Loading src/stories/components/Rating/Rating.stories.ts +18 −29 Original line number Diff line number Diff line Loading @@ -14,17 +14,10 @@ const meta: Meta = { }, }, argTypes: { label: { control: 'text' }, padding: { control: 'text' }, count: { control: 'number' }, gap: { control: 'text' }, size: { control: 'select', options: ['small', 'normal', 'large', 'huge'] }, textStyle: { control: 'select', options: ['bold', 'italic'] }, iconPos: { control: 'select', options: ['left', 'top', 'right', 'bottom'] }, width: { control: 'text' }, darknessTheme: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'] }, darknessTextColor: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'], }, theme: { control: 'select', options: [ Loading @@ -45,26 +38,6 @@ const meta: Meta = { 'black', ], }, textColor: { control: 'select', options: [ 'white', 'blue', 'sky', 'cyan', 'teal', 'green', 'yellow', 'orange', 'pink', 'fuchsia', 'purple', 'indigo', 'rose', 'red', 'black', ], }, }, args: {}, } satisfies Meta<typeof Rating>; Loading @@ -76,3 +49,19 @@ type Story = StoryObj<typeof meta>; export const Simple: Story = { args: {}, }; export const Small: Story = { args: { size: 'small', }, }; export const Full: Story = { args: { theme: 'sky', darknessTheme: '400', count: 7, gap: '2px', size: 'huge', }, }; src/stories/components/Rating/Rating.vue +65 −22 Original line number Diff line number Diff line <script setup lang="ts"> import type { IRatingProps } from '@interfaces/componentsProps'; import { ref } from 'vue'; import { computed, type Ref, ref } from 'vue'; import { iconsSet } from '@/common/constants/icons'; import StarFilledIcon from '@stories/icons/Mono/StarFilledIcon.vue'; import { convertThemeToColor } from '@helpers/common'; const props = withDefaults(defineProps<IRatingProps>(), { count: 5, gap: '5px', size: 'normal', theme: 'black', darknessTheme: '500', }); const value = defineModel(); const value = defineModel({ default: 0, }) as Ref<number>; const onHoverIndex = ref(); // const textColor = computed(() => {}); const themeColor = computed(() => convertThemeToColor(props.theme, props.darknessTheme)); const themeColorOnHover = computed(() => convertThemeToColor(props.theme, '200')); const iconSize = computed(() => { const size = props.size; if (size === 'normal') return '20px'; if (size === 'large') return '30px'; if (size === 'huge') return '40px'; return '10px'; }); const onActiveClick = (index: number) => { if (value.value > index) { value.value = index; return; } value.value = 0; }; </script> <template> {{ value }} <ul class="list"> <li v-for="index of Array(count).keys()" :key="index" class="item"> <ul class="list" :style="`gap: ${gap}`"> <li v-for="index of Array(count).keys()" :key="index" class="item iconSize"> <div v-show="value < index + 1 && !$slots.offIcon" class="iconSize iconContainer"> <component class="icon" :is="iconsSet[icon ?? 'Star']" color="black" class="icon absoluteIcon" :is="iconsSet['Star']" :color="themeColor" @pointerenter="onHoverIndex = index" @pointerleave="onHoverIndex = null" :size="iconSize" /> <Transition> <component class="hoverIcon" class="absoluteIcon" v-show="onHoverIndex === index" :is="iconsSet[icon ?? 'Star']" color="gray" :is="iconsSet['Star']" :color="themeColorOnHover" @pointerenter="onHoverIndex = index" @pointerleave="onHoverIndex = null" @click="value = index + 1" /></Transition> :size="iconSize" /> </Transition> </div> <div v-show="value < index + 1" @click="value = index + 1"> <slot name="offIcon" :size="iconSize"></slot> </div> <StarFilledIcon v-show="value >= index + 1 && !$slots.onIcon" :color="themeColor" :size="iconSize" class="absoluteIcon" @click="onActiveClick(index + 1)" /> <div class="iconSize" v-show="value >= index + 1" @click="onActiveClick(index + 1)"> <slot name="onIcon" :size="iconSize"></slot> </div> </li> </ul> </template> Loading @@ -45,7 +85,6 @@ const onHoverIndex = ref(); .item { position: relative; cursor: pointer; transition: all 1s ease-in-out; } .icon { opacity: 1; Loading @@ -54,11 +93,15 @@ const onHoverIndex = ref(); opacity: 0; } } .hoverIcon { .absoluteIcon { position: absolute; top: 0; left: 0; } .iconSize { width: v-bind(iconSize); height: v-bind(iconSize); } .v-enter-active, .v-leave-active { transition: opacity 0.15s ease; Loading Loading
src/App.vue +2 −0 Original line number Diff line number Diff line Loading @@ -110,6 +110,7 @@ import TriangleIcon from '@stories/icons/Mono/TriangleIcon.vue'; import Playground from '@/Playground.vue'; import ArrowShortDownIcon from '@stories/icons/Mono/ArrowShortDownIcon.vue'; import StarIcon from '@stories/icons/Mono/StarIcon.vue'; import StarFilledIcon from '@stories/icons/Mono/StarFilledIcon.vue'; const gentleIcons = { Age18Icon, Loading Loading @@ -214,6 +215,7 @@ const gentleIcons = { SearchIcon, SettingsIcon, StarIcon, StarFilledIcon, SortDownIcon, SortHorizontalIcon, SortUpIcon, Loading
src/Playground.vue +10 −1 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ import Tag from '@stories/components/Tag/Tag.vue'; import Select from '@stories/components/Select/Select.vue'; import AtIcon from '@stories/icons/Mono/AtIcon.vue'; import Knob from '@stories/components/Knob/Knob.vue'; import Rating from '@stories/components/Rating/Rating.vue'; import HomeIcon from '@stories/icons/Mono/HomeIcon.vue'; const visibleDrawer = ref(false); const sliderOptions: ISliderOptions[] = [ Loading Loading @@ -197,7 +199,14 @@ const knob = ref(0); <template> <h2 class="title gradient-text">Playground</h2> {{ knob }} <Rating theme="red"> <template #offIcon> <CrossIcon color="red" /> </template> <template #onIcon> <HomeIcon color="blue" /> </template> </Rating> <Knob v-model="knob" /> <Select :options="selectOptions" theme="sky"> <template #icon-left-First> Loading
src/common/constants/icons.ts +2 −0 Original line number Diff line number Diff line Loading @@ -110,6 +110,7 @@ import SortVerticalIcon from '@stories/icons/Mono/SortVerticalIcon.vue'; import ArrowShortDownIcon from '@stories/icons/Mono/ArrowShortDownIcon.vue'; import SearchIcon from '@stories/icons/Mono/SearchIcon.vue'; import StarIcon from '@stories/icons/Mono/StarIcon.vue'; import StarFilledIcon from '@stories/icons/Mono/StarFilledIcon.vue'; export const iconsSet: Record<string, Component> = { Age18: Age18Icon, Loading Loading @@ -214,6 +215,7 @@ export const iconsSet: Record<string, Component> = { Search: SearchIcon, Settings: SettingsIcon, Star: StarIcon, StarFilled: StarFilledIcon, SortDown: SortDownIcon, SortHorizontal: SortHorizontalIcon, SortUp: SortUpIcon, Loading
src/stories/components/Rating/Rating.stories.ts +18 −29 Original line number Diff line number Diff line Loading @@ -14,17 +14,10 @@ const meta: Meta = { }, }, argTypes: { label: { control: 'text' }, padding: { control: 'text' }, count: { control: 'number' }, gap: { control: 'text' }, size: { control: 'select', options: ['small', 'normal', 'large', 'huge'] }, textStyle: { control: 'select', options: ['bold', 'italic'] }, iconPos: { control: 'select', options: ['left', 'top', 'right', 'bottom'] }, width: { control: 'text' }, darknessTheme: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'] }, darknessTextColor: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'], }, theme: { control: 'select', options: [ Loading @@ -45,26 +38,6 @@ const meta: Meta = { 'black', ], }, textColor: { control: 'select', options: [ 'white', 'blue', 'sky', 'cyan', 'teal', 'green', 'yellow', 'orange', 'pink', 'fuchsia', 'purple', 'indigo', 'rose', 'red', 'black', ], }, }, args: {}, } satisfies Meta<typeof Rating>; Loading @@ -76,3 +49,19 @@ type Story = StoryObj<typeof meta>; export const Simple: Story = { args: {}, }; export const Small: Story = { args: { size: 'small', }, }; export const Full: Story = { args: { theme: 'sky', darknessTheme: '400', count: 7, gap: '2px', size: 'huge', }, };
src/stories/components/Rating/Rating.vue +65 −22 Original line number Diff line number Diff line <script setup lang="ts"> import type { IRatingProps } from '@interfaces/componentsProps'; import { ref } from 'vue'; import { computed, type Ref, ref } from 'vue'; import { iconsSet } from '@/common/constants/icons'; import StarFilledIcon from '@stories/icons/Mono/StarFilledIcon.vue'; import { convertThemeToColor } from '@helpers/common'; const props = withDefaults(defineProps<IRatingProps>(), { count: 5, gap: '5px', size: 'normal', theme: 'black', darknessTheme: '500', }); const value = defineModel(); const value = defineModel({ default: 0, }) as Ref<number>; const onHoverIndex = ref(); // const textColor = computed(() => {}); const themeColor = computed(() => convertThemeToColor(props.theme, props.darknessTheme)); const themeColorOnHover = computed(() => convertThemeToColor(props.theme, '200')); const iconSize = computed(() => { const size = props.size; if (size === 'normal') return '20px'; if (size === 'large') return '30px'; if (size === 'huge') return '40px'; return '10px'; }); const onActiveClick = (index: number) => { if (value.value > index) { value.value = index; return; } value.value = 0; }; </script> <template> {{ value }} <ul class="list"> <li v-for="index of Array(count).keys()" :key="index" class="item"> <ul class="list" :style="`gap: ${gap}`"> <li v-for="index of Array(count).keys()" :key="index" class="item iconSize"> <div v-show="value < index + 1 && !$slots.offIcon" class="iconSize iconContainer"> <component class="icon" :is="iconsSet[icon ?? 'Star']" color="black" class="icon absoluteIcon" :is="iconsSet['Star']" :color="themeColor" @pointerenter="onHoverIndex = index" @pointerleave="onHoverIndex = null" :size="iconSize" /> <Transition> <component class="hoverIcon" class="absoluteIcon" v-show="onHoverIndex === index" :is="iconsSet[icon ?? 'Star']" color="gray" :is="iconsSet['Star']" :color="themeColorOnHover" @pointerenter="onHoverIndex = index" @pointerleave="onHoverIndex = null" @click="value = index + 1" /></Transition> :size="iconSize" /> </Transition> </div> <div v-show="value < index + 1" @click="value = index + 1"> <slot name="offIcon" :size="iconSize"></slot> </div> <StarFilledIcon v-show="value >= index + 1 && !$slots.onIcon" :color="themeColor" :size="iconSize" class="absoluteIcon" @click="onActiveClick(index + 1)" /> <div class="iconSize" v-show="value >= index + 1" @click="onActiveClick(index + 1)"> <slot name="onIcon" :size="iconSize"></slot> </div> </li> </ul> </template> Loading @@ -45,7 +85,6 @@ const onHoverIndex = ref(); .item { position: relative; cursor: pointer; transition: all 1s ease-in-out; } .icon { opacity: 1; Loading @@ -54,11 +93,15 @@ const onHoverIndex = ref(); opacity: 0; } } .hoverIcon { .absoluteIcon { position: absolute; top: 0; left: 0; } .iconSize { width: v-bind(iconSize); height: v-bind(iconSize); } .v-enter-active, .v-leave-active { transition: opacity 0.15s ease; Loading