Loading src/common/interfaces/componentsProp.ts +7 −3 Original line number Diff line number Diff line Loading @@ -58,9 +58,11 @@ export interface IMDItemProps { export interface ISelectOption { value: string; label?: string; group?: string; iconLeft?: TIcons; iconRight?: TIcons; iconColor?: TThemeColor; iconLeftColor?: TThemeColor; iconRightColor?: TThemeColor; color?: TThemeColor; darknessColor?: TDarkness; background?: TThemeColor; Loading @@ -68,10 +70,12 @@ export interface ISelectOption { } export interface ISelectGroup { title: string; name: string; titleColor?: TThemeColor; iconLeft?: TIcons; iconRight?: TIcons; items: string[]; iconLeftColor?: TThemeColor; iconRightColor?: TThemeColor; } export interface ISBOption { Loading src/common/interfaces/componentsProps.ts +3 −0 Original line number Diff line number Diff line Loading @@ -134,8 +134,11 @@ export interface ISelectProps { name?: string; theme?: TThemeColor; background?: TThemeColor; placeholderColor?: TThemeColor; openIconColor?: TThemeColor; darknessTheme?: TDarkness; darknessBackground?: TDarkness; darknessOpenIcon?: TDarkness; disabled?: boolean; } Loading src/stories/components/MenuDial/MenuDial.stories.ts +2 −2 Original line number Diff line number Diff line Loading @@ -102,7 +102,7 @@ export const Full: Story = { }, }; export const Down: Story = { export const Vertical: Story = { args: { items: [ { Loading @@ -125,7 +125,7 @@ export const Down: Story = { }, }; export const Huge: Story = { export const Full2: Story = { args: { items: [ { Loading src/stories/components/Select/Select.stories.ts +45 −1 Original line number Diff line number Diff line import type { Meta, StoryObj } from '@storybook/vue3'; import Select from './Select.vue'; import { iconsSet } from '@/common/constants/icons'; const meta: Meta = { title: 'Components/Select', Loading @@ -18,9 +19,11 @@ const meta: Meta = { disabled: { control: 'boolean' }, placeholder: { control: 'text' }, name: { control: 'text' }, openIcon: { control: 'select', options: Object.keys(iconsSet) }, size: { control: 'select', options: ['small', 'normal', 'large', 'huge'] }, darknessTheme: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'] }, darknessBackground: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'] }, darknessOpenIcon: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'] }, theme: { control: 'select', options: [ Loading Loading @@ -61,6 +64,46 @@ const meta: Meta = { 'black', ], }, openIconColor: { control: 'select', options: [ 'white', 'blue', 'sky', 'cyan', 'teal', 'green', 'yellow', 'orange', 'pink', 'fuchsia', 'purple', 'indigo', 'rose', 'red', 'black', ], }, placeholderColor: { control: 'select', options: [ 'white', 'blue', 'sky', 'cyan', 'teal', 'green', 'yellow', 'orange', 'pink', 'fuchsia', 'purple', 'indigo', 'rose', 'red', 'black', ], }, }, } satisfies Meta<typeof Select>; Loading Loading @@ -95,7 +138,7 @@ export const Full: Story = { }, { value: 'Second', iconColor: 'red', iconRightColor: 'red', iconRight: 'Age18', }, { Loading @@ -112,5 +155,6 @@ export const Full: Story = { background: 'sky', darknessTheme: '700', darknessBackground: '200', openIconColor: 'sky', }, }; src/stories/components/Select/Select.vue +44 −80 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ import { computed, ref } from 'vue'; import { convertThemeToColor } from '@helpers/common'; import { iconsSet } from '@/common/constants/icons'; import type { TThemeColor } from '@interfaces/common'; import SelectItem from '@stories/components/Select/SelectItem.vue'; const props = withDefaults(defineProps<ISelectProps>(), { size: 'normal', Loading @@ -11,22 +12,20 @@ const props = withDefaults(defineProps<ISelectProps>(), { theme: 'black', darknessTheme: '700', darknessBackground: '200', darknessOpenIcon: '700', name: 'select', placeholder: 'Nothing selected', openIcon: 'ArrowShortDown', }); const selected = defineModel('value'); // watch(, () => {}); const isOpen = ref<boolean>(false); const selectedOption = computed(() => props.options.find((option) => option.value === selected.value)); const textColor = computed(() => convertThemeToColor(props.theme, props.darknessTheme)); const textColor = computed(() => (props.disabled ? '#62708c' : convertThemeToColor(props.theme, props.darknessTheme))); const backgroundColor = computed(() => convertThemeToColor( props.background ?? (props.theme === 'white' ? 'black' : props.theme === 'black' ? 'white' : props.theme), (!props.background && props.theme === 'black') || (props.background === 'white' && props.theme === 'black') ? '500' : props.darknessBackground, (!props.background && props.theme === 'black') || props.background === 'white' ? '500' : props.darknessBackground, ), ); const fontSize = computed(() => { Loading @@ -36,6 +35,13 @@ const fontSize = computed(() => { if (size === 'huge') return '24px'; return '12px'; }); const padding = computed(() => { const size = props.size; if (size === 'normal') return '6px'; if (size === 'large') return '10px'; if (size === 'huge') return '14px'; return '4px'; }); const pickOption = (value: string) => { selected.value = value; Loading @@ -54,38 +60,31 @@ const calcOptionColor = (color: TThemeColor | undefined, darknessColor: string | </option> </select> <div class="list" :style="`background-color: ${backgroundColor}`"> <button @click.prevent="isOpen = !isOpen" class="button" :style="`width: ${width}`"> <span <button @click.prevent="!disabled ? (isOpen = !isOpen) : ''" :class="[ 'button', { disabled: disabled, }, ]" :style="`width: ${width}`" > <SelectItem class="selected" :style="`color: ${selected ? calcOptionColor(selectedOption?.color, selectedOption?.darknessColor, textColor) : '#62708c'}; font-weight: 600`" :style="`color: ${selected ? calcOptionColor(selectedOption?.color, selectedOption?.darknessColor, textColor) : placeholderColor ? convertThemeToColor(placeholderColor, '700') : '#62708c'}; font-weight: 600`" :option="selectedOption" :fontSize="fontSize" :textColor="textColor" > <slot :name="`icon-left-${selectedOption?.value}`"></slot> <span :style="`font-size: ${fontSize}`">{{ selected ?? placeholder }}</span> <slot :name="`icon-right-${selectedOption?.value}`"></slot> </SelectItem> <component v-if="selectedOption?.iconLeft" :is="iconsSet[selectedOption?.iconLeft]" :size="fontSize.slice(0, -2)" :color=" calcOptionColor( selectedOption.iconColor ?? selectedOption?.color, selectedOption?.darknessColor, textColor, ) " /><span>{{ selected ?? placeholder }}</span> <component v-if="selectedOption?.iconRight" :is="iconsSet[selectedOption?.iconRight]" :size="fontSize.slice(0, -2)" :color=" calcOptionColor( selectedOption.iconColor ?? selectedOption?.color, selectedOption?.darknessColor, textColor, ) " /><slot :name="`icon-right-${selectedOption?.value}`"></slot></span ><component :is="iconsSet[openIcon]" :size="fontSize.slice(0, -2)" color="#62708c" :color="openIconColor ? convertThemeToColor(openIconColor, darknessOpenIcon) : '#62708c'" :style="`width: ${fontSize}`" /> </button> Loading @@ -98,7 +97,7 @@ const calcOptionColor = (color: TThemeColor | undefined, darknessColor: string | ]" > <div style="overflow: hidden"> <p <SelectItem @click.prevent="pickOption(option.value)" v-for="option of options" :key="option.value" Loading @@ -111,22 +110,14 @@ const calcOptionColor = (color: TThemeColor | undefined, darknessColor: string | ]" :style="`color: ${calcOptionColor(option.color, option.darknessColor, textColor)}; background-color: ${calcOptionColor(option.background, option.darknessBackground, backgroundColor)}`" :option="option" :fontSize="fontSize" :textColor="textColor" > <slot :name="`icon-left-${option.value}`"></slot> <component v-if="option.iconLeft" :is="iconsSet[option.iconLeft]" :size="fontSize.slice(0, -2)" :color="calcOptionColor(option.iconColor ?? option.color, option.darknessColor, textColor)" /><span>{{ option.label ?? option.value }}</span ><component v-if="option.iconRight" :is="iconsSet[option.iconRight]" :size="fontSize.slice(0, -2)" :color="calcOptionColor(option.iconColor ?? option.color, option.darknessColor, textColor)" /> <span :style="`font-size: ${fontSize}`">{{ option.label ?? option.value }}</span> <slot :name="`icon-right-${option.value}`"></slot> </p> </SelectItem> </div> </div> </div> Loading @@ -146,7 +137,7 @@ const calcOptionColor = (color: TThemeColor | undefined, darknessColor: string | } .button { display: flex; padding: 7px; padding: v-bind(padding); justify-content: space-between; gap: 10px; } Loading Loading @@ -176,7 +167,7 @@ const calcOptionColor = (color: TThemeColor | undefined, darknessColor: string | display: flex; align-items: center; gap: 5px; padding: 7px; padding: v-bind(padding); } .option:hover { filter: brightness(90%); Loading @@ -193,36 +184,9 @@ const calcOptionColor = (color: TThemeColor | undefined, darknessColor: string | border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; } .disabled { cursor: auto; background-color: #e1e7f1 !important; border-radius: 4px; } </style> <!--.list {--> <!--position: relative;--> <!--width: max-content;--> <!--border: 1px solid v-bind(textColor);--> <!--border-radius: 5px 5px 0 0;--> <!--cursor: pointer;--> <!--}--> <!--.button {--> <!--display: flex;--> <!--padding: 7px;--> <!--justify-content: space-between;--> <!--gap: 10px;--> <!--}--> <!--.selected {--> <!--display: flex;--> <!--gap: 5px;--> <!--}--> <!--.options {--> <!--position: absolute;--> <!--top: 100%;--> <!--width: 100%;--> <!--border: 1px solid v-bind(textColor);--> <!--border-top: none;--> <!--border-bottom-left-radius: 5px;--> <!--border-bottom-right-radius: 5px;--> <!--display: grid;--> <!--grid-template-rows: 0fr;--> <!--opacity: 0;--> <!--transition:--> <!--all 0.2s ease-in-out,--> <!--opacity 0.1s ease-in-out;--> <!--}--> Loading
src/common/interfaces/componentsProp.ts +7 −3 Original line number Diff line number Diff line Loading @@ -58,9 +58,11 @@ export interface IMDItemProps { export interface ISelectOption { value: string; label?: string; group?: string; iconLeft?: TIcons; iconRight?: TIcons; iconColor?: TThemeColor; iconLeftColor?: TThemeColor; iconRightColor?: TThemeColor; color?: TThemeColor; darknessColor?: TDarkness; background?: TThemeColor; Loading @@ -68,10 +70,12 @@ export interface ISelectOption { } export interface ISelectGroup { title: string; name: string; titleColor?: TThemeColor; iconLeft?: TIcons; iconRight?: TIcons; items: string[]; iconLeftColor?: TThemeColor; iconRightColor?: TThemeColor; } export interface ISBOption { Loading
src/common/interfaces/componentsProps.ts +3 −0 Original line number Diff line number Diff line Loading @@ -134,8 +134,11 @@ export interface ISelectProps { name?: string; theme?: TThemeColor; background?: TThemeColor; placeholderColor?: TThemeColor; openIconColor?: TThemeColor; darknessTheme?: TDarkness; darknessBackground?: TDarkness; darknessOpenIcon?: TDarkness; disabled?: boolean; } Loading
src/stories/components/MenuDial/MenuDial.stories.ts +2 −2 Original line number Diff line number Diff line Loading @@ -102,7 +102,7 @@ export const Full: Story = { }, }; export const Down: Story = { export const Vertical: Story = { args: { items: [ { Loading @@ -125,7 +125,7 @@ export const Down: Story = { }, }; export const Huge: Story = { export const Full2: Story = { args: { items: [ { Loading
src/stories/components/Select/Select.stories.ts +45 −1 Original line number Diff line number Diff line import type { Meta, StoryObj } from '@storybook/vue3'; import Select from './Select.vue'; import { iconsSet } from '@/common/constants/icons'; const meta: Meta = { title: 'Components/Select', Loading @@ -18,9 +19,11 @@ const meta: Meta = { disabled: { control: 'boolean' }, placeholder: { control: 'text' }, name: { control: 'text' }, openIcon: { control: 'select', options: Object.keys(iconsSet) }, size: { control: 'select', options: ['small', 'normal', 'large', 'huge'] }, darknessTheme: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'] }, darknessBackground: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'] }, darknessOpenIcon: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'] }, theme: { control: 'select', options: [ Loading Loading @@ -61,6 +64,46 @@ const meta: Meta = { 'black', ], }, openIconColor: { control: 'select', options: [ 'white', 'blue', 'sky', 'cyan', 'teal', 'green', 'yellow', 'orange', 'pink', 'fuchsia', 'purple', 'indigo', 'rose', 'red', 'black', ], }, placeholderColor: { control: 'select', options: [ 'white', 'blue', 'sky', 'cyan', 'teal', 'green', 'yellow', 'orange', 'pink', 'fuchsia', 'purple', 'indigo', 'rose', 'red', 'black', ], }, }, } satisfies Meta<typeof Select>; Loading Loading @@ -95,7 +138,7 @@ export const Full: Story = { }, { value: 'Second', iconColor: 'red', iconRightColor: 'red', iconRight: 'Age18', }, { Loading @@ -112,5 +155,6 @@ export const Full: Story = { background: 'sky', darknessTheme: '700', darknessBackground: '200', openIconColor: 'sky', }, };
src/stories/components/Select/Select.vue +44 −80 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ import { computed, ref } from 'vue'; import { convertThemeToColor } from '@helpers/common'; import { iconsSet } from '@/common/constants/icons'; import type { TThemeColor } from '@interfaces/common'; import SelectItem from '@stories/components/Select/SelectItem.vue'; const props = withDefaults(defineProps<ISelectProps>(), { size: 'normal', Loading @@ -11,22 +12,20 @@ const props = withDefaults(defineProps<ISelectProps>(), { theme: 'black', darknessTheme: '700', darknessBackground: '200', darknessOpenIcon: '700', name: 'select', placeholder: 'Nothing selected', openIcon: 'ArrowShortDown', }); const selected = defineModel('value'); // watch(, () => {}); const isOpen = ref<boolean>(false); const selectedOption = computed(() => props.options.find((option) => option.value === selected.value)); const textColor = computed(() => convertThemeToColor(props.theme, props.darknessTheme)); const textColor = computed(() => (props.disabled ? '#62708c' : convertThemeToColor(props.theme, props.darknessTheme))); const backgroundColor = computed(() => convertThemeToColor( props.background ?? (props.theme === 'white' ? 'black' : props.theme === 'black' ? 'white' : props.theme), (!props.background && props.theme === 'black') || (props.background === 'white' && props.theme === 'black') ? '500' : props.darknessBackground, (!props.background && props.theme === 'black') || props.background === 'white' ? '500' : props.darknessBackground, ), ); const fontSize = computed(() => { Loading @@ -36,6 +35,13 @@ const fontSize = computed(() => { if (size === 'huge') return '24px'; return '12px'; }); const padding = computed(() => { const size = props.size; if (size === 'normal') return '6px'; if (size === 'large') return '10px'; if (size === 'huge') return '14px'; return '4px'; }); const pickOption = (value: string) => { selected.value = value; Loading @@ -54,38 +60,31 @@ const calcOptionColor = (color: TThemeColor | undefined, darknessColor: string | </option> </select> <div class="list" :style="`background-color: ${backgroundColor}`"> <button @click.prevent="isOpen = !isOpen" class="button" :style="`width: ${width}`"> <span <button @click.prevent="!disabled ? (isOpen = !isOpen) : ''" :class="[ 'button', { disabled: disabled, }, ]" :style="`width: ${width}`" > <SelectItem class="selected" :style="`color: ${selected ? calcOptionColor(selectedOption?.color, selectedOption?.darknessColor, textColor) : '#62708c'}; font-weight: 600`" :style="`color: ${selected ? calcOptionColor(selectedOption?.color, selectedOption?.darknessColor, textColor) : placeholderColor ? convertThemeToColor(placeholderColor, '700') : '#62708c'}; font-weight: 600`" :option="selectedOption" :fontSize="fontSize" :textColor="textColor" > <slot :name="`icon-left-${selectedOption?.value}`"></slot> <span :style="`font-size: ${fontSize}`">{{ selected ?? placeholder }}</span> <slot :name="`icon-right-${selectedOption?.value}`"></slot> </SelectItem> <component v-if="selectedOption?.iconLeft" :is="iconsSet[selectedOption?.iconLeft]" :size="fontSize.slice(0, -2)" :color=" calcOptionColor( selectedOption.iconColor ?? selectedOption?.color, selectedOption?.darknessColor, textColor, ) " /><span>{{ selected ?? placeholder }}</span> <component v-if="selectedOption?.iconRight" :is="iconsSet[selectedOption?.iconRight]" :size="fontSize.slice(0, -2)" :color=" calcOptionColor( selectedOption.iconColor ?? selectedOption?.color, selectedOption?.darknessColor, textColor, ) " /><slot :name="`icon-right-${selectedOption?.value}`"></slot></span ><component :is="iconsSet[openIcon]" :size="fontSize.slice(0, -2)" color="#62708c" :color="openIconColor ? convertThemeToColor(openIconColor, darknessOpenIcon) : '#62708c'" :style="`width: ${fontSize}`" /> </button> Loading @@ -98,7 +97,7 @@ const calcOptionColor = (color: TThemeColor | undefined, darknessColor: string | ]" > <div style="overflow: hidden"> <p <SelectItem @click.prevent="pickOption(option.value)" v-for="option of options" :key="option.value" Loading @@ -111,22 +110,14 @@ const calcOptionColor = (color: TThemeColor | undefined, darknessColor: string | ]" :style="`color: ${calcOptionColor(option.color, option.darknessColor, textColor)}; background-color: ${calcOptionColor(option.background, option.darknessBackground, backgroundColor)}`" :option="option" :fontSize="fontSize" :textColor="textColor" > <slot :name="`icon-left-${option.value}`"></slot> <component v-if="option.iconLeft" :is="iconsSet[option.iconLeft]" :size="fontSize.slice(0, -2)" :color="calcOptionColor(option.iconColor ?? option.color, option.darknessColor, textColor)" /><span>{{ option.label ?? option.value }}</span ><component v-if="option.iconRight" :is="iconsSet[option.iconRight]" :size="fontSize.slice(0, -2)" :color="calcOptionColor(option.iconColor ?? option.color, option.darknessColor, textColor)" /> <span :style="`font-size: ${fontSize}`">{{ option.label ?? option.value }}</span> <slot :name="`icon-right-${option.value}`"></slot> </p> </SelectItem> </div> </div> </div> Loading @@ -146,7 +137,7 @@ const calcOptionColor = (color: TThemeColor | undefined, darknessColor: string | } .button { display: flex; padding: 7px; padding: v-bind(padding); justify-content: space-between; gap: 10px; } Loading Loading @@ -176,7 +167,7 @@ const calcOptionColor = (color: TThemeColor | undefined, darknessColor: string | display: flex; align-items: center; gap: 5px; padding: 7px; padding: v-bind(padding); } .option:hover { filter: brightness(90%); Loading @@ -193,36 +184,9 @@ const calcOptionColor = (color: TThemeColor | undefined, darknessColor: string | border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; } .disabled { cursor: auto; background-color: #e1e7f1 !important; border-radius: 4px; } </style> <!--.list {--> <!--position: relative;--> <!--width: max-content;--> <!--border: 1px solid v-bind(textColor);--> <!--border-radius: 5px 5px 0 0;--> <!--cursor: pointer;--> <!--}--> <!--.button {--> <!--display: flex;--> <!--padding: 7px;--> <!--justify-content: space-between;--> <!--gap: 10px;--> <!--}--> <!--.selected {--> <!--display: flex;--> <!--gap: 5px;--> <!--}--> <!--.options {--> <!--position: absolute;--> <!--top: 100%;--> <!--width: 100%;--> <!--border: 1px solid v-bind(textColor);--> <!--border-top: none;--> <!--border-bottom-left-radius: 5px;--> <!--border-bottom-right-radius: 5px;--> <!--display: grid;--> <!--grid-template-rows: 0fr;--> <!--opacity: 0;--> <!--transition:--> <!--all 0.2s ease-in-out,--> <!--opacity 0.1s ease-in-out;--> <!--}-->