mirror of https://github.com/VERT-sh/VERT.git
fix: card, tooltip, and scrollbar fixes
This commit is contained in:
parent
8c182457fe
commit
bc055e6b98
|
@ -4,15 +4,47 @@
|
||||||
interface Props {
|
interface Props {
|
||||||
children: () => any;
|
children: () => any;
|
||||||
text: string;
|
text: string;
|
||||||
|
className?: string;
|
||||||
position?: "top" | "bottom" | "left" | "right";
|
position?: "top" | "bottom" | "left" | "right";
|
||||||
}
|
}
|
||||||
|
|
||||||
let { children, text, position = "top" }: Props = $props();
|
let { children, text, className, position = "top" }: Props = $props();
|
||||||
let showTooltip = $state(false);
|
let showTooltip = $state(false);
|
||||||
let timeout: number = 0;
|
let timeout: number = 0;
|
||||||
|
let triggerElement: HTMLElement;
|
||||||
|
let tooltipPosition = $state({ x: 0, y: 0 });
|
||||||
|
|
||||||
function show() {
|
function show() {
|
||||||
timeout = setTimeout(() => {
|
timeout = setTimeout(() => {
|
||||||
|
if (!triggerElement) return;
|
||||||
|
const rect = triggerElement.getBoundingClientRect();
|
||||||
|
|
||||||
|
switch (position) {
|
||||||
|
case "top":
|
||||||
|
tooltipPosition = {
|
||||||
|
x: rect.left + rect.width / 2,
|
||||||
|
y: rect.top - 10,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case "bottom":
|
||||||
|
tooltipPosition = {
|
||||||
|
x: rect.left + rect.width / 2,
|
||||||
|
y: rect.bottom + 10,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case "left":
|
||||||
|
tooltipPosition = {
|
||||||
|
x: rect.left - 10,
|
||||||
|
y: rect.top + rect.height / 2,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case "right":
|
||||||
|
tooltipPosition = {
|
||||||
|
x: rect.right + 10,
|
||||||
|
y: rect.top + rect.height / 2,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
showTooltip = true;
|
showTooltip = true;
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
@ -24,7 +56,8 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="relative inline-block"
|
bind:this={triggerElement}
|
||||||
|
class="relative inline-block {className}"
|
||||||
onmouseenter={show}
|
onmouseenter={show}
|
||||||
onmouseleave={hide}
|
onmouseleave={hide}
|
||||||
onfocusin={show}
|
onfocusin={show}
|
||||||
|
@ -34,26 +67,28 @@
|
||||||
role="tooltip"
|
role="tooltip"
|
||||||
>
|
>
|
||||||
{@render children()}
|
{@render children()}
|
||||||
{#if showTooltip}
|
|
||||||
<div
|
|
||||||
class="tooltip tooltip-{position}"
|
|
||||||
transition:fade={{
|
|
||||||
duration: 100,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{text}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{#if showTooltip}
|
||||||
|
<div
|
||||||
|
class="tooltip tooltip-{position}"
|
||||||
|
style="left: {tooltipPosition.x}px; top: {tooltipPosition.y}px;"
|
||||||
|
transition:fade={{
|
||||||
|
duration: 100,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.tooltip {
|
.tooltip {
|
||||||
--border-size: 1px;
|
--border-size: 1px;
|
||||||
@apply absolute z-10 bg-panel-alt text-foreground border border-stone-400 dynadark:border-white drop-shadow-lg text-xs px-4 py-2 rounded-full whitespace-nowrap pointer-events-none;
|
@apply fixed bg-panel-alt text-foreground border border-stone-400 dynadark:border-white drop-shadow-lg text-xs px-4 py-2 rounded-full whitespace-nowrap pointer-events-none z-[999];
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip-top {
|
.tooltip-top {
|
||||||
@apply bottom-full left-1/2 -translate-x-1/2 mb-3;
|
transform: translate(-50%, -100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip-top::after {
|
.tooltip-top::after {
|
||||||
|
@ -67,7 +102,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip-bottom {
|
.tooltip-bottom {
|
||||||
@apply top-full left-1/2 -translate-x-1/2 mt-3;
|
transform: translate(-50%, 20%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip-bottom::after {
|
.tooltip-bottom::after {
|
||||||
|
@ -81,7 +116,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip-left {
|
.tooltip-left {
|
||||||
@apply right-full top-1/2 -translate-y-1/2 mr-3;
|
transform: translate(-100%, -50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip-left::after {
|
.tooltip-left::after {
|
||||||
|
@ -89,7 +124,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip-right {
|
.tooltip-right {
|
||||||
@apply left-full top-1/2 -translate-y-1/2 ml-3;
|
transform: translate(0%, -50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip-right::after {
|
.tooltip-right::after {
|
||||||
|
|
|
@ -277,8 +277,6 @@ const toArgs = (ext: string): string[] => {
|
||||||
"18",
|
"18",
|
||||||
"-tune",
|
"-tune",
|
||||||
"stillimage",
|
"stillimage",
|
||||||
"-c:a",
|
|
||||||
"aac",
|
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -335,6 +335,44 @@ body {
|
||||||
@apply bg-accent-purple !text-black;
|
@apply bg-accent-purple !text-black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// firefox
|
||||||
|
* {
|
||||||
|
scrollbar-width: thin;
|
||||||
|
scrollbar-color: var(--bg-separator) transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// other browsers
|
||||||
|
*::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
*::-webkit-scrollbar-track {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
*::-webkit-scrollbar-thumb {
|
||||||
|
background-color: var(--bg-separator);
|
||||||
|
border-radius: 3px;
|
||||||
|
border: none;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
*::-webkit-scrollbar-thumb:hover {
|
||||||
|
background-color: var(--bg-separator);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*::-webkit-scrollbar-corner {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
*::-webkit-scrollbar-button {
|
||||||
|
display: none;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
@layer components {
|
@layer components {
|
||||||
select {
|
select {
|
||||||
@apply appearance-none;
|
@apply appearance-none;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
import { AudioLines, BookText, Check, Film, Image } from "lucide-svelte";
|
import { AudioLines, BookText, Check, Film, Image } from "lucide-svelte";
|
||||||
import { m } from "$lib/paraglide/messages";
|
import { m } from "$lib/paraglide/messages";
|
||||||
import { link } from "$lib/store/index.svelte";
|
import { link } from "$lib/store/index.svelte";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
|
||||||
const getSupportedFormats = (name: string) =>
|
const getSupportedFormats = (name: string) =>
|
||||||
converters
|
converters
|
||||||
|
@ -72,6 +73,30 @@
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let scrollContainers: HTMLElement[] = [];
|
||||||
|
// svelte-ignore state_referenced_locally
|
||||||
|
let showBlur = $state(Array(Object.keys(status).length).fill(false));
|
||||||
|
|
||||||
|
const checkScrollable = (index: number) => {
|
||||||
|
const container = scrollContainers[index];
|
||||||
|
if (!container) return;
|
||||||
|
showBlur[index] = container.scrollHeight > container.clientHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
const handleResize = () => {
|
||||||
|
for (let i = 0; i < scrollContainers.length; i++)
|
||||||
|
checkScrollable(i);
|
||||||
|
};
|
||||||
|
|
||||||
|
handleResize();
|
||||||
|
window.addEventListener("resize", handleResize);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("resize", handleResize);
|
||||||
|
};
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="max-w-6xl w-full mx-auto px-6 md:px-8">
|
<div class="max-w-6xl w-full mx-auto px-6 md:px-8">
|
||||||
|
@ -103,7 +128,7 @@
|
||||||
<h2 class="text-center text-4xl">{m["upload.cards.title"]()}</h2>
|
<h2 class="text-center text-4xl">{m["upload.cards.title"]()}</h2>
|
||||||
|
|
||||||
<div class="flex gap-4 mt-8 md:flex-row flex-col">
|
<div class="flex gap-4 mt-8 md:flex-row flex-col">
|
||||||
{#each Object.entries(status) as [key, s]}
|
{#each Object.entries(status) as [key, s], i}
|
||||||
{@const Icon = s.icon}
|
{@const Icon = s.icon}
|
||||||
<div class="file-category-card w-full flex flex-col gap-4">
|
<div class="file-category-card w-full flex flex-col gap-4">
|
||||||
<div class="file-category-card-inner">
|
<div class="file-category-card-inner">
|
||||||
|
@ -120,61 +145,89 @@
|
||||||
<span>{s.title}</span>
|
<span>{s.title}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="file-category-card-content flex-grow gap-4">
|
<div class="file-category-card-content flex-grow relative">
|
||||||
{#if key === "Video"}
|
<div
|
||||||
<p>
|
class="h-[12.25rem] overflow-y-auto overflow-x-hidden"
|
||||||
{@html link(
|
bind:this={scrollContainers[i]}
|
||||||
"wiki_link",
|
>
|
||||||
m["upload.cards.video_server_processing"](),
|
<div class="flex flex-col gap-4">
|
||||||
"https://github.com/VERT-sh/VERT/wiki/How-to-convert-video-with-VERT",
|
{#if key === "Video"}
|
||||||
)}
|
<p>
|
||||||
</p>
|
{@html link(
|
||||||
{:else}
|
"wiki_link",
|
||||||
<p class="flex tems-center justify-center gap-2">
|
m[
|
||||||
<Check size="20" />
|
"upload.cards.video_server_processing"
|
||||||
{m["upload.cards.local_supported"]()}
|
](),
|
||||||
</p>
|
"https://github.com/VERT-sh/VERT/wiki/How-to-convert-video-with-VERT",
|
||||||
{/if}
|
)}
|
||||||
<p>
|
</p>
|
||||||
{@html m["upload.cards.status.text"]({
|
{:else}
|
||||||
status: s.ready
|
<p
|
||||||
? m["upload.cards.status.ready"]()
|
class="flex tems-center justify-center gap-2"
|
||||||
: m["upload.cards.status.not_ready"](),
|
|
||||||
})}
|
|
||||||
</p>
|
|
||||||
<div>
|
|
||||||
<span class="flex flex-wrap justify-center">
|
|
||||||
<b
|
|
||||||
>{m[
|
|
||||||
"upload.cards.supported_formats"
|
|
||||||
]()} </b
|
|
||||||
>
|
|
||||||
{#each s.formats.split(", ") as format, index}
|
|
||||||
{@const isPartial = format.endsWith("*")}
|
|
||||||
{@const formatName = isPartial
|
|
||||||
? format.slice(0, -1)
|
|
||||||
: format}
|
|
||||||
<span
|
|
||||||
class="text-sm font-normal flex items-center"
|
|
||||||
>
|
>
|
||||||
{#if isPartial}
|
<Check size="20" />
|
||||||
<Tooltip
|
{m["upload.cards.local_supported"]()}
|
||||||
text={getTooltip(formatName)}
|
</p>
|
||||||
|
{/if}
|
||||||
|
<p>
|
||||||
|
{@html m["upload.cards.status.text"]({
|
||||||
|
status: s.ready
|
||||||
|
? m["upload.cards.status.ready"]()
|
||||||
|
: m[
|
||||||
|
"upload.cards.status.not_ready"
|
||||||
|
](),
|
||||||
|
})}
|
||||||
|
</p>
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<b
|
||||||
|
>{m[
|
||||||
|
"upload.cards.supported_formats"
|
||||||
|
]()} </b
|
||||||
|
>
|
||||||
|
<p
|
||||||
|
class="flex flex-wrap justify-center leading-tight px-2"
|
||||||
|
>
|
||||||
|
{#each s.formats.split(", ") as format, index}
|
||||||
|
{@const isPartial =
|
||||||
|
format.endsWith("*")}
|
||||||
|
{@const formatName = isPartial
|
||||||
|
? format.slice(0, -1)
|
||||||
|
: format}
|
||||||
|
<span
|
||||||
|
class="text-sm font-normal flex items-center"
|
||||||
>
|
>
|
||||||
{formatName}<span
|
{#if isPartial}
|
||||||
class="text-red-500">*</span
|
<Tooltip
|
||||||
>
|
text={getTooltip(
|
||||||
</Tooltip>
|
formatName,
|
||||||
{:else}
|
)}
|
||||||
{formatName}
|
>
|
||||||
{/if}
|
{formatName}<span
|
||||||
{#if index < s.formats.split(", ").length - 1}
|
class="text-red-500"
|
||||||
<span>, </span>
|
>*</span
|
||||||
{/if}
|
>
|
||||||
</span>
|
</Tooltip>
|
||||||
{/each}
|
{:else}
|
||||||
</span>
|
{formatName}
|
||||||
|
{/if}
|
||||||
|
{#if index < s.formats.split(", ").length - 1}
|
||||||
|
<span>, </span>
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
{/each}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- blur at bottom if scrollable -->
|
||||||
|
{#if showBlur[i]}
|
||||||
|
<div
|
||||||
|
class="absolute left-0 bottom-0 w-full h-10 pointer-events-none"
|
||||||
|
style="
|
||||||
|
background: linear-gradient(to top, rgba(255,255,255,0.8), transparent 100%);
|
||||||
|
"
|
||||||
|
></div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
|
@ -184,7 +237,7 @@
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.file-category-card {
|
.file-category-card {
|
||||||
@apply bg-panel rounded-2xl p-5 shadow-panel;
|
@apply bg-panel rounded-2xl p-5 shadow-panel relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-category-card p {
|
.file-category-card p {
|
||||||
|
|
Loading…
Reference in New Issue