167 lines
2.9 KiB
Vue
167 lines
2.9 KiB
Vue
<template>
|
|
<button
|
|
:class="[
|
|
bem.b(),
|
|
bem.exp(!!type, bem.m(`type_${type!}`)),
|
|
bem.exp(!!size, bem.m(`size_${size!}`)),
|
|
bem.is('icon-only', iconOnly),
|
|
bem.is('loading', loading),
|
|
bem.is('disabled', disabled),
|
|
bem.is('full', full),
|
|
]"
|
|
:disabled="disabled"
|
|
:type="nativeType"
|
|
>
|
|
<!-- <ChadSpinner v-if="loading" class="chad-button__spinner" /> -->
|
|
|
|
<!-- <template v-else> -->
|
|
<Component :is="icon" v-if="icon" :class="bem.e('icon')" />
|
|
|
|
<span v-if="$slots.default">
|
|
<slot />
|
|
</span>
|
|
<!-- </template> -->
|
|
</button>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import type { Component } from 'vue'
|
|
import useBem from '@shared/composables/use-bem.ts'
|
|
import { computed, useSlots } from 'vue'
|
|
|
|
defineOptions({
|
|
name: 'ChadButton',
|
|
})
|
|
|
|
const props = withDefaults(
|
|
defineProps<ChadButtonProps>(),
|
|
{
|
|
nativeType: 'button',
|
|
},
|
|
)
|
|
|
|
export interface ChadButtonProps {
|
|
loading?: boolean
|
|
disabled?: boolean
|
|
type?: 'secondary' | 'danger'
|
|
nativeType?: 'button' | 'submit'
|
|
icon?: Component
|
|
full?: boolean
|
|
size?: 'sm' | 'lg'
|
|
}
|
|
|
|
const slots = useSlots()
|
|
const bem = useBem('chad-button')
|
|
|
|
const iconOnly = computed(() => {
|
|
return !slots.default && props.icon
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.chad-button {
|
|
$self: &;
|
|
|
|
@include font-display-14;
|
|
|
|
flex-shrink: 0;
|
|
border: none;
|
|
color: var(--ink);
|
|
padding: 0 var(--space-3);
|
|
height: 36px;
|
|
background-color: var(--yellow);
|
|
font-weight: 700;
|
|
text-align: center;
|
|
cursor: pointer;
|
|
outline: var(--border-w) solid var(--ink);
|
|
outline-offset: calc(var(--border-w) * -1);
|
|
|
|
&.is-full:not(.is-icon-only) {
|
|
width: 100%;
|
|
}
|
|
|
|
&.is-icon-only {
|
|
padding: 0;
|
|
aspect-ratio: 1;
|
|
}
|
|
|
|
&:not(:disabled) {
|
|
&:hover,
|
|
&:focus {
|
|
background-color: var(--yellow-deep);
|
|
}
|
|
|
|
&:active {
|
|
background-color: var(--ink);
|
|
color: var(--yellow);
|
|
}
|
|
}
|
|
|
|
&--size_sm {
|
|
@include font-body-bold;
|
|
|
|
height: 28px;
|
|
outline-width: 1px;
|
|
outline-offset: -1px;
|
|
}
|
|
|
|
&--size_lg {
|
|
height: 44px;
|
|
}
|
|
|
|
&--type_secondary {
|
|
background-color: var(--paper);
|
|
|
|
&:not(:disabled) {
|
|
&:hover,
|
|
&:focus {
|
|
background-color: var(--grey-2);
|
|
}
|
|
|
|
&:active {
|
|
background-color: var(--yellow);
|
|
color: var(--ink);
|
|
}
|
|
}
|
|
}
|
|
|
|
&--type_danger {
|
|
outline-color: var(--red);
|
|
background-color: var(--paper);
|
|
color: var(--red);
|
|
|
|
&:not(:disabled) {
|
|
&:hover,
|
|
&:focus,
|
|
&:active {
|
|
background-color: var(--red);
|
|
color: var(--white);
|
|
}
|
|
}
|
|
}
|
|
|
|
&:disabled {
|
|
cursor: not-allowed;
|
|
opacity: 0.6;
|
|
}
|
|
|
|
&.is-loading {
|
|
--stripe-width: 44px;
|
|
|
|
@include diagonal-stripes;
|
|
|
|
pointer-events: none;
|
|
}
|
|
|
|
&__icon {
|
|
&:not(:last-child) {
|
|
margin-right: var(--space-1);
|
|
}
|
|
|
|
#{$self}--size_sm & {
|
|
width: 16px;
|
|
}
|
|
}
|
|
}
|
|
</style>
|