1
0
Fork 0
moritzruth.de/components/MyButton.vue

216 lines
4.2 KiB
Vue

<style scoped lang="scss">
@use "~@/assets/styles/colors";
.my-button {
position: relative;
display: inline-flex;
justify-content: flex-start;
align-items: center;
padding: 8px 12px 8px 20px;
border-radius: 4px;
height: 30px;
background-color: transparent;
border: none;
text-decoration: none;
font: inherit;
color: inherit;
cursor: default;
transition: 140ms ease background-color;
&:hover, &:focus {
&:not(.my-button--disabled) {
background: transparentize(colors.$background-c, 0.94);
}
}
&.my-button--disabled, &.my-button--loading {
&::before {
pointer-events: auto;
opacity: 0.6;
}
}
&.my-button--loading {
&::after {
opacity: 1;
}
}
&.my-button--center {
justify-content: center;
}
}
.my-button::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
pointer-events: none;
background-color: colors.$background;
opacity: 0;
transition: 100ms linear opacity;
}
.my-button::after {
$size: 20px;
pointer-events: none;
opacity: 0;
transition: 100ms linear opacity;
content: "";
position: absolute;
top: calc(50% - #{$size} / 2 + 2px);
left: calc(50% - #{$size} / 2);
width: $size;
height: $size;
border: 2px solid var(--colors-background-c);
border-left-color: transparent;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
from {
transform: rotate(0)
}
to {
transform: rotate(360deg);
}
}
.my-button__text {
text-transform: uppercase;
font-weight: bold;
font-size: 1.2rem;
pointer-events: none;
}
.my-button__prefix {
display: inline-flex;
margin-right: 10px;
margin-left: -10px;
justify-content: center;
& > * {
height: 20px;
}
}
.my-button__suffix {
display: inline-flex;
margin-left: 10px;
justify-content: center;
& > * {
height: 20px;
}
}
</style>
<script>
export default {
name: "MyButton",
props: {
to: { type: String, default: "" },
href: { type: String, default: "" },
loading: { type: Boolean },
disabled: { type: Boolean },
isSubmit: { type: Boolean },
center: { type: Boolean }
},
computed: {
isExternalLink: vm => Boolean(vm.href),
isInternalLink: vm => Boolean(vm.to)
},
methods: {
onClick(event) {
if (!this.disabled && !this.loading)
this.$emit("click", event)
}
},
render(h) {
const children = []
if (this.$slots.prefix) {
children.push(h("div", {
class: "my-button__prefix"
}, this.$slots.prefix))
}
children.push(h("div", {
class: "my-button__text"
}, this.$slots.default))
if (this.$slots.suffix) {
h("div", {
class: "my-button__suffix"
}, this.$slots.suffix)
}
const baseOptions = {
class: ["my-button", {
"my-button--loading": this.loading,
"my-button--disabled": this.disabled,
"my-button--center": this.center
}],
on: {
click: this.onClick
},
directives: [
{
name: "ripple",
modifiers: {
click: true,
400: true
},
value: "rgba(0, 0, 0, 0.2)"
}
],
attrs: {
tabindex: this.disabled || this.loading ? "-1" : "0"
}
}
if (this.isInternalLink) {
return h("nuxt-link", {
...baseOptions,
props: {
to: this.to
}
}, children)
} else if (this.isExternalLink) {
return h("a", {
...baseOptions,
attrs: {
...baseOptions.attrs,
href: this.href,
rel: "noopener"
}
}, children)
}
return h("button", {
...baseOptions,
attrs: {
...baseOptions.attrs,
disabled: this.disabled,
type: this.isSubmit ? "submit" : "button"
}
}, children)
}
}
</script>