mirror of
https://github.com/ivabus/gui
synced 2025-04-23 14:07:14 +03:00
new package card style (#436)
* new package card style * fix button padding
This commit is contained in:
parent
653928d504
commit
7f7efdb79d
10 changed files with 106 additions and 52 deletions
|
@ -13,7 +13,9 @@
|
|||
|
||||
$: isOpened = false;
|
||||
|
||||
const toggleOpen = () => {
|
||||
const toggleOpen = (evt?: MouseEvent) => {
|
||||
evt?.preventDefault();
|
||||
|
||||
if ([PackageStates.INSTALLING, PackageStates.UPDATING].includes(pkg.state)) {
|
||||
return;
|
||||
}
|
||||
|
@ -22,7 +24,7 @@
|
|||
|
||||
const isInstalled = (version: string) => pkg.installed_versions?.includes(version);
|
||||
|
||||
const handleClick = (version: string) => {
|
||||
const handleClick = (evt: MouseEvent, version: string) => {
|
||||
if (isInstalled(version)) {
|
||||
return;
|
||||
}
|
||||
|
@ -36,7 +38,7 @@
|
|||
|
||||
<div class="dropdown z-10" use:clickOutside on:click_outside={handleClickOutside}>
|
||||
<PackageStateButton {buttonSize} {pkg} onClick={toggleOpen}>
|
||||
<div class="pt-1">
|
||||
<div class="pt-2">
|
||||
<div class="version-list" class:visible={isOpened}>
|
||||
{#each availableVersions as version, idx}
|
||||
{#if idx !== 0}<hr class="divider" />{/if}
|
||||
|
@ -44,7 +46,7 @@
|
|||
<div
|
||||
class="version-item flex items-center justify-start gap-x-1 text-xs"
|
||||
class:installable-version={!isInstalled(version)}
|
||||
on:click={() => handleClick(version)}
|
||||
on:click={(evt) => handleClick(evt, version)}
|
||||
>
|
||||
<div class:installed-text={isInstalled(version)}>v{version}</div>
|
||||
{#if idx === 0}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
export let buttonSize: "small" | "large" = "small";
|
||||
|
||||
export let pkg: GUIPackage;
|
||||
export let onClick = () => {
|
||||
export let onClick = (evt?: MouseEvent) => {
|
||||
console.log("do nothing");
|
||||
};
|
||||
|
||||
|
@ -38,7 +38,7 @@
|
|||
color={getColor(pkg.state)}
|
||||
{onClick}
|
||||
>
|
||||
<div class="version-button">
|
||||
<div class="version-button h-full">
|
||||
<div class="flex h-full flex-col justify-center p-2">
|
||||
{#if pkg.state === PackageStates.AVAILABLE}
|
||||
<div class="flex items-center justify-between gap-x-2">
|
||||
|
|
|
@ -1,81 +1,123 @@
|
|||
<script lang="ts">
|
||||
import "../../app.css";
|
||||
import ImgLoader from "@tea/ui/img-loader/img-loader.svelte";
|
||||
import ProgressCircle from "@tea/ui/progress-circle/progress-circle.svelte";
|
||||
import InstallButton from "../install-button/install-button.svelte";
|
||||
import type { GUIPackage } from "$libs/types";
|
||||
import { findRecentInstalledVersion } from "$libs/packages/pkg-utils";
|
||||
|
||||
export let pkg: GUIPackage;
|
||||
export let availableVersions: string[];
|
||||
export let link: string;
|
||||
export let progessLoading = 0;
|
||||
|
||||
const imgUrl = !pkg.thumb_image_url.includes("https://tea.xyz")
|
||||
? "https://tea.xyz/Images/package-thumb-nolabel4.jpg"
|
||||
: pkg.thumb_image_url;
|
||||
|
||||
export let onClickCTA = async (_version: string) => {
|
||||
console.log("do nothing");
|
||||
};
|
||||
</script>
|
||||
|
||||
<section class="package-card border-gray relative h-auto border">
|
||||
<section
|
||||
class="package-card border-gray relative h-auto border"
|
||||
style="background-image: url({imgUrl})"
|
||||
>
|
||||
<a href={link}>
|
||||
<figure class="relative">
|
||||
<ImgLoader
|
||||
class="pkg-image object-cover"
|
||||
src={!pkg.thumb_image_url.includes("https://tea.xyz")
|
||||
? "https://tea.xyz/Images/package-thumb-nolabel4.jpg"
|
||||
: pkg.thumb_image_url}
|
||||
alt={pkg.name}
|
||||
/>
|
||||
</figure>
|
||||
<article class="card-thumb-label">
|
||||
<h3 class="text-bold font-mona text-xl font-bold text-white">{pkg.name}</h3>
|
||||
{#if pkg.maintainer}
|
||||
<h4 class="text-sm font-light">• {pkg.maintainer}</h4>
|
||||
{/if}
|
||||
{#if pkg.desc}
|
||||
<p class="line-clamp-2 text-xs font-thin">{pkg.desc}</p>
|
||||
{/if}
|
||||
</article>
|
||||
</a>
|
||||
<footer class="absolute bottom-0 left-0 flex w-full p-3">
|
||||
<div class="install-button">
|
||||
<InstallButton {pkg} {availableVersions} onClick={onClickCTA} />
|
||||
</div>
|
||||
</footer>
|
||||
{#if progessLoading > 0 && progessLoading < 100}
|
||||
<div class="absolute left-0 top-0 h-full w-full bg-black bg-opacity-50">
|
||||
<div class="absolute left-0 right-0 top-1/2 m-auto -mt-12 h-24 w-24">
|
||||
<ProgressCircle value={progessLoading} />
|
||||
<div class="package-card-content flex h-full w-full flex-col justify-between">
|
||||
<div class="hint-container">
|
||||
<div class="hint">
|
||||
<div class="text-xs">view more details</div>
|
||||
<div class="hint-icon"><i class="icon-upward-arrow" /></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-container">
|
||||
<article class="card-thumb-label">
|
||||
<h3 class="text-bold font-mona line-clamp-1 text-2xl font-bold text-white">{pkg.name}</h3>
|
||||
<p class="line-clamp-2 h-[32px] text-xs font-thin">{pkg.desc ?? ""}</p>
|
||||
</article>
|
||||
<div class="mt-3.5 flex w-full">
|
||||
<div class="install-button">
|
||||
<InstallButton {pkg} {availableVersions} onClick={onClickCTA} />
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-1 h-[10px] leading-[10px]">
|
||||
{#if pkg.state === "NEEDS_UPDATE"}
|
||||
<span class="text-[0.5rem]">Updating from v{findRecentInstalledVersion(pkg)}</span>
|
||||
{/if}
|
||||
</div>
|
||||
{#if progessLoading > 0 && progessLoading < 100}
|
||||
<div class="absolute left-0 top-0 h-full w-full bg-black bg-opacity-50">
|
||||
<div class="absolute left-0 right-0 top-1/2 m-auto -mt-12 h-24 w-24">
|
||||
<ProgressCircle value={progessLoading} />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</a>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
section {
|
||||
background-color: #1a1a1a;
|
||||
transition: all 0.3s;
|
||||
width: 100%;
|
||||
height: 230px;
|
||||
}
|
||||
section:hover {
|
||||
background-color: #252525;
|
||||
height: 340px;
|
||||
}
|
||||
|
||||
figure {
|
||||
position: relative;
|
||||
height: 70px;
|
||||
.content-container {
|
||||
height: 50%;
|
||||
background: linear-gradient(180deg, rgba(26, 26, 26, 0.3) 0%, rgba(26, 26, 26, 0.75) 72.92%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 28px 14px;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.package-card :global(.pkg-image) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.hint-container {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.hint {
|
||||
width: 60%;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
column-gap: 0.5rem;
|
||||
background: linear-gradient(270deg, #e1e1e1 66.29%, rgba(225, 225, 225, 0) 100%);
|
||||
color: #1a1a1a;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.hint-icon {
|
||||
background: #8000ff;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #e1e1e1;
|
||||
}
|
||||
|
||||
.package-card {
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.package-card:active {
|
||||
border-color: #8000ff;
|
||||
box-shadow: 0px 0px 0px 2px rgba(128, 0, 255, 0.5);
|
||||
mix-blend-mode: overlay;
|
||||
}
|
||||
|
||||
.package-card:hover .hint {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.card-thumb-label {
|
||||
padding: 1.116vw;
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
height: 110px;
|
||||
}
|
||||
|
||||
.card-thumb-label p {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import type { GUIPackage } from "$libs/types";
|
||||
import type { Package } from "@tea/ui/types";
|
||||
import { clean } from "semver";
|
||||
import semverCompare from "semver/functions/compare";
|
||||
|
||||
|
@ -32,3 +33,8 @@ export const addInstalledVersion = (
|
|||
semverCompare(cleanVersion(b), cleanVersion(a))
|
||||
);
|
||||
};
|
||||
|
||||
export const findRecentInstalledVersion = (pkg: GUIPackage) => {
|
||||
// this assumes that the versions are already sorted
|
||||
return pkg.installed_versions?.[0];
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
// export let size: 'large' | 'medium' | 'small' = 'medium';
|
||||
|
||||
export let onClick: undefined | (() => void) = undefined;
|
||||
export let onClick: undefined | ((evt?: MouseEvent) => void) = undefined;
|
||||
export let active = false;
|
||||
|
||||
export let type: "outline" | "ghost" | "plain" = "ghost";
|
||||
|
@ -19,7 +19,7 @@
|
|||
class="w-full p-2 text-gray {clazz} {type} {color}"
|
||||
class:active
|
||||
class:animate-pulse={loading}
|
||||
on:click={() => onClick && onClick()}
|
||||
on:click={(evt) => onClick && onClick(evt)}
|
||||
>
|
||||
<slot />
|
||||
</button>
|
||||
|
|
Binary file not shown.
|
@ -56,4 +56,5 @@
|
|||
<glyph glyph-name="arrow-left" unicode="U" d="M512 288l-389 0 178 179-45 45-256-256 256-256 45 45-178 179 389 0z"/>
|
||||
<glyph glyph-name="arrow-right" unicode="V" d="M0 224l389 0-178-179 45-45 256 256-256 256-45-45 178-179-389 0z"/>
|
||||
<glyph glyph-name="scissors" unicode="X" d="M274 256c5 0 10-2 13-5 4-4 6-8 6-13 0-5-2-10-6-13-3-4-8-6-13-6-5 0-9 2-13 6-3 3-5 8-5 13 0 5 2 9 5 13 4 3 8 5 13 5z m86-18l145-114c5-4 8-9 7-16-1-7-4-12-10-15l-37-18c-2-1-5-2-8-2-3 0-6 1-9 2l-197 111-31-19c-2-1-3-1-4-1 3-10 4-19 3-28-1-15-7-29-16-42-9-14-22-25-38-35-25-16-51-24-79-24-26 0-47 7-63 22-17 16-25 36-23 59 2 14 7 28 16 42 10 14 22 25 38 35 25 16 51 24 79 24 16 0 30-3 43-8 2 2 4 4 7 6l34 21-34 21c-3 1-5 3-7 6-13-6-27-9-43-9-28 0-54 8-79 24-16 10-28 22-38 35-9 14-14 28-16 42-1 12 1 22 5 33 4 10 10 19 18 26 16 15 37 23 63 23 28 0 54-8 79-24 16-10 29-22 38-35 9-14 15-28 16-43 1-9 0-18-3-27 1 0 2-1 4-2l31-19 197 111c3 2 6 2 9 2 3 0 6 0 8-2l37-18c6-3 9-8 10-15 1-6-2-12-7-16z m-195 74c9 8 11 18 6 31-4 12-14 24-30 33-17 12-36 17-55 17-14 0-25-3-32-10-9-8-11-18-6-31 5-13 15-24 30-33 18-12 36-17 55-17 14 0 25 3 32 10z m-24-213c16 10 26 21 30 34 5 12 3 22-6 30-7 7-18 11-32 11-19 0-37-6-55-17-15-10-25-21-30-34-5-12-3-22 6-30 7-7 18-11 32-11 19 0 38 6 55 17z m51 175l27-16 0 3c0 7 4 12 10 16l4 2-23 14-7-8c-1 0-2-1-3-3-1-2-2-3-3-3-1-1-1-1-2-1 0-1 0-1 0-1z m64-64l27-9 211 165-37 18-219-123 0-32-46-28 3-2c0-1 1-1 2-2 0-1 1-2 3-3 1-2 2-3 3-4l7-7z m201-119l37 19-149 116-50-39c-1-1-2-1-4-2z"/>
|
||||
<glyph glyph-name="upward-arrow" unicode="W" d="M331 469l181-170-43-41-108 102 0-317-361 0 0 57 301 0 0 260-108-102-42 41z"/>
|
||||
</font></defs></svg>
|
||||
|
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Binary file not shown.
Binary file not shown.
|
@ -184,3 +184,6 @@
|
|||
.icon-scissors:before {
|
||||
content: "\58";
|
||||
}
|
||||
.icon-upward-arrow:before {
|
||||
content: "\57";
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue