hyprland-website/src/routes/HeroBackground.svelte

211 lines
4.6 KiB
Svelte
Raw Normal View History

2023-09-04 20:54:16 +02:00
<script>
import baseColors from 'tailwindcss/colors'
2023-09-05 21:09:18 +02:00
const workspacesPerRow = 4
const workspaceHeight = 240
const gapLength = 32
2023-09-04 20:54:16 +02:00
const colors = [baseColors.blue[500], baseColors.cyan[400], baseColors.sky[500]]
2023-09-05 21:09:18 +02:00
const leftColumns = Array.from({ length: 3 }, () => generateRow(workspacesPerRow))
const rightColumns = Array.from({ length: 3 }, () => generateRow(workspacesPerRow))
/** Used to transform the rows by their own lenght*/
const height = workspacesPerRow * (workspaceHeight + gapLength)
2023-09-04 20:54:16 +02:00
function generateRow(amount) {
const base = Array.from({ length: amount }).map(generateWorkspace)
// For the effect to work, the items need to be duplicated
return [...base, ...base]
}
function generateWorkspace() {
return [
generateTiles(),
Math.random() > 0.4 ? generateTiles() : false,
Math.random() > 0.7 ? generateTiles() : false
].filter(Boolean)
}
function generateTiles() {
const result = Math.random() > 0.5 ? [getRandomColor()] : [getRandomColor(), getRandomColor()]
return result
}
function getRandomColor() {
return colors.at(Math.floor(Math.random() * colors.length))
}
</script>
2023-09-07 21:03:47 +02:00
<div class="wrapper" aria-hidden="true">
2023-09-04 20:54:16 +02:00
<div
class="inner-wrapper"
2023-09-05 21:09:18 +02:00
style={`--amount: ${workspacesPerRow}; --workspace-gap: ${gapLength}px;--workspace-height: ${workspaceHeight}px; --length: ${height}px;`}
2023-09-04 20:54:16 +02:00
>
2023-09-05 21:09:18 +02:00
<!-- Gradient background -->
<div class="top-light" />
<div class="columns left" aria-hidden="true">
2023-09-04 20:54:16 +02:00
{#each leftColumns as column}
<div class="column">
{#each column as workspace}
<div class="workspace">
{#each workspace as tiles}
<div class="tiles">
{#each tiles as tile}
<div class="tile" style:--color={tile}></div>
{/each}
</div>
{/each}
</div>
{/each}
</div>
{/each}
</div>
2023-09-05 21:09:18 +02:00
<div class="columns right" aria-hidden="true">
2023-09-04 20:54:16 +02:00
{#each rightColumns as column}
<div class="column">
{#each column as workspace}
<div class="workspace">
{#each workspace as tiles}
<div class="tiles">
{#each tiles as tile}
<div class="tile" style:--color={tile}></div>
{/each}
</div>
{/each}
</div>
{/each}
</div>
{/each}
</div>
</div>
</div>
<style lang="postcss">
.left {
2023-09-05 21:09:18 +02:00
transform: rotateY(10deg) rotateZ(90deg);
2023-09-04 20:54:16 +02:00
}
.right {
2023-09-05 21:09:18 +02:00
transform: rotateY(-10deg) rotateZ(-90deg);
2023-09-04 20:54:16 +02:00
}
.wrapper {
width: 100vw;
display: flex;
align-items: center;
justify-content: center;
2023-09-05 21:09:18 +02:00
height: calc(100vh - 48px);
contain: strict;
@apply max-sm:hidden;
2023-09-04 20:54:16 +02:00
}
.inner-wrapper {
position: absolute;
perspective: 100px;
height: 100%;
2023-09-05 21:09:18 +02:00
width: max(100vw, 2200px);
2023-09-04 20:54:16 +02:00
contain: strict;
display: flex;
2023-09-05 21:09:18 +02:00
mask-image: linear-gradient(to top, transparent 0%, black 20%);
2023-09-07 21:03:47 +02:00
contain: layout style content;
2023-09-05 21:09:18 +02:00
&::after {
content: ' ';
background: radial-gradient(80% 250%, theme(colors.black) 10%, transparent 50%);
position: absolute;
top: 50%;
left: 50%;
translate: -50% -50%;
width: 100%;
height: 100%;
z-index: -10;
pointer-events: none;
2023-09-07 21:03:47 +02:00
contain: strict;
2023-09-05 21:09:18 +02:00
}
2023-09-04 20:54:16 +02:00
}
.columns {
display: flex;
gap: 2rem;
flex-grow: 1;
2023-09-05 21:09:18 +02:00
mask-image: linear-gradient(to top, transparent 0%, black 30%);
z-index: -10;
height: var(--length);
min-height: var(--length);
max-height: var(--length);
2023-09-10 08:09:06 +02:00
/* animation: backwards animate-in ease-in 2000ms 300ms; */
2023-09-07 21:03:47 +02:00
contain: layout style content;
2023-09-04 20:54:16 +02:00
}
.column {
display: flex;
flex-direction: column;
2023-09-05 21:09:18 +02:00
height: 200%;
2023-09-04 20:54:16 +02:00
width: 100%;
gap: var(--workspace-gap);
2023-09-05 21:09:18 +02:00
z-index: -50;
2023-09-07 21:03:47 +02:00
/* animation: loop 98s infinite linear; */
contain: layout style content;
2023-09-05 21:09:18 +02:00
@media (prefers-reduced-motion) {
animation: none;
}
2023-09-04 20:54:16 +02:00
}
.workspace {
display: flex;
gap: 8px;
2023-09-05 21:09:18 +02:00
min-height: var(--workspace-height);
max-height: var(--workspace-height);
2023-09-04 20:54:16 +02:00
width: 100%;
2023-09-07 21:03:47 +02:00
contain: layout style content;
2023-09-04 20:54:16 +02:00
}
.tiles {
display: flex;
flex-direction: column;
gap: 8px;
flex-grow: 1;
2023-09-07 21:03:47 +02:00
contain: layout style content;
2023-09-04 20:54:16 +02:00
}
.tile {
2023-09-05 21:09:18 +02:00
border: var(--color) 2px solid;
2023-09-04 20:54:16 +02:00
flex-grow: 1;
height: var(--height);
border-radius: 12px;
pointer-events: auto;
2023-09-07 21:03:47 +02:00
transition: 380ms ease-in-out;
transition-property: background opacity scale box-shadow;
opacity: 0.5;
contain: strict;
2023-09-04 20:54:16 +02:00
&:hover {
2023-09-07 21:03:47 +02:00
opacity: 1;
scale: 1.02;
2023-09-05 21:09:18 +02:00
background: color-mix(in hsl, var(--color), transparent 20%);
box-shadow:
0px 0px 10px var(--color),
0px 0px 40px var(--color);
2023-09-04 20:54:16 +02:00
}
}
2023-09-05 21:09:18 +02:00
.top-light {
background: radial-gradient(
100% 80% at top,
2023-09-07 21:03:47 +02:00
theme(colors.cyan.500 / 50%) 0%,
2023-09-05 21:09:18 +02:00
theme(colors.sky.500 / 20%),
transparent
);
width: 100%;
height: 100%;
position: absolute;
z-index: 10;
top: 0;
left: 0;
pointer-events: none;
2023-09-07 21:03:47 +02:00
contain: strict;
2023-09-04 20:54:16 +02:00
}
</style>