client/components/button-fill.vue (194 lines of code) (raw):
<script>
// Copyright (c) 2017-2024 Uber Technologies Inc.
//
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
const COLOR_TYPE_DEFAULT = 'primary';
const COLOR_TYPES = ['primary', 'secondary', 'tertiary'];
const SIZE_TYPE_DEFAULT = 'medium';
const SIZE_TYPES = ['small', 'medium', 'large'];
const TAG_TYPE_DEFAULT = 'button';
const TAG_LINK_TYPES = ['a', 'router-link'];
export default {
name: 'button-fill',
props: {
active: {
type: Boolean,
default: false,
},
color: {
type: String,
default: COLOR_TYPE_DEFAULT,
validator: value => COLOR_TYPES.includes(value),
},
disabled: {
type: Boolean,
default: false,
},
disabledLabel: {
type: String,
},
enabled: {
type: Boolean,
default: true,
},
href: {
type: String,
},
label: {
type: String,
},
size: {
type: String,
default: SIZE_TYPE_DEFAULT,
validator: value => SIZE_TYPES.includes(value),
},
tag: {
type: String,
default: TAG_TYPE_DEFAULT,
},
to: {
type: [String, Object],
},
uppercase: {
type: Boolean,
default: false,
},
},
computed: {
computedTag() {
const { isDisabled, tag } = this;
if (isDisabled && TAG_LINK_TYPES.includes(tag)) {
return 'button';
}
return tag;
},
disabledLabelText() {
const { isDisabled, disabledLabel } = this;
return isDisabled ? disabledLabel : '';
},
isDisabled() {
const { disabled, enabled } = this;
return disabled || !enabled;
},
},
methods: {
onClick(...args) {
const { isDisabled } = this;
if (!isDisabled) {
this.$emit('click', ...args);
}
},
},
};
</script>
<template>
<component
:aria-disabled="isDisabled"
class="button-fill"
:class="{
active,
[color]: color,
disabled: isDisabled,
[size]: size,
uppercase,
}"
:disabled="isDisabled"
:href="href"
:is="computedTag"
:to="to"
:title="disabledLabelText"
@click="onClick"
>
{{ label }}
</component>
</template>
<style lang="stylus">
.button-fill {
border: none;
color: #fff !important;
cursor: pointer;
display: inline-block;
font-weight: 600;
transition: all 400ms ease;
white-space: nowrap;
&:focus {
outline: none;
}
&.disabled {
opacity: 0.5;
cursor: not-allowed;
}
// color
&.primary {
background-color: #11939a;
&.active {
background-color: #0e767b;
}
&:focus, &:hover {
background-color: #10858b;
}
&:active {
background-color: #0e767b;
}
}
&.secondary {
background-color: #ca3b27;
&.active {
background-color: #a22f1f;
}
&:focus, &:hover {
background-color: #b63523;
}
&:active {
background-color: #a22f1f;
}
}
&.tertiary {
background-color: transparent;
color: #11939a !important;
&.active {
color: #0e767b !important;
}
&:focus, &:hover {
color: #10858b !important;
}
&:active {
color: #0e767b !important;
}
}
// size
&.small {
font-size: 12px;
padding: 6px 10px;
}
&.medium {
font-size: 14px;
padding: 13px 21px;
}
&.large {
font-size: 26px;
padding: 26px 42px;
}
// uppercase
&.uppercase {
text-transform: uppercase;
}
}
</style>