this repo has no description
1<script setup lang="ts">
2import { computed } from "vue";
3
4const props = defineProps<{
5 variant?: "default" | "accent" | "danger" | "ghost";
6 size?: "sm" | "md" | "lg";
7 disabled?: boolean;
8 type?: "button" | "submit" | "reset";
9 url?: string;
10}>();
11
12const emit = defineEmits<{
13 click: [event: MouseEvent];
14}>();
15
16const urlIsExternal = computed(() => props.url?.startsWith("http"));
17</script>
18
19<template>
20 <Component
21 :is="url ? urlIsExternal ? 'a' : 'router-link' : 'button'"
22 :href="url"
23 :to="url && !urlIsExternal ? url : undefined"
24 :class="[
25 'app-button',
26 `variant-${variant || 'default'}`,
27 `size-${size || 'md'}`,
28 { disabled }
29 ]"
30 :disabled="disabled"
31 :type="type || 'button'"
32 @click="emit('click', $event)"
33 >
34 <slot></slot>
35 </Component>
36</template>
37
38<style lang="scss" scoped>
39.app-button {
40 font-family: inherit;
41 border-radius: 0.375rem;
42 font-weight: 500;
43 display: inline-flex;
44 align-items: center;
45 justify-content: center;
46 transition: all 0.2s ease;
47 cursor: pointer;
48 border: 1px solid transparent;
49
50 &.variant-default {
51 background-color: hsl(var(--surface0));
52 color: hsl(var(--text));
53
54 &:hover:not(:disabled) {
55 background-color: hsl(var(--surface1));
56 }
57
58 &:active:not(:disabled) {
59 background-color: hsl(var(--surface2));
60 }
61 }
62
63 &.variant-accent {
64 background-color: hsl(var(--accent));
65 color: hsl(var(--text-on-accent));
66
67 &:hover:not(:disabled) {
68 opacity: 0.9;
69 }
70
71 &:active:not(:disabled) {
72 opacity: 0.8;
73 }
74 }
75
76 &.variant-danger {
77 background-color: hsl(var(--red));
78 color: hsl(var(--crust));
79
80 &:hover:not(:disabled) {
81 opacity: 0.9;
82 }
83
84 &:active:not(:disabled) {
85 opacity: 0.8;
86 }
87 }
88
89 &.variant-ghost {
90 background-color: transparent;
91 color: hsl(var(--text));
92
93 &:hover:not(:disabled) {
94 background-color: hsla(var(--overlay0) / 0.2);
95 }
96
97 &:active:not(:disabled) {
98 background-color: hsla(var(--overlay0) / 0.3);
99 }
100 }
101
102 &:focus-visible {
103 outline: 2px solid hsl(var(--accent));
104 outline-offset: 1px;
105 }
106
107 &:disabled {
108 opacity: 0.5;
109 cursor: not-allowed;
110 }
111
112 &.size-sm {
113 padding: 0.25rem 0.5rem;
114 font-size: 0.875rem;
115 }
116
117 &.size-md {
118 padding: 0.5rem 1rem;
119 font-size: 1rem;
120 }
121
122 &.size-lg {
123 padding: 0.75rem 1.5rem;
124 font-size: 1.125rem;
125 }
126}
127
128a {
129 text-decoration: none;
130}
131
132</style>