feat: Banner background inherits cluster icon

This commit is contained in:
LynithDev 2024-08-02 13:04:59 +02:00
parent 32d27bc9fb
commit a0d64eaffa
3 changed files with 65 additions and 17 deletions

View file

@ -0,0 +1,15 @@
.linearBlur::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
-webkit-backdrop-filter: blur(var(--blur));
backdrop-filter: blur(var(--blur));
-webkit-mask: linear-gradient(var(--degrees), transparent, black 50%);
mask: linear-gradient(var(--degrees), transparent, black 50%);
background: linear-gradient(var(--degrees), transparent, rgba(0, 0, 0, 0.4) 50%);
}

View file

@ -1,21 +1,28 @@
import { convertFileSrc } from '@tauri-apps/api/core';
import { type JSX, splitProps } from 'solid-js';
import { type JSX, type ParentProps, Show, splitProps } from 'solid-js';
import styles from './ClusterCover.module.scss';
import defaultCover from '~assets/images/default_instance_cover.jpg';
import type { Cluster } from '~bindings';
type ClusterCoverProps = JSX.HTMLAttributes<HTMLImageElement> & {
cluster: Cluster | undefined;
override?: string;
fallback?: string;
linearBlur?: {
degrees?: number;
blur?: number;
class?: string;
};
};
function ClusterCover(props: ClusterCoverProps) {
const [split, rest] = splitProps(props, ['cluster', 'override', 'onError']);
const [split, rest] = splitProps(props, ['cluster', 'override', 'onError', 'fallback', 'linearBlur', 'class']);
const image = () => {
const url = split.override || split.cluster?.meta.icon_url || split.cluster?.meta.icon;
if (url === undefined || url === null)
return defaultCover;
return split.fallback || defaultCover;
if (url.startsWith('/'))
return convertFileSrc(url);
@ -23,17 +30,33 @@ function ClusterCover(props: ClusterCoverProps) {
return url;
};
const Wrapper = (props: ParentProps) => (
<Show when={split.linearBlur !== undefined} fallback={<>{props.children}</>}>
<div
class={`${styles.linearBlur} ${split.linearBlur?.class || ''}`}
style={{
'--degrees': `${split.linearBlur?.degrees ?? 0}deg`,
'--blur': `${split.linearBlur?.blur ?? 0}px`,
}}
children={props.children}
/>
</Show>
);
return (
<img
{...rest}
src={image()}
onError={(e) => {
e.currentTarget.src = split.override ? convertFileSrc(split.override) : defaultCover;
if (split.onError)
<Wrapper>
<img
{...rest}
class={`${styles.cover} ${split.class || ''}`}
src={image()}
onError={(e) => {
e.currentTarget.src = split.override ? convertFileSrc(split.override) : defaultCover;
if (split.onError)
// @ts-expect-error -- jsx stuff
split.onError!(e);
}}
/>
split.onError!(e);
}}
/>
</Wrapper>
);
}

View file

@ -1,5 +1,5 @@
import {
ChevronRightIcon,
DotsVerticalIcon,
PlayIcon,
PlusIcon,
SearchMdIcon,
@ -8,7 +8,7 @@ import { For, Show, createEffect, createSignal } from 'solid-js';
import { useNavigate } from '@solidjs/router';
import { mergeRefs } from '@solid-primitives/refs';
import image from '../../assets/images/header.png';
import BannerBackground from '../../assets/images/header.png';
import Button from '../components/base/Button';
import TextField from '../components/base/TextField';
import ClusterRoot from './cluster/ClusterRoot';
@ -217,8 +217,18 @@ function Banner(props: BannerProps) {
});
return (
<div class="relative w-full h-52">
<img src={image} class="absolute rounded-xl w-full h-52 object-cover" />
<div class="relative w-full h-52 min-h-52 overflow-hidden rounded-xl">
<ClusterCover
class="absolute rounded-xl w-full h-52 object-cover"
linearBlur={{
degrees: 270,
blur: 30,
class: 'after:right-1/3!',
}}
cluster={cluster()}
fallback={BannerBackground}
/>
<div class="relative z-10 h-full px-8 py-6 text-fg-primary flex flex-col justify-between items-start">
<div class="flex flex-col gap-y-2">
<h1>{cluster()?.meta.name || 'Create a cluster'}</h1>
@ -254,7 +264,7 @@ function Banner(props: BannerProps) {
<Button
buttonStyle="iconSecondary"
class="bg-op-10!"
children={<ChevronRightIcon />}
children={<DotsVerticalIcon />}
onClick={() => ClusterRoot.open(navigate, cluster()!.uuid)}
/>
</>