wip bsky client for the web & android bbell.vt3e.cat
at main 236 lines 4.6 kB view raw
1<script setup lang="ts"> 2withDefaults( 3 defineProps<{ 4 variant?: 'primary' | 'secondary' | 'ghost' | 'danger' | 'subtle' | 'subtle-alt' | 'text' 5 size?: 'sm' | 'md' | 'lg' 6 icon?: boolean 7 block?: boolean 8 loading?: boolean 9 disabled?: boolean 10 flat?: boolean 11 type?: 'button' | 'submit' | 'reset' 12 pill?: boolean 13 }>(), 14 { 15 variant: 'primary', 16 size: 'md', 17 type: 'button', 18 disabled: false, 19 }, 20) 21 22const emit = defineEmits<{ 23 (e: 'click', event: MouseEvent): void 24}>() 25</script> 26 27<template> 28 <button 29 :type="type" 30 class="th-btn" 31 :class="[ 32 `variant-${variant}`, 33 `size-${size}`, 34 { 35 'is-icon': icon, 36 'is-block': block, 37 'is-loading': loading, 38 'is-flat': flat, 39 'is-pill': pill, 40 }, 41 ]" 42 :disabled="disabled || loading" 43 @click.stop="emit('click', $event)" 44 > 45 <span v-if="loading" class="spinner"></span> 46 <slot v-else /> 47 </button> 48</template> 49 50<style scoped> 51.th-btn { 52 display: inline-flex; 53 align-items: center; 54 justify-content: center; 55 gap: 0.5rem; 56 border: 1px solid transparent; 57 border-radius: var(--radius-sm); 58 font-family: inherit; 59 font-weight: 600; 60 line-height: 1; 61 cursor: pointer; 62 position: relative; 63 overflow: hidden; 64 65 &.is-flat { 66 border: none !important; 67 } 68 &.is-pill { 69 border-radius: 10rem !important; 70 } 71 72 &:disabled { 73 opacity: 0.5; 74 cursor: not-allowed; 75 pointer-events: none; 76 } 77 78 &.is-block { 79 width: 100%; 80 display: flex; 81 } 82 83 background-color: hsla(var(--bg-colour) / 0.9); 84 color: hsl(var(--text-colour)); 85 /*border-color: hsla(var(--border-colour) / 0.2);*/ 86 87 &:not(.variant-text) { 88 &:hover:not(:disabled) { 89 background-color: hsla(var(--bg-colour) / 1); 90 /*border-color: hsla(var(--border-colour) / 0.5);*/ 91 } 92 93 &:active:not(:disabled) { 94 background-color: hsla(var(--bg-colour) / 0.7); 95 /*border-color: hsla(var(--border-colour) / 0.5);*/ 96 } 97 } 98} 99 100/* Sizes */ 101.size-sm { 102 font-size: 0.75rem; 103 padding: 0.375rem 0.75rem; 104 &.is-icon { 105 padding: 0; 106 width: 2rem; 107 height: 2rem; 108 } 109} 110.size-md { 111 font-size: 0.875rem; 112 padding: 0.625rem 1.25rem; 113 &.is-icon { 114 padding: 0; 115 width: 2.5rem; 116 height: 2.5rem; 117 } 118} 119.size-lg { 120 font-size: 1rem; 121 padding: 0.875rem 1.75rem; 122 &.is-icon { 123 padding: 0; 124 width: 3rem; 125 height: 3rem; 126 } 127} 128 129.th-btn.variant-primary { 130 --bg-colour: var(--accent); 131 --text-colour: var(--base); 132 --border-colour: var(--accent); 133} 134 135.th-btn.variant-secondary { 136 --bg-colour: var(--surface0); 137 --text-colour: var(--text); 138 --border-colour: var(--surface2); 139} 140 141.th-btn.variant-subtle { 142 --bg-colour: var(--accent); 143 --text-colour: var(--accent); 144 --border-colour: var(--accent); 145 146 border-color: hsla(var(--accent) / 0.05); 147 background-color: hsla(var(--accent) / 0.05); 148 149 &:hover:not(:disabled) { 150 background-color: hsla(var(--accent) / 0.15); 151 border-color: hsla(var(--accent) / 0.1); 152 } 153 &:active:not(:disabled) { 154 background-color: hsla(var(--accent) / 0.1); 155 border-color: hsla(var(--accent) / 0.1); 156 } 157} 158 159.th-btn.variant-subtle-alt { 160 border-color: transparent; 161 background-color: hsla(var(--overlay0) / 0.1); 162 color: hsl(var(--subtext0)); 163 164 &:hover:not(:disabled) { 165 background-color: hsla(var(--overlay0) / 0.15); 166 border-color: transparent; 167 } 168 &:active:not(:disabled) { 169 background-color: hsla(var(--overlay0) / 0.075); 170 border-color: transparent; 171 } 172} 173 174.th-btn.variant-ghost { 175 --bg-colour: transparent; 176 --text-colour: var(--subtext0); 177 --border-colour: transparent; 178 179 border-color: transparent; 180 181 &:hover:not(:disabled) { 182 background-color: hsla(var(--surface1) / 0.35); 183 border-color: hsla(var(--surface2) / 0); 184 } 185 &:active:not(:disabled) { 186 background-color: hsla(var(--surface1) / 0.25); 187 border-color: hsla(var(--surface2) / 0); 188 } 189} 190 191.variant-danger { 192 --background-colour: var(--red); 193 --text-colour: var(--red); 194 --border-colour: var(--red); 195 196 border-color: hsla(var(--red) / 0.05); 197 background-color: hsla(var(--red) / 0.25); 198 199 &:hover:not(:disabled) { 200 background-color: hsla(var(--red) / 0.4); 201 border-color: hsla(var(--red) / 0.3); 202 } 203 &:active:not(:disabled) { 204 background-color: hsla(var(--red) / 0.3); 205 border-color: hsla(var(--red) / 0.3); 206 } 207} 208 209.variant-text { 210 background-color: none; 211 color: hsl(var(--text-colour)); 212 border-color: transparent; 213 214 &:hover { 215 color: hsla(var(--text) / 0.9); 216 } 217 &:active { 218 color: hsla(var(--text) / 0.75); 219 } 220} 221 222/* Spinner */ 223.spinner { 224 width: 1em; 225 height: 1em; 226 border: 2px solid currentColor; 227 border-right-color: transparent; 228 border-radius: 50%; 229 animation: spin 0.75s linear infinite; 230} 231@keyframes spin { 232 to { 233 transform: rotate(360deg); 234 } 235} 236</style>