campfire/src/lib/ui/Button.svelte

175 lines
4.3 KiB
Svelte
Raw Normal View History

<script>
import { playSound } from '../sound.js';
import { createEventDispatcher } from 'svelte';
import { afterUpdate } from 'svelte';
const dispatch = createEventDispatcher();
let className = "";
export { className as class };
export let active = false;
export let filled = false;
export let disabled = false;
export let centered = false;
export let label = undefined;
export let sound = "default";
export let href = undefined;
export let onClick = undefined;
let classes = [];
function click() {
if (disabled) return;
playSound(sound);
dispatch('click');
}
afterUpdate(() => {
classes = className.split(' ');
if (active) classes.push("active");
if (filled) classes.push("filled");
if (disabled) classes.push("disabled");
if (centered) classes.push("centered");
});
</script>
{#if href}
<a
class={classes.join(' ')}
title={label}
aria-label={label}
href={href}
on:click={() => click()}>
<span class="icon">
<slot name="icon" />
</span>
<slot/>
</a>
{:else}
<button
type="button"
class={classes.join(' ')}
title={label}
aria-label={label}
on:click={() => click()}>
<span class="icon">
<slot name="icon" />
</span>
<slot/>
</button>
{/if}
<style>
a, button {
2025-07-10 22:32:54 +01:00
height: fit-content;
padding: .7em .8em;
display: flex;
flex-direction: row;
align-items: center;
font-family: inherit;
font-size: 1rem;
font-weight: 600;
text-align: left;
text-decoration: none;
border-radius: 8px;
2025-07-10 22:32:54 +01:00
border: 2px solid var(--bg-700);
background-color: var(--bg-700);
color: var(--text);
transition-property: border-color, background-color, color;
transition-timing-function: ease-out;
transition-duration: .1s;
cursor: pointer;
}
a {
width: calc(100% - 1.6em);
}
button {
width: 100%;
}
a.centered,
button.centered {
text-align: center;
justify-content: center;
}
a:hover,
button:hover {
border-color: color-mix(in srgb, var(--bg-700), black 10%);
background-color: color-mix(in srgb, var(--bg-700), black 10%);
}
a:active,
button:active {
border-color: color-mix(in srgb, var(--bg-700), black 20%);
background-color: color-mix(in srgb, var(--bg-700), black 20%);
}
a.active,
button.active {
background-color: var(--bg-600);
color: var(--accent);
border-color: var(--accent);
text-shadow: 0px 2px 32px var(--accent);
}
a.active:hover,
button.active:hover {
color: color-mix(in srgb, var(--accent), var(--bg-1000) 20%);
border-color: color-mix(in srgb, var(--accent), var(--bg-1000) 20%);
background-color: color-mix(in srgb, var(--bg-600), var(--accent) 10%);
}
a.active:active,
button.active:active {
color: color-mix(in srgb, var(--accent), var(--bg-800) 10%);
border-color: color-mix(in srgb, var(--accent), var(--bg-800) 10%);
background-color: color-mix(in srgb, var(--bg-600), var(--bg-800) 10%);
}
a.filled,
button.filled {
background-color: var(--accent);
color: var(--bg-800);
border-color: transparent;
}
a.filled:not(.disabled):hover,
button.filled:not(.disabled):hover {
color: color-mix(in srgb, var(--bg-800), white 10%);
background-color: color-mix(in srgb, var(--accent), white 20%);
}
a.filled:not(.disabled):active,
button.filled:not(.disabled):active {
color: color-mix(in srgb, var(--bg-800), black 10%);
background-color: color-mix(in srgb, var(--accent), black 20%);
}
a.disabled,
button.disabled {
color: var(--text);
2025-07-14 18:48:31 +01:00
opacity: .35;
border-color: transparent;
cursor: not-allowed;
}
2024-06-30 19:57:32 +01:00
.icon:not(:empty) {
2025-07-10 22:32:54 +01:00
height: 1.8em;
2024-06-30 19:57:32 +01:00
margin-right: 8px;
}
.icon :global(svg) {
height: 100%;
}
.centered .icon {
margin-right: 0px;
}
</style>