mirror of
https://github.com/imputnet/cobalt.git
synced 2025-01-15 11:25:17 +00:00
web/SectionHeading: reusable component for linkable section headings
This commit is contained in:
parent
503514d98e
commit
1a845fcfc2
|
@ -7,6 +7,7 @@
|
||||||
"download": "download",
|
"download": "download",
|
||||||
"share": "share",
|
"share": "share",
|
||||||
"copy": "copy",
|
"copy": "copy",
|
||||||
|
"copy.section": "copy the section link",
|
||||||
"copied": "copied",
|
"copied": "copied",
|
||||||
"import": "import",
|
"import": "import",
|
||||||
"continue": "continue",
|
"continue": "continue",
|
||||||
|
|
95
web/src/components/misc/SectionHeading.svelte
Normal file
95
web/src/components/misc/SectionHeading.svelte
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { page } from "$app/stores";
|
||||||
|
import { t } from "$lib/i18n/translations";
|
||||||
|
import { copyURL } from "$lib/download";
|
||||||
|
|
||||||
|
import CopyIcon from "$components/misc/CopyIcon.svelte";
|
||||||
|
|
||||||
|
export let title: string;
|
||||||
|
export let sectionId: string;
|
||||||
|
export let beta = false;
|
||||||
|
|
||||||
|
let copied = false;
|
||||||
|
|
||||||
|
$: if (copied) {
|
||||||
|
setTimeout(() => {
|
||||||
|
copied = false;
|
||||||
|
}, 1500);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="heading-container">
|
||||||
|
<h3 class="content-title">{title}</h3>
|
||||||
|
{#if beta}
|
||||||
|
<div class="beta-label">{$t("general.beta")}</div>
|
||||||
|
{/if}
|
||||||
|
<button
|
||||||
|
class="link-copy"
|
||||||
|
aria-label={copied ? $t("button.copied") : $t("button.copy.section")}
|
||||||
|
on:click={() => {
|
||||||
|
copied = true;
|
||||||
|
copyURL(`${$page.url.origin}${$page.url.pathname}#${sectionId}`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CopyIcon check={copied} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.heading-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 6px;
|
||||||
|
justify-content: start;
|
||||||
|
align-items: center;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-copy {
|
||||||
|
background: transparent;
|
||||||
|
padding: 2px;
|
||||||
|
box-shadow: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
transition: opacity 0.1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-copy :global(.copy-animation) {
|
||||||
|
width: 17px;
|
||||||
|
height: 17px;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-copy :global(.copy-animation *) {
|
||||||
|
width: 17px;
|
||||||
|
height: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-copy :global(.copy-animation):hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.beta-label {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 0 5px;
|
||||||
|
background: var(--secondary);
|
||||||
|
color: var(--primary);
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 2;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (hover: hover) {
|
||||||
|
.link-copy:not(:focus-visible) {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading-container:hover .link-copy {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,8 +1,8 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { page } from "$app/stores";
|
import { page } from "$app/stores";
|
||||||
import { t } from "$lib/i18n/translations";
|
|
||||||
import { copyURL as _copyURL } from "$lib/download";
|
import { copyURL as _copyURL } from "$lib/download";
|
||||||
import CopyIcon from "$components/misc/CopyIcon.svelte";
|
|
||||||
|
import SectionHeading from "$components/misc/SectionHeading.svelte";
|
||||||
|
|
||||||
export let title: string;
|
export let title: string;
|
||||||
export let sectionId: string;
|
export let sectionId: string;
|
||||||
|
@ -11,11 +11,7 @@
|
||||||
export let beta = false;
|
export let beta = false;
|
||||||
|
|
||||||
let focus = false;
|
let focus = false;
|
||||||
let animate = false;
|
|
||||||
let copied = false;
|
let copied = false;
|
||||||
let showCopy = false;
|
|
||||||
|
|
||||||
const copyURL = () => _copyURL(`${$page.url.origin}${$page.url.pathname}#${sectionId}`);
|
|
||||||
|
|
||||||
$: hash = $page.url.hash.replace("#", "");
|
$: hash = $page.url.hash.replace("#", "");
|
||||||
|
|
||||||
|
@ -37,55 +33,11 @@
|
||||||
class:disabled
|
class:disabled
|
||||||
aria-hidden={disabled}
|
aria-hidden={disabled}
|
||||||
>
|
>
|
||||||
<div
|
<SectionHeading {title} {sectionId} {beta} />
|
||||||
class="settings-content-header"
|
|
||||||
on:mouseenter={() => showCopy = true}
|
|
||||||
on:mouseleave={() => showCopy = false}
|
|
||||||
role="link"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
<h3 class="settings-content-title">{title}</h3>
|
|
||||||
{#if beta}
|
|
||||||
<div class="beta-label">{$t("general.beta")}</div>
|
|
||||||
{/if}
|
|
||||||
{#if showCopy}
|
|
||||||
<button
|
|
||||||
class="settings-link-copy"
|
|
||||||
on:click={() => {
|
|
||||||
copied = true;
|
|
||||||
copyURL();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<CopyIcon check={copied} />
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.settings-link-copy {
|
|
||||||
background: transparent;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.settings-link-copy :global(.copy-animation) {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.settings-link-copy :global(.copy-animation *) {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.settings-link-copy :global(.copy-animation):hover {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.settings-content {
|
.settings-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -134,27 +86,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-content-header {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.beta-label {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 0 5px;
|
|
||||||
background: var(--secondary);
|
|
||||||
color: var(--primary);
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 0;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 750px) {
|
@media screen and (max-width: 750px) {
|
||||||
.settings-content {
|
.settings-content {
|
||||||
padding: var(--padding);
|
padding: var(--padding);
|
||||||
|
|
Loading…
Reference in a new issue