mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
refactor: beta card adjustments & light mode
This commit is contained in:
@@ -1,19 +1,26 @@
|
||||
<script lang="ts">
|
||||
import { Confetti } from 'svelte-confetti';
|
||||
import Card from './Card.svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
let triggerConfettiKey = 1;
|
||||
const confettiColors = [
|
||||
'hsl(var(--color-primary-100))',
|
||||
'hsl(var(--color-primary-200))',
|
||||
'hsl(var(--color-primary-300))'
|
||||
'hsl(var(--color-primary-300))',
|
||||
'#F05088',
|
||||
'#FF86BB',
|
||||
'#FFFFFF80'
|
||||
];
|
||||
|
||||
let cardActive = false;
|
||||
let cardIsFlipped = false;
|
||||
</script>
|
||||
|
||||
<div class="wrapper">
|
||||
<div class="card">
|
||||
<h3 class="heading-level-3">
|
||||
Join the celebration
|
||||
Welcome to the Cloud Club
|
||||
<button class="confetti-btn" on:click={() => triggerConfettiKey++}>
|
||||
🎉
|
||||
{#each Array(triggerConfettiKey) as _, i (i)}
|
||||
@@ -28,7 +35,10 @@
|
||||
</button>
|
||||
</h3>
|
||||
<div class="u-flex u-margin-block-start-40 u-cross-center u-gap-24">
|
||||
<img src="/images/cloud-beta-hoodies.png" alt="Cloud Beta hoodies" />
|
||||
<div class="hoodie-container">
|
||||
<img src="/images/hoodie-1.png" alt="Cloud Beta hoodies" />
|
||||
<img src="/images/hoodie-2.png" alt="Cloud Beta hoodies" />
|
||||
</div>
|
||||
<div>
|
||||
<div class="u-flex u-cross-center u-gap-8">
|
||||
<h4 class="eyebrow-heading-1">Cloud is live in public</h4>
|
||||
@@ -64,17 +74,38 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="cbc-wrapper">
|
||||
<!-- <div class="confetti-wrapper">
|
||||
<Confetti
|
||||
x={[-2, 2]}
|
||||
y={[-2.25, 1.25]}
|
||||
amount={50}
|
||||
size="10"
|
||||
delay={[0, 5000]}
|
||||
colorArray={confettiColors}
|
||||
fallDistance="50px" />
|
||||
</div> -->
|
||||
<Card />
|
||||
{#if !cardActive}
|
||||
<div transition:fade>
|
||||
<Confetti
|
||||
x={[-1.75, 1.85]}
|
||||
y={[-1.875, 1]}
|
||||
amount={100}
|
||||
size="10"
|
||||
infinite
|
||||
delay={[2000, 7000]}
|
||||
colorArray={confettiColors}
|
||||
fallDistance="50px" />
|
||||
</div>
|
||||
{/if}
|
||||
<Card bind:active={cardActive} bind:isFlipped={cardIsFlipped} />
|
||||
</div>
|
||||
{#if cardActive}
|
||||
<div
|
||||
class="overlay"
|
||||
on:click={() => (cardActive = false)}
|
||||
on:keydown={() => {
|
||||
/* no-op */
|
||||
}}
|
||||
transition:fade />
|
||||
{/if}
|
||||
<div class="controls" class:invisible={!cardActive}>
|
||||
<button
|
||||
class="button is-text"
|
||||
on:click={() => (cardIsFlipped = !cardIsFlipped)}
|
||||
aria-label="Rotate card">
|
||||
<span class="icon-refresh" aria-hidden="true" />
|
||||
<span class="text">Spin</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -85,7 +116,19 @@
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
:global(.theme-dark) .wrapper {
|
||||
--glow: hsl(var(--color-primary-100));
|
||||
--beta-bg: hsl(var(--color-neutral-120));
|
||||
--beta-fg: hsl(var(--color-neutral-0));
|
||||
--sep-clr: hsl(var(--color-neutral-150));
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
--glow: transparent;
|
||||
--beta-bg: rgba(240, 46, 101, 0.16);
|
||||
--beta-fg: rgba(240, 46, 101, 0.8);
|
||||
--sep-clr: hsl(var(--color-neutral-10));
|
||||
|
||||
display: grid;
|
||||
place-items: center;
|
||||
justify-content: center;
|
||||
@@ -107,7 +150,8 @@
|
||||
}
|
||||
|
||||
.beta-tag {
|
||||
background-color: hsl(var(--color-neutral-120));
|
||||
background-color: var(--beta-bg);
|
||||
color: var(--beta-fg);
|
||||
padding-inline: 0.75rem; // 12px
|
||||
padding-block: 0.25rem; // 4px
|
||||
border-radius: 0.375rem; // 6px
|
||||
@@ -117,11 +161,59 @@
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.hoodie-container {
|
||||
background-image: url('/images/hoodies-bg.png');
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
position: relative;
|
||||
width: 9.9375rem; // 159px
|
||||
height: 7.375rem; // 118px
|
||||
flex-shrink: 0;
|
||||
|
||||
transition: 300ms ease;
|
||||
|
||||
img {
|
||||
display: block;
|
||||
position: absolute;
|
||||
object-fit: contain;
|
||||
width: 5.8125rem; // 93px
|
||||
height: 5.8125rem; // 93px
|
||||
|
||||
transition: 300ms ease;
|
||||
|
||||
&:first-child {
|
||||
top: 1rem;
|
||||
left: 0.1875rem;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
top: 0.5625rem; // 9px
|
||||
right: 0.1875rem; // 3px
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 0 30px var(--glow);
|
||||
|
||||
img:first-child {
|
||||
scale: 1.5;
|
||||
rotate: -5deg;
|
||||
translate: -1rem 1rem;
|
||||
}
|
||||
|
||||
img:last-child {
|
||||
scale: 1.5;
|
||||
rotate: 5deg;
|
||||
translate: 1rem -1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
border-top: 1px solid hsl(var(--color-neutral-150));
|
||||
border-top: 1px solid var(--sep-clr);
|
||||
|
||||
margin-block-start: 2rem;
|
||||
padding-block-start: 2rem;
|
||||
@@ -136,11 +228,6 @@
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.confetti-wrapper {
|
||||
position: relative;
|
||||
// z-index: 9999;
|
||||
}
|
||||
|
||||
@keyframes shake {
|
||||
0% {
|
||||
translate: 0;
|
||||
@@ -179,4 +266,33 @@
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
|
||||
position: absolute;
|
||||
top: 80%;
|
||||
left: 50%;
|
||||
translate: -50% -50%;
|
||||
|
||||
transition: opacity 250ms ease;
|
||||
|
||||
&.invisible {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
background-color: hsl(var(--p-body-bg-color));
|
||||
backdrop-filter: blur(80px);
|
||||
opacity: 0.5;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -22,12 +22,14 @@
|
||||
import { spring } from 'svelte/motion';
|
||||
|
||||
let cardEl: HTMLDivElement | undefined;
|
||||
let active = false;
|
||||
export let active = false;
|
||||
export let isFlipped = false;
|
||||
|
||||
let interacting = false;
|
||||
|
||||
const springR = { stiffness: 0.066, damping: 0.25 };
|
||||
const springD = { stiffness: 0.033, damping: 0.45 };
|
||||
const THICKNESS = 6;
|
||||
const THICKNESS = 3;
|
||||
|
||||
let springRotate = spring({ x: 0, y: 0 }, springR);
|
||||
let springGlare = spring({ x: 50, y: 50, o: 0.25 }, springR);
|
||||
@@ -39,8 +41,6 @@
|
||||
let centerProximity = spring(0, springR);
|
||||
let springRotateZ = spring(-15, springD);
|
||||
|
||||
let isBackwards = false;
|
||||
|
||||
// Events
|
||||
const interact = (e: MouseEvent | TouchEvent) => {
|
||||
if (!active) return;
|
||||
@@ -61,7 +61,7 @@
|
||||
};
|
||||
const center = {
|
||||
x: percent.x - 50,
|
||||
y: (percent.y - 50) * (isBackwards ? -1 : 1)
|
||||
y: (percent.y - 50) * (isFlipped ? -1 : 1)
|
||||
};
|
||||
|
||||
springBackground.stiffness = springR.stiffness;
|
||||
@@ -153,6 +153,7 @@
|
||||
springTranslate.set({ x: 0, y: 0 });
|
||||
springRotateDelta.set({ x: 0, y: 0 });
|
||||
springRotate.set({ x: 0, y: 0 });
|
||||
springGlare.set({ x: 50, y: 50, o: 0 });
|
||||
$centerProximity = 0;
|
||||
springRotateZ.set(-15);
|
||||
};
|
||||
@@ -161,23 +162,19 @@
|
||||
active = !active;
|
||||
};
|
||||
|
||||
const handleBlur = () => {
|
||||
active = false;
|
||||
};
|
||||
|
||||
const windowKeyDown = (e: KeyboardEvent) => {
|
||||
if (!active) return;
|
||||
// If user presses q, rotate card
|
||||
if (e.key === 'q') {
|
||||
isBackwards = !isBackwards;
|
||||
isFlipped = !isFlipped;
|
||||
}
|
||||
};
|
||||
|
||||
$: if (!active) {
|
||||
isBackwards = false;
|
||||
isFlipped = false;
|
||||
} else {
|
||||
springRotateDelta.update((old) => ({
|
||||
x: isBackwards ? 180 : 360,
|
||||
x: isFlipped ? 180 : 360,
|
||||
y: old.y
|
||||
}));
|
||||
}
|
||||
@@ -273,7 +270,9 @@
|
||||
on:pointermove={interact}
|
||||
on:mouseout={interactEnd}
|
||||
on:click={handleClick}
|
||||
on:blur={handleBlur}>
|
||||
on:blur={() => {
|
||||
/* noop */
|
||||
}}>
|
||||
<div class="card__back">
|
||||
<img
|
||||
src="/images/back.png"
|
||||
@@ -310,20 +309,24 @@
|
||||
--hyp: 0;
|
||||
}
|
||||
|
||||
:global(.theme-dark) .cb-card {
|
||||
--shadow-clr: transparent;
|
||||
}
|
||||
|
||||
.cb-card {
|
||||
--radius: 12px;
|
||||
--back: white;
|
||||
--glow: var(--primary);
|
||||
--radius: 16px;
|
||||
--shadow-clr: hsl(var(--color-neutral-30));
|
||||
|
||||
z-index: calc(var(--s) * 100);
|
||||
transform: translate3d(0, 0, 0.1px);
|
||||
-webkit-transform: translate3d(0, 0, 0.1px);
|
||||
will-change: transform, visibility;
|
||||
transform-style: preserve-3d;
|
||||
-webkit-transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.cb-card.interacting {
|
||||
z-index: calc(var(--s) * 120);
|
||||
&.interacting {
|
||||
z-index: calc(var(--s) * 120);
|
||||
}
|
||||
}
|
||||
|
||||
.cb-card.active .card__translater,
|
||||
@@ -352,17 +355,30 @@
|
||||
transform-style: preserve-3d;
|
||||
-webkit-transform: rotateY(var(--rx)) rotateX(var(--ry)) rotateZ(var(--rz));
|
||||
-webkit-transform-style: preserve-3d;
|
||||
box-shadow: 0px 10px 20px -5px #14141f;
|
||||
box-shadow: 0px 10px 20px -5px var(--shadow-clr);
|
||||
border-radius: var(--radius);
|
||||
outline: none;
|
||||
transition: box-shadow 0.4s ease, outline 0.2s ease;
|
||||
}
|
||||
button.card__rotator {
|
||||
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
border: none;
|
||||
background: top;
|
||||
padding: 0;
|
||||
|
||||
:global(*) {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-area: 1/1;
|
||||
border-radius: var(--radius);
|
||||
image-rendering: optimizeQuality;
|
||||
transform-style: preserve-3d;
|
||||
-webkit-transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
img {
|
||||
outline: 1px solid transparent;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.card__thick {
|
||||
@@ -373,44 +389,14 @@
|
||||
transform: translateZ(calc(var(--i) * 1px));
|
||||
}
|
||||
|
||||
.cb-card.active .card__rotator {
|
||||
box-shadow: 0 0 10px 0px var(--glow), 0 0 10px 0px var(--glow), 0 0 30px 0px var(--glow);
|
||||
}
|
||||
|
||||
.card__rotator:focus {
|
||||
box-shadow: 0 0 10px 0px var(--glow), 0 0 10px 0px var(--glow), 0 0 30px 0px var(--glow);
|
||||
}
|
||||
|
||||
.cb-card.active .card__rotator:focus {
|
||||
box-shadow: 0px 10px 30px 3px #14141f;
|
||||
}
|
||||
|
||||
.card__rotator :global(*) {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-area: 1/1;
|
||||
border-radius: var(--radius);
|
||||
image-rendering: optimizeQuality;
|
||||
transform-style: preserve-3d;
|
||||
-webkit-transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.card__rotator img {
|
||||
outline: 1px solid transparent;
|
||||
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.card__back {
|
||||
background-color: var(--back);
|
||||
transform: rotateY(180deg) translateZ(0px);
|
||||
-webkit-transform: rotateY(180deg) translateZ(0px);
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
|
||||
.card__front,
|
||||
.card__front * {
|
||||
backface-visibility: hidden;
|
||||
&::before {
|
||||
--resolved-angle: calc(calc(var(--angle) * -1) + 60deg);
|
||||
}
|
||||
}
|
||||
|
||||
.card__front {
|
||||
@@ -418,18 +404,20 @@
|
||||
transition: opacity 0.33s ease-out;
|
||||
transform: translateZ(calc(var(--thickness) * 1px));
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.card__front::before {
|
||||
--resolved-angle: calc(var(--angle) + 65deg);
|
||||
}
|
||||
.card__back::before {
|
||||
--resolved-angle: calc(calc(var(--angle) * -1) + 60deg);
|
||||
backface-visibility: hidden;
|
||||
|
||||
* {
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
|
||||
&::before {
|
||||
--resolved-angle: calc(var(--angle) + 65deg);
|
||||
}
|
||||
}
|
||||
|
||||
.card__front::before,
|
||||
.card__back::before {
|
||||
/* Conic gradient */
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@@ -449,6 +437,7 @@
|
||||
}
|
||||
|
||||
.card__glare {
|
||||
border-radius: calc(var(--radius) + 3px);
|
||||
transform: translateZ(1px);
|
||||
z-index: 4;
|
||||
background: radial-gradient(
|
||||
@@ -458,6 +447,6 @@
|
||||
rgba(0, 0, 0, 0.5) 90%
|
||||
);
|
||||
mix-blend-mode: overlay;
|
||||
opacity: calc(var(--o) * 0.25);
|
||||
opacity: calc(var(--o) * 0.5);
|
||||
}
|
||||
</style>
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
Reference in New Issue
Block a user