forked from blisstown/campfire
Button component improvements
buttons with a `href` now render as <a> elements, otherwise <button>
This commit is contained in:
parent
d0163ee094
commit
77665702b7
4 changed files with 64 additions and 72 deletions
|
@ -5,48 +5,48 @@
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
let className = "";
|
||||||
|
export { className as class };
|
||||||
export let active = false;
|
export let active = false;
|
||||||
export let filled = false;
|
export let filled = false;
|
||||||
export let disabled = false;
|
export let disabled = false;
|
||||||
export let centered = false;
|
export let centered = false;
|
||||||
export let label = undefined;
|
export let label = undefined;
|
||||||
export let sound = "default";
|
export let sound = "default";
|
||||||
export let href = false;
|
export let href = undefined;
|
||||||
|
export let onClick = undefined;
|
||||||
|
|
||||||
let classes = [];
|
let classes = [];
|
||||||
|
|
||||||
function click() {
|
function click() {
|
||||||
if (disabled) return;
|
if (disabled) return;
|
||||||
if (href) {
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = href;
|
|
||||||
link.dispatchEvent(new MouseEvent('click', {
|
|
||||||
bubbles: true,
|
|
||||||
cancelable: true,
|
|
||||||
view: window,
|
|
||||||
ctrlKey: event.ctrlKey,
|
|
||||||
metaKey: event.metaKey,
|
|
||||||
shiftKey: event.shiftKey,
|
|
||||||
altKey: event.altKey,
|
|
||||||
button: event.button,
|
|
||||||
}));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
playSound(sound);
|
playSound(sound);
|
||||||
dispatch('click');
|
dispatch('click');
|
||||||
}
|
}
|
||||||
|
|
||||||
afterUpdate(() => {
|
afterUpdate(() => {
|
||||||
classes = [];
|
classes = className.split(' ');
|
||||||
if (active) classes = ["active"];
|
if (active) classes.push("active");
|
||||||
if (filled) classes = ["filled"];
|
if (filled) classes.push("filled");
|
||||||
if (disabled) classes = ["disabled"];
|
if (disabled) classes.push("disabled");
|
||||||
if (centered) classes.push("centered");
|
if (centered) classes.push("centered");
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button
|
{#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"
|
type="button"
|
||||||
class={classes.join(' ')}
|
class={classes.join(' ')}
|
||||||
title={label}
|
title={label}
|
||||||
|
@ -56,11 +56,11 @@
|
||||||
<slot name="icon" />
|
<slot name="icon" />
|
||||||
</span>
|
</span>
|
||||||
<slot/>
|
<slot/>
|
||||||
</button>
|
</button>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
button {
|
a, button {
|
||||||
width: 100%;
|
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
padding: .7em .8em;
|
padding: .7em .8em;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -71,6 +71,7 @@
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 2px solid var(--bg-700);
|
border: 2px solid var(--bg-700);
|
||||||
|
@ -84,22 +85,32 @@
|
||||||
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
a {
|
||||||
|
width: calc(100% - 1.6em);
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.centered,
|
||||||
button.centered {
|
button.centered {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a:hover,
|
||||||
button:hover {
|
button:hover {
|
||||||
border-color: color-mix(in srgb, var(--bg-700), black 10%);
|
border-color: color-mix(in srgb, var(--bg-700), black 10%);
|
||||||
background-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 {
|
button:active {
|
||||||
border-color: color-mix(in srgb, var(--bg-700), black 20%);
|
border-color: color-mix(in srgb, var(--bg-700), black 20%);
|
||||||
background-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 {
|
button.active {
|
||||||
background-color: var(--bg-600);
|
background-color: var(--bg-600);
|
||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
|
@ -107,34 +118,40 @@
|
||||||
text-shadow: 0px 2px 32px var(--accent);
|
text-shadow: 0px 2px 32px var(--accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.active:hover,
|
||||||
button.active:hover {
|
button.active:hover {
|
||||||
color: color-mix(in srgb, var(--accent), var(--bg-1000) 20%);
|
color: color-mix(in srgb, var(--accent), var(--bg-1000) 20%);
|
||||||
border-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%);
|
background-color: color-mix(in srgb, var(--bg-600), var(--accent) 10%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.active:active,
|
||||||
button.active:active {
|
button.active:active {
|
||||||
color: color-mix(in srgb, var(--accent), var(--bg-800) 10%);
|
color: color-mix(in srgb, var(--accent), var(--bg-800) 10%);
|
||||||
border-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%);
|
background-color: color-mix(in srgb, var(--bg-600), var(--bg-800) 10%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.filled,
|
||||||
button.filled {
|
button.filled {
|
||||||
background-color: var(--accent);
|
background-color: var(--accent);
|
||||||
color: var(--bg-800);
|
color: var(--bg-800);
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.filled:hover,
|
||||||
button.filled:hover {
|
button.filled:hover {
|
||||||
color: color-mix(in srgb, var(--bg-800), white 10%);
|
color: color-mix(in srgb, var(--bg-800), white 10%);
|
||||||
background-color: color-mix(in srgb, var(--accent), white 20%);
|
background-color: color-mix(in srgb, var(--accent), white 20%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.filled:active,
|
||||||
button.filled:active {
|
button.filled:active {
|
||||||
color: color-mix(in srgb, var(--bg-800), black 10%);
|
color: color-mix(in srgb, var(--bg-800), black 10%);
|
||||||
background-color: color-mix(in srgb, var(--accent), black 20%);
|
background-color: color-mix(in srgb, var(--accent), black 20%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.disabled,
|
||||||
button.disabled {
|
button.disabled {
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
opacity: .5;
|
opacity: .5;
|
||||||
|
|
|
@ -32,35 +32,6 @@
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
function handle_btn(name) {
|
|
||||||
if (!$account) return;
|
|
||||||
let route;
|
|
||||||
switch (name) {
|
|
||||||
case "timeline":
|
|
||||||
route = "/";
|
|
||||||
getTimeline(true);
|
|
||||||
break;
|
|
||||||
case "notifications":
|
|
||||||
route = "/notifications";
|
|
||||||
notifications.set([]);
|
|
||||||
getNotifications();
|
|
||||||
break;
|
|
||||||
case "explore":
|
|
||||||
case "lists":
|
|
||||||
case "favourites":
|
|
||||||
case "bookmarks":
|
|
||||||
case "hashtags":
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!route) return;
|
|
||||||
window.scrollTo({
|
|
||||||
top: 0,
|
|
||||||
behavior: "smooth"
|
|
||||||
});
|
|
||||||
goto(route);
|
|
||||||
}
|
|
||||||
|
|
||||||
function gotoProfile() {
|
function gotoProfile() {
|
||||||
if (!$account) return;
|
if (!$account) return;
|
||||||
playSound();
|
playSound();
|
||||||
|
@ -102,7 +73,7 @@
|
||||||
{#if $account}
|
{#if $account}
|
||||||
<div id="nav-items">
|
<div id="nav-items">
|
||||||
<Button label="Timeline"
|
<Button label="Timeline"
|
||||||
on:click={() => handle_btn("timeline")}
|
href="/")}
|
||||||
active={$page.url.pathname === "/"}>
|
active={$page.url.pathname === "/"}>
|
||||||
<svelte:fragment slot="icon">
|
<svelte:fragment slot="icon">
|
||||||
<TimelineIcon/>
|
<TimelineIcon/>
|
||||||
|
@ -110,7 +81,7 @@
|
||||||
{lang.string('navigation.timeline')}
|
{lang.string('navigation.timeline')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button label="Notifications"
|
<Button label="Notifications"
|
||||||
on:click={() => handle_btn("notifications")}
|
href="notifications"}
|
||||||
active={$page.url.pathname === "/notifications"}>
|
active={$page.url.pathname === "/notifications"}>
|
||||||
<svelte:fragment slot="icon">
|
<svelte:fragment slot="icon">
|
||||||
<NotificationsIcon/>
|
<NotificationsIcon/>
|
||||||
|
@ -183,7 +154,7 @@
|
||||||
<div id="account-button">
|
<div id="account-button">
|
||||||
<img src={$account.avatar_url} class="account-avatar" height="64px" alt="" aria-hidden="true" on:click={() => gotoProfile()}>
|
<img src={$account.avatar_url} class="account-avatar" height="64px" alt="" aria-hidden="true" on:click={() => gotoProfile()}>
|
||||||
<div class="account-name" aria-hidden="true">
|
<div class="account-name" aria-hidden="true">
|
||||||
<a href="/{$server.host}/{$account.username}" class="nickname" title={$account.nickname}>{@html $account.rich_name}</a>
|
<a href="/{$server.host}/@{$account.username}" class="nickname" title={$account.nickname}>{@html $account.rich_name}</a>
|
||||||
<span class="username" title={`@${$account.username}@${$account.host}`}>
|
<span class="username" title={`@${$account.username}@${$account.host}`}>
|
||||||
{$account.fqn}
|
{$account.fqn}
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -12,12 +12,12 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class={"post-header-container" + (reply ? " reply" : "")}>
|
<div class={"post-header-container" + (reply ? " reply" : "")}>
|
||||||
<a href="/{$server.host}/{post.account.fqn}" class="post-avatar-container" on:mouseup|stopPropagation>
|
<a href="/{$server.host}/@{post.account.fqn}" class="post-avatar-container" on:mouseup|stopPropagation>
|
||||||
<img src={post.account.avatar_url} type={post.account.avatar_type} alt="" width="48" height="48" class="post-avatar" loading="lazy" decoding="async">
|
<img src={post.account.avatar_url} type={post.account.avatar_type} alt="" width="48" height="48" class="post-avatar" loading="lazy" decoding="async">
|
||||||
</a>
|
</a>
|
||||||
<header class="post-header">
|
<header class="post-header">
|
||||||
<div class="post-user-info" on:mouseup|stopPropagation>
|
<div class="post-user-info" on:mouseup|stopPropagation>
|
||||||
<a href="/{$server.host}/{post.account.fqn}" class="name">{@html post.account.rich_name}</a>
|
<a href="/{$server.host}/@{post.account.fqn}" class="name">{@html post.account.rich_name}</a>
|
||||||
<span class="username">{post.account.mention}</span>
|
<span class="username">{post.account.mention}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="post-info" on:mouseup|stopPropagation>
|
<div class="post-info" on:mouseup|stopPropagation>
|
||||||
|
|
|
@ -78,7 +78,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
<div class="profile-actions">
|
<div class="profile-actions">
|
||||||
{#if $account && profile.fqn !== $account.fqn}
|
{#if $account && profile.fqn !== $account.fqn}
|
||||||
<Button disabled filled label="{lang.string('profile.follow')} {profile.nickname}" class="profile-btn-follow">
|
<Button filled label="{lang.string('profile.follow')} {profile.nickname}" class="profile-btn-follow">
|
||||||
{lang.string('profile.follow')}
|
{lang.string('profile.follow')}
|
||||||
</Button>
|
</Button>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -186,13 +186,17 @@
|
||||||
gap: .5rem;
|
gap: .5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile-btn-follow {
|
.profile-actions :global(button.profile-btn-follow) {
|
||||||
padding: 0 32px;
|
padding: 0 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile-actions :global(button) {
|
.profile-actions :global(a) {
|
||||||
height: 42px;
|
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
.profile-actions :global(button) {
|
||||||
|
width: fit-content;
|
||||||
|
height: 42px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile-post-categories {
|
.profile-post-categories {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue