mirror of
https://github.com/imputnet/cobalt.git
synced 2025-06-28 09:28:29 +00:00
204 lines
4.9 KiB
Svelte
204 lines
4.9 KiB
Svelte
<script lang="ts">
|
|
import { t } from "$lib/i18n/translations";
|
|
import cachedInfo from "$lib/state/server-info";
|
|
import { getServerInfo } from "$lib/api/server-info";
|
|
|
|
import type { SvelteComponent } from "svelte";
|
|
|
|
import Skeleton from "$components/misc/Skeleton.svelte";
|
|
import IconPlus from "@tabler/icons-svelte/IconPlus.svelte";
|
|
import PopoverContainer from "$components/misc/PopoverContainer.svelte";
|
|
|
|
let services: string[] = [];
|
|
|
|
let popover: SvelteComponent;
|
|
$: expanded = false;
|
|
|
|
let servicesContainer: HTMLDivElement;
|
|
$: loaded = false;
|
|
|
|
const loadInfo = async () => {
|
|
await getServerInfo();
|
|
|
|
if ($cachedInfo) {
|
|
loaded = true;
|
|
services = $cachedInfo.info.cobalt.services;
|
|
}
|
|
};
|
|
|
|
const popoverAction = async () => {
|
|
expanded = !expanded;
|
|
if (expanded && services.length === 0) {
|
|
await loadInfo();
|
|
}
|
|
if (expanded) {
|
|
servicesContainer.focus();
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<div id="supported-services" class:expanded>
|
|
<button
|
|
id="services-button"
|
|
class="button"
|
|
on:click={popoverAction}
|
|
aria-label={$t(`save.services.title_${expanded ? "hide" : "show"}`)}
|
|
>
|
|
<div class="expand-icon">
|
|
<IconPlus />
|
|
</div>
|
|
<span class="title">{$t("save.services.title")}</span>
|
|
</button>
|
|
|
|
<PopoverContainer
|
|
bind:this={popover}
|
|
id="services-popover"
|
|
{expanded}
|
|
>
|
|
<div
|
|
id="services-container"
|
|
bind:this={servicesContainer}
|
|
tabindex="-1"
|
|
data-focus-ring-hidden
|
|
>
|
|
{#if loaded}
|
|
{#each services as service}
|
|
<div class="service-item">{service}</div>
|
|
{/each}
|
|
{:else}
|
|
{#each { length: 17 } as _}
|
|
<Skeleton
|
|
class="elevated"
|
|
width={Math.random() * 44 + 50 + "px"}
|
|
height="24.5px"
|
|
/>
|
|
{/each}
|
|
{/if}
|
|
</div>
|
|
<div id="services-disclaimer" class="subtext">
|
|
{$t("save.services.disclaimer")}
|
|
</div>
|
|
</PopoverContainer>
|
|
</div>
|
|
|
|
<style>
|
|
#supported-services {
|
|
display: flex;
|
|
position: relative;
|
|
max-width: 400px;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
height: 35px;
|
|
}
|
|
|
|
#services-button {
|
|
gap: 9px;
|
|
padding: 7px 13px 7px 10px;
|
|
justify-content: flex-start;
|
|
border-radius: 18px;
|
|
display: flex;
|
|
flex-direction: row;
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
background: none;
|
|
transition: background 0.2s, box-shadow 0.1s;
|
|
}
|
|
|
|
#services-button:not(:focus-visible):not(:active) {
|
|
box-shadow: none;
|
|
}
|
|
|
|
.expand-icon {
|
|
height: 22px;
|
|
width: 22px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 18px;
|
|
background: var(--button-elevated);
|
|
padding: 0;
|
|
box-shadow: none;
|
|
transition: background 0.2s, transform 0.2s;
|
|
}
|
|
|
|
#services-button:active {
|
|
background: var(--button-hover-transparent);
|
|
}
|
|
|
|
@media (hover: hover) {
|
|
#services-button:hover {
|
|
background: var(--button-hover-transparent);
|
|
}
|
|
|
|
#services-button:active {
|
|
background: var(--button-press-transparent);
|
|
}
|
|
|
|
#services-button:hover .expand-icon {
|
|
background: var(--button-elevated-hover);
|
|
}
|
|
}
|
|
|
|
@media (hover: none) {
|
|
#services-button:active {
|
|
box-shadow: none;
|
|
}
|
|
}
|
|
|
|
#services-button:active .expand-icon {
|
|
background: var(--button-elevated-press);
|
|
}
|
|
|
|
.expand-icon :global(svg) {
|
|
height: 18px;
|
|
width: 18px;
|
|
stroke-width: 2px;
|
|
color: var(--secondary);
|
|
will-change: transform;
|
|
}
|
|
|
|
.expanded .expand-icon {
|
|
transform: rotate(45deg);
|
|
}
|
|
|
|
#services-container {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
flex-direction: row;
|
|
gap: 3px;
|
|
}
|
|
|
|
.service-item {
|
|
display: flex;
|
|
padding: 4px 8px;
|
|
border-radius: calc(var(--border-radius) / 2);
|
|
background: var(--button-elevated);
|
|
font-size: 12.5px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
#services-disclaimer {
|
|
padding: 0;
|
|
user-select: none;
|
|
-webkit-user-select: none;
|
|
}
|
|
|
|
.expanded #services-disclaimer {
|
|
padding: 0;
|
|
user-select: text;
|
|
-webkit-user-select: text;
|
|
}
|
|
|
|
@media screen and (max-width: 535px) {
|
|
.expand-icon {
|
|
height: 21px;
|
|
width: 21px;
|
|
}
|
|
|
|
.expand-icon :global(svg) {
|
|
height: 16px;
|
|
width: 16px;
|
|
}
|
|
}
|
|
</style>
|