Newer
Older
<script setup lang="ts">
import { computed } from 'vue';
import type { ISBProps } from '@interfaces/componentsProps';
import { convertThemeToColor } from '@helpers/common';
const props = withDefaults(defineProps<ISBProps>(), {
darknessActiveBackgroundColor: 500,
darknessBorder: 500,
const emit = defineEmits(['onClick']);
const value = defineModel<never>('value');
const themeColor = computed(() => convertThemeToColor(props.theme, props.darknessTheme));
const textColor = computed(() => {
if (props.theme === 'white' || (props.darknessTheme <= 600 && props.theme !== 'black'))
return '#000000';
return '#ffffff';
});
const activeBackgroundColorComputed = computed(() =>
props.activeBackgroundColor
? convertThemeToColor(props.activeBackgroundColor, props.darknessActiveBackgroundColor)
: '',
);
const borderColor = computed(() =>
!props.border ? '' : convertThemeToColor(props.border, props.darknessBorder),
);
const textSize = computed(() => {
switch (props.size) {
case 'small':
return '12px';
case 'large':
return '20px';
return '24px';
}
});
const buttonPadding = computed(() => {
switch (props.size) {
case 'small':
return '0.5rem 0.375rem';
case 'large':
return '1.2rem 0.8rem';
return '1.8rem 1.2rem';
}
return '0.75rem 0.5rem';
});
const buttonHeight = computed(() => {
switch (props.size) {
case 'small':
return '24px';
case 'large':
return '68px';
return '114px';
}
});
</script>
<template>
<div
:class="[
'buttonGroup',
{
'rounded-full': props.rounded,
border: borderColor,
disabled: disabled,
},
]"
>
<button
v-for="(item, index) of options"
:key="item.label"
:class="[
'button',
{
'flex-column': item.iconPosition === 'top' || item.iconPosition === 'bottom',
},
]"
:style="`padding: ${buttonPadding}`"
@click.prevent="
() => {
value = (item.value as never) ?? item.label;
emit('onClick', value);
}
"
>
<span
:style="`background-color: ${activeBackgroundColorComputed && ((value && value === item.value) || value === item.label) ? activeBackgroundColorComputed : (convertThemeToColor(item.backgroundColor, item.darknessBackgroundColor ?? 500) ?? themeColor)}`"
:class="[
'background',
{
'rounded-left': index === 0,
'rounded-left-full': index === 0 && props.rounded,
'rounded-right': index === options.length - 1,
'rounded-right-full': index === options.length - 1 && props.rounded,
},
]"
></span>
<span
v-if="!item.isLabelHidden"
:style="`color: ${(item.value && value === item.value) || value === item.label ? (convertThemeToColor(item.activeColor, item.darknessActiveColor ?? 500) ?? textColor) : (convertThemeToColor(item.color, item.darknessColor ?? 500) ?? textColor)}; font-size: ${textSize}`"
:class="[
{
bold: item.textStyle === 'bold',
italic: item.textStyle === 'italic',
},
>{{ item.label ?? index }}</span
<span
v-if="$slots[`${index + 1}Icon`]"
:class="[
'icon',
{
'order-1': item.iconPosition === 'left' || item.iconPosition === 'top',
},
>
<slot :name="`${index + 1}Icon`" />
</span>
</button>
</div>
</template>
<style scoped>
.buttonGroup {
width: max-content;
display: flex;
border-radius: 0.75rem;
position: relative;
}
.button {
position: relative;
display: flex;
gap: 8px;
align-items: center;
user-select: none;
}
.button:hover .background {
filter: brightness(90%);
}
.button:active .background {
filter: brightness(75%);
}
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
.background {
width: 100%;
height: 100%;
position: absolute;
z-index: -2;
top: 0;
left: 0;
transition: filter 0.2s ease-in-out;
}
.icon {
display: flex;
align-items: center;
justify-content: center;
}
.order-1 {
order: -1;
}
.border {
border: 2px solid v-bind(borderColor);
}
.rounded-left {
border-radius: 0.5rem 0 0 0.5rem;
}
.rounded-left-full {
border-radius: v-bind(buttonHeight) 0 0 v-bind(buttonHeight);
}
.rounded-right {
border-radius: 0 0.5rem 0.5rem 0;
}
.rounded-right-full {
border-radius: 0 v-bind(buttonHeight) v-bind(buttonHeight) 0;
}
.rounded-full {
border-radius: v-bind(buttonHeight);
}
.disabled {
pointer-events: none;
background-color: #e1e7f1;
}
.disabled * {
color: #62708c !important;
}