hyprland-website/src/routes/home-slices/PluginsSlice.svelte
Visual-Dawg d982e5761d
Add Plugins page and more (#48)
* some progress, updating packages

* migrate to SvelteKit 2

* progress

* more stuff

* hy3 banner

* add links to features

* fix distro option extra image

* update community section

* add plugins page link  to plugins slice

* community more profiles

* add more community profiles

* fix RSS not showing in prod (#45)

* plugin page: better banner hover playback

* improve community slice intro timing

* remove fillter texts

* improve command button

* plugin install command wording improvment

* footer adjustments

* add dwindle-autogroup

* stuff

* community profile pictures hosted by Discord :P

* fix autoplay previewRice Chrome

* navbar: no entry delay

* small community profile changes

* optimize plugins layout

* fix sorting

* improve card performance

* clean up test content from .md files

* did more stuff

* change desc of some plugins

* work on design and layout

* make main bg darker
Creates less banding and looks a bit better, while also providing better contrast

* nicer trim text

* more stuff

* fix messup

* update plugins readme

* add a profile picture

* plugins: add gradient bg

* remove placeholder plugins

* plugins: improve mobile layout

* community: small stuff

* remove csgo vulkan fix logo

* plugins: fix bg jumping on Firefox

* plugin slug: improve animation staggering

* small css fixes

* pluginsSlice: animate only with slide
Opacity change looks a bit off here

* community: hide errored images

---------

Co-authored-by: Vaxry <vaxry@vaxry.net>
2024-03-06 21:04:26 +00:00

205 lines
6.7 KiB
Svelte

<script>
import PatternBackground from '$lib/PatternBackground.svelte'
import IconPlugin from '~icons/mingcute/plugin-2-line'
import IconIpc from '~icons/mingcute/hexagon-line'
import IconLinkOut from '~icons/mingcute/external-link-line'
import IconSlideLeft from '~icons/mingcute/align-arrow-left-line'
import clsx from 'clsx'
import Video from '$lib/components/Video.svelte'
import { animateIn } from '$lib/Helper.mjs'
import { Subject, debounceTime, map, tap, throttle, throttleTime } from 'rxjs'
import { onMount } from 'svelte'
import { fade } from 'svelte/transition'
import Button from '$lib/components/Button.svelte'
/** @type {HTMLVideoElement[]}*/
const videos = []
let activeIndex = 0
let isHoveringVideo = false
const isVideoCroppedInput$ = new Subject()
/** @type {import('rxjs').Subject<boolean>}*/
const isVideoCropped$ = isVideoCroppedInput$.pipe(
debounceTime(100),
map(
() =>
window.innerWidth > 1024 && // LG breakpoint
window.innerWidth < 2200 // Video is fully visible
)
)
const items = [
{
icon: IconPlugin,
title: 'Plugins.',
description:
'Customize everything with official and community extensions. Write your own easily with C++',
poster: '/videos/outfoxxed_thumb.webp',
src: '/videos/outfoxxed',
subtext: `
Setup by <a href="https://github.com/outfoxxed/" target="_blank">outfoxxed</a> using <a href="https://github.com/outfoxxed/hy3" target="_blank">hy3</a> and <a href="https://github.com/VortexCoyote/hyprfocus" target="_blank">hyprfocus</a>`
},
{
icon: IconIpc,
title: 'Bindings and IPC.',
description: 'Control your desktop with your favourite languages or simply via IPC.',
poster: '/videos/aylur_thumb.png',
src: '/videos/aylur',
subtext: `Setup by <a href="https://github.com/Aylur/dotfiles" target="_blank">Aylur</a>, creator of
<a href="https://github.com/Aylur/ags" target="_blank">Ags</a> using Ags to control Hyprland
via IPC.`
}
]
function setActiveItem(index) {
activeIndex = index
}
function onPlay(currentIndex) {
videos.filter((_, index) => index !== currentIndex).forEach((video) => video.play())
}
function onPause(activeIndex, currentIndex) {
// Prevent infinite loop when active video gets paused and other videos also get paused as a result
if (currentIndex !== activeIndex) return
videos.filter((_, index) => index !== currentIndex).forEach((video) => video.pause())
}
function toggleVideoSlide() {
isHoveringVideo ? slideVideoOut() : slideVideoIn()
}
function slideVideoIn() {
isHoveringVideo = true
}
function slideVideoOut() {
if (!isHoveringVideo) return
isHoveringVideo = false
}
onMount(() => {
isVideoCroppedInput$.next(0)
})
</script>
<svelte:window on:resize={() => isVideoCroppedInput$.next(0)} />
<section class="relative z-0 flex min-h-max w-full flex-col items-center py-20">
<div
class="mx-auto grid max-w-7xl grid-cols-1 gap-8 transition-all lg:grid-cols-2 lg:gap-12"
use:animateIn={{ slide: 24 }}
>
<div
class={clsx(
'z-10 flex flex-col gap-10 px-5 transition-transform delay-75 duration-300 sm:px-6',
isHoveringVideo && '-translate-x-36'
)}
>
<div class="txt-shadow_ mt-8 flex flex-col gap-6">
<h2 class=" text-6xl font-bold">Unlock full power</h2>
<p class="text-lg font-bold text-slate-300">
Get the latest features Linux offers. Have full control over your workflow by customizing
and extending it how you want.
</p>
</div>
<div class="flex h-full flex-col gap-4">
{#each items as { icon, title, description }, index}
{@const isActive = index === activeIndex}
<button
class={clsx(
'flex gap-3 rounded-xl px-4 py-4 outline-0 outline-cyan-400/50 transition-all sm:-ml-4',
isActive && 'bg-blue-300/5 shadow-md outline outline-1 backdrop-blur-sm '
)}
on:mouseenter={() => setActiveItem(index)}
>
<svelte:component this={icon} class="h-8 w-8 shrink-0 text-primary" />
<p
class={clsx(
'txt-shadow_ text-left text-lg font-medium transition-colors ',
isActive ? 'text-slate-300' : 'text-slate-400'
)}
>
<span class="font-bold text-white">{title}</span>
{description}
</p>
</button>
{/each}
</div>
<Button type="fancyOutline" size="lg" class="max-w-max"
><a href="/plugins/">Checkout more plugins</a></Button
>
<div class="-mt-5 hidden gap-1 lg:mt-12 lg:flex lg:flex-col">
<a
class="txt-shadow_ flex w-max max-w-max shrink-0 items-center gap-3 rounded font-bold text-slate-400 hover:underline"
href="https://github.com/hyprland-community/awesome-hyprland"
target="_blank"
>
<div>
Also see <span class="text-cyan-500">Awesome Hyprland</span>
</div>
<IconLinkOut />
</a>
<p class="font-medium text-slate-400">
A list of plugins, bindings and more by the community
</p>
</div>
</div>
<!-- Prevent the video from making the container big on small phones. 300px seem to work well for the text -->
<div
class={clsx(
'relative z-10 w-full min-w-0 transition-transform sm:h-[25rem] sm:px-4 md:h-[30rem] lg:h-[37rem] lg:px-0',
isHoveringVideo && '-translate-x-56'
)}
>
{#if $isVideoCropped$}
<button
on:click={toggleVideoSlide}
class:rotate-180={isHoveringVideo}
class="group absolute -left-6 top-1/2 z-50 rounded-full bg-blue-400/5 p-2 outline outline-white/10 backdrop-blur-sm transition-transform"
out:fade
>
<IconSlideLeft
class="h-6 w-6 opacity-70 transition-all group-hover:-translate-x-0.5 group-hover:opacity-100"
/>
</button>
{/if}
<div class="h-full w-full" role="complementary">
{#each items as { src, poster }, index}
<Video
sources={[src + '.mp4']}
{poster}
autoplay
muted
bind:videoElement={videos[index]}
class="z-10 aspect-video origin-left object-cover object-left shadow-xl shadow-cyan-700/50 outline-2 outline-cyan-500 duration-500 sm:h-[inherit] sm:rounded-lg sm:outline"
playButtonClass=" lg:left-32 xl:left-1/2"
hidden={index !== activeIndex}
on:pause={() => onPause(activeIndex, index)}
on:play={() => onPlay(index)}
videoClass="h-[inherit] aspect-video"
/>
{/each}
</div>
<div
class="px-2 text-sm font-medium text-slate-300 sm:px-0 sm:pt-5 md:text-base [&>a:hover]:text-cyan-300 [&>a:hover]:underline [&>a]:font-bold"
>
{@html items[activeIndex].subtext}
</div>
</div>
</div>
<PatternBackground class="absolute inset-0 h-[110%] w-full text-slate-800 opacity-40" />
</section>
<style lang="postcss">
.txt-shadow_ {
text-shadow:
0px 0px 12px theme(colors.black / 90%),
0px 0px 24px theme(colors.black / 50%);
}
.slideToLeft {
margin-left: -15rem;
}
</style>