mirror of
https://github.com/LukeHagar/website.git
synced 2025-12-11 04:22:19 +00:00
prettier updates
This commit is contained in:
@@ -1,34 +1,34 @@
|
||||
<script lang="ts">
|
||||
import { rect } from '$lib/actions';
|
||||
import { writable } from 'svelte/store';
|
||||
import { rect } from '$lib/actions';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
const bodyRect = writable<DOMRect | null>(null);
|
||||
const bodyRect = writable<DOMRect | null>(null);
|
||||
</script>
|
||||
|
||||
<div class="relative">
|
||||
<div
|
||||
class="true-body"
|
||||
style:width={`${$bodyRect?.width ?? 0}px`}
|
||||
style:height={`${$bodyRect?.height ?? 0}px`}
|
||||
/>
|
||||
<div class="body" use:rect={bodyRect}>
|
||||
<slot />
|
||||
</div>
|
||||
<div
|
||||
class="true-body"
|
||||
style:width={`${$bodyRect?.width ?? 0}px`}
|
||||
style:height={`${$bodyRect?.height ?? 0}px`}
|
||||
/>
|
||||
<div class="body" use:rect={bodyRect}>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.relative {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.relative {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.body {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.body {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.true-body {
|
||||
transition: 0.2s ease;
|
||||
}
|
||||
.true-body {
|
||||
transition: 0.2s ease;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<script lang="ts">
|
||||
import '$scss/hljs.css';
|
||||
import '$scss/hljs.css';
|
||||
|
||||
import { getCodeHtml } from '$lib/utils/code';
|
||||
import { getCodeHtml } from '$lib/utils/code';
|
||||
|
||||
export let content: string;
|
||||
$: codeHtml = getCodeHtml({ content, language: 'js' });
|
||||
export let content: string;
|
||||
$: codeHtml = getCodeHtml({ content, language: 'js' });
|
||||
</script>
|
||||
|
||||
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
||||
|
||||
@@ -1,96 +1,96 @@
|
||||
<script>
|
||||
import AutoBox from '../AutoBox.svelte';
|
||||
import Code from './Code.svelte';
|
||||
import AutoBox from '../AutoBox.svelte';
|
||||
import Code from './Code.svelte';
|
||||
</script>
|
||||
|
||||
<div class="code-console">
|
||||
<div class="header">
|
||||
<div class="ellipse" />
|
||||
<div class="ellipse-2" />
|
||||
<div class="ellipse-3" />
|
||||
</div>
|
||||
<div class="block">
|
||||
<AutoBox>
|
||||
<slot {Code} />
|
||||
</AutoBox>
|
||||
</div>
|
||||
<div id="code-bottom" />
|
||||
<div class="header">
|
||||
<div class="ellipse" />
|
||||
<div class="ellipse-2" />
|
||||
<div class="ellipse-3" />
|
||||
</div>
|
||||
<div class="block">
|
||||
<AutoBox>
|
||||
<slot {Code} />
|
||||
</AutoBox>
|
||||
</div>
|
||||
<div id="code-bottom" />
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
@use '$scss/abstract/mixins/border-gradient' as gradients;
|
||||
|
||||
.code-console {
|
||||
@include gradients.border-gradient;
|
||||
--p-radius: 16px;
|
||||
.code-console {
|
||||
@include gradients.border-gradient;
|
||||
--p-radius: 16px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
background-color: hsl(var(--web-color-card));
|
||||
border-radius: var(--p-radius);
|
||||
--m-border-radius: var(--p-radius);
|
||||
--m-border-gradient-before: linear-gradient(
|
||||
180deg,
|
||||
rgba(255, 255, 255, 0.12) 0%,
|
||||
rgba(255, 255, 255, 0) 125.11%
|
||||
);
|
||||
backdrop-filter: blur(8px);
|
||||
background-color: hsl(var(--web-color-card));
|
||||
border-radius: var(--p-radius);
|
||||
--m-border-radius: var(--p-radius);
|
||||
--m-border-gradient-before: linear-gradient(
|
||||
180deg,
|
||||
rgba(255, 255, 255, 0.12) 0%,
|
||||
rgba(255, 255, 255, 0) 125.11%
|
||||
);
|
||||
backdrop-filter: blur(8px);
|
||||
|
||||
min-width: 330px;
|
||||
width: fit-content;
|
||||
padding: 0 0.25rem 0.25rem;
|
||||
}
|
||||
min-width: 330px;
|
||||
width: fit-content;
|
||||
padding: 0 0.25rem 0.25rem;
|
||||
}
|
||||
|
||||
.block {
|
||||
width: 100%;
|
||||
flex-grow: 1;
|
||||
text-align: left;
|
||||
.block {
|
||||
width: 100%;
|
||||
flex-grow: 1;
|
||||
text-align: left;
|
||||
|
||||
border-radius: 12px;
|
||||
background: linear-gradient(129deg, rgba(0, 0, 0, 0.48) 22.38%, rgba(0, 0, 0, 0) 136.5%);
|
||||
padding: 20px;
|
||||
border-radius: 12px;
|
||||
background: linear-gradient(129deg, rgba(0, 0, 0, 0.48) 22.38%, rgba(0, 0, 0, 0) 136.5%);
|
||||
padding: 20px;
|
||||
|
||||
position: relative;
|
||||
}
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.header {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.375rem;
|
||||
padding: 0.75rem;
|
||||
.header {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.375rem;
|
||||
padding: 0.75rem;
|
||||
|
||||
.ellipse {
|
||||
background-color: #ec6a5e;
|
||||
.ellipse {
|
||||
background-color: #ec6a5e;
|
||||
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
top: 12px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
top: 12px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.ellipse-2 {
|
||||
background-color: #f5bf4f;
|
||||
.ellipse-2 {
|
||||
background-color: #f5bf4f;
|
||||
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
top: 12px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
top: 12px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.ellipse-3 {
|
||||
background-color: #61c554;
|
||||
.ellipse-3 {
|
||||
background-color: #61c554;
|
||||
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
top: 12px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
top: 12px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.code-console :global(code) {
|
||||
white-space: pre;
|
||||
tab-size: 4;
|
||||
}
|
||||
.code-console :global(code) {
|
||||
white-space: pre;
|
||||
tab-size: 4;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -182,7 +182,7 @@
|
||||
class="web-card is-white web-u-min-block-size-320 u-flex-vertical oss-card"
|
||||
id="oss-discord"
|
||||
>
|
||||
<div class="u-flex-vertical u-main-space-between u-gap-32">
|
||||
<div class="u-flex-vertical u-main-space-between gap-8">
|
||||
<span
|
||||
class="web-icon-discord web-u-font-size-40"
|
||||
aria-hidden="true"
|
||||
@@ -197,7 +197,7 @@
|
||||
id="oss-github"
|
||||
href="https://github.com/appwrite/appwrite"
|
||||
>
|
||||
<div class="u-flex-vertical u-main-space-between u-gap-32">
|
||||
<div class="u-flex-vertical u-main-space-between gap-8">
|
||||
<span
|
||||
class="web-icon-github web-u-font-size-40"
|
||||
aria-hidden="true"
|
||||
@@ -212,7 +212,7 @@
|
||||
class="web-card is-white web-u-min-block-size-320 u-flex-vertical oss-card"
|
||||
id="oss-twitter"
|
||||
>
|
||||
<div class="u-flex-vertical u-main-space-between u-gap-32">
|
||||
<div class="u-flex-vertical u-main-space-between gap-8">
|
||||
<span
|
||||
class="web-icon-x web-u-font-size-40"
|
||||
aria-hidden="true"
|
||||
@@ -227,7 +227,7 @@
|
||||
class="web-card is-white web-u-min-block-size-320 u-flex-vertical oss-card"
|
||||
id="oss-youtube"
|
||||
>
|
||||
<div class="u-flex-vertical u-main-space-between u-gap-32">
|
||||
<div class="u-flex-vertical u-main-space-between gap-8">
|
||||
<span
|
||||
class="web-icon-youtube web-u-font-size-40"
|
||||
aria-hidden="true"
|
||||
@@ -242,7 +242,7 @@
|
||||
id="oss-commits"
|
||||
href="https://github.com/appwrite/appwrite"
|
||||
>
|
||||
<div class="u-flex-vertical u-main-space-between u-gap-32">
|
||||
<div class="u-flex-vertical u-main-space-between gap-8">
|
||||
<span
|
||||
class="web-icon-github web-u-font-size-40"
|
||||
aria-hidden="true"
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script lang="ts">
|
||||
export let id: string | undefined = undefined;
|
||||
export let id: string | undefined = undefined;
|
||||
</script>
|
||||
|
||||
<div class="phone" {id}>
|
||||
<div class="inner">
|
||||
<slot />
|
||||
</div>
|
||||
<div class="inner">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,55 +1,55 @@
|
||||
<script lang="ts">
|
||||
import AutoHeight from '../AutoBox.svelte';
|
||||
import AutoHeight from '../AutoBox.svelte';
|
||||
</script>
|
||||
|
||||
<div class="anim-box">
|
||||
<div class="top"><slot name="top" /></div>
|
||||
<div class="content">
|
||||
<AutoHeight>
|
||||
<slot />
|
||||
</AutoHeight>
|
||||
</div>
|
||||
<div class="top"><slot name="top" /></div>
|
||||
<div class="content">
|
||||
<AutoHeight>
|
||||
<slot />
|
||||
</AutoHeight>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
@use '$scss/abstract/mixins/border-gradient' as gradients;
|
||||
|
||||
.anim-box {
|
||||
@include gradients.border-gradient;
|
||||
--m-border-radius: 1rem;
|
||||
--m-border-gradient-before: linear-gradient(
|
||||
180deg,
|
||||
rgba(255, 255, 255, 0.12) 0%,
|
||||
rgba(255, 255, 255, 0) 125.11%
|
||||
);
|
||||
border-radius: var(--m-border-radius);
|
||||
background: hsl(var(--web-color-card));
|
||||
backdrop-filter: blur(8px);
|
||||
.anim-box {
|
||||
@include gradients.border-gradient;
|
||||
--m-border-radius: 1rem;
|
||||
--m-border-gradient-before: linear-gradient(
|
||||
180deg,
|
||||
rgba(255, 255, 255, 0.12) 0%,
|
||||
rgba(255, 255, 255, 0) 125.11%
|
||||
);
|
||||
border-radius: var(--m-border-radius);
|
||||
background: hsl(var(--web-color-card));
|
||||
backdrop-filter: blur(8px);
|
||||
|
||||
padding: 0.5rem;
|
||||
padding-block-start: 0;
|
||||
padding: 0.5rem;
|
||||
padding-block-start: 0;
|
||||
|
||||
text-align: left;
|
||||
text-align: left;
|
||||
|
||||
.top {
|
||||
color: var(--greyscale-50, #ededf0);
|
||||
font-family: Aeonik Pro;
|
||||
font-size: 1.25rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 2rem; /* 160% */
|
||||
letter-spacing: -0.0125rem;
|
||||
.top {
|
||||
color: var(--greyscale-50, #ededf0);
|
||||
font-family: Aeonik Pro;
|
||||
font-size: 1.25rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 2rem; /* 160% */
|
||||
letter-spacing: -0.0125rem;
|
||||
|
||||
padding: 1rem;
|
||||
text-align: left;
|
||||
}
|
||||
padding: 1rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.content {
|
||||
border-radius: 0.75rem;
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
backdrop-filter: blur(30px);
|
||||
.content {
|
||||
border-radius: 0.75rem;
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
backdrop-filter: blur(30px);
|
||||
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -247,7 +247,7 @@
|
||||
Your backend, minus the hassle
|
||||
</h2>
|
||||
<p
|
||||
class="web-description web-u-max-width-700 u-margin-inline-auto"
|
||||
class="web-description web-u-max-width-700 mx-auto"
|
||||
transition:fly={{
|
||||
y: 16,
|
||||
delay: 400
|
||||
|
||||
@@ -1,61 +1,61 @@
|
||||
<script lang="ts">
|
||||
import { createCheckbox, melt } from '@melt-ui/svelte';
|
||||
import { createCheckbox, melt } from '@melt-ui/svelte';
|
||||
|
||||
export let checked = false;
|
||||
export let checked = false;
|
||||
|
||||
const {
|
||||
elements: { root },
|
||||
states: { checked: localChecked },
|
||||
helpers: { isChecked }
|
||||
} = createCheckbox({
|
||||
onCheckedChange({ next }) {
|
||||
if (typeof next === 'boolean') {
|
||||
checked = next;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
});
|
||||
const {
|
||||
elements: { root },
|
||||
states: { checked: localChecked },
|
||||
helpers: { isChecked }
|
||||
} = createCheckbox({
|
||||
onCheckedChange({ next }) {
|
||||
if (typeof next === 'boolean') {
|
||||
checked = next;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
});
|
||||
|
||||
$: localChecked.set(checked);
|
||||
$: localChecked.set(checked);
|
||||
</script>
|
||||
|
||||
<div class="wrapper">
|
||||
<button use:melt={$root} class="anim-checkbox">
|
||||
{#if $isChecked}
|
||||
<span class="web-icon-check" />
|
||||
{/if}
|
||||
</button>
|
||||
<button use:melt={$root} class="anim-checkbox">
|
||||
{#if $isChecked}
|
||||
<span class="web-icon-check" />
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.wrapper {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
.wrapper {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
.anim-checkbox {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
flex-shrink: 0;
|
||||
.anim-checkbox {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
flex-shrink: 0;
|
||||
|
||||
border-radius: 0.125rem;
|
||||
border: 1.5px solid var(--greyscale-500, #818186);
|
||||
border-radius: 0.125rem;
|
||||
border: 1.5px solid var(--greyscale-500, #818186);
|
||||
|
||||
position: relative;
|
||||
position: relative;
|
||||
|
||||
&:global(.anim-checkbox[data-state='checked']) {
|
||||
background-color: #7c67fe;
|
||||
border-color: #7c67fe;
|
||||
}
|
||||
}
|
||||
&:global(.anim-checkbox[data-state='checked']) {
|
||||
background-color: #7c67fe;
|
||||
border-color: #7c67fe;
|
||||
}
|
||||
}
|
||||
|
||||
[class*='icon-'] {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
[class*='icon-'] {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
|
||||
color: white;
|
||||
font-size: 1rem;
|
||||
}
|
||||
color: white;
|
||||
font-size: 1rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,64 +1,64 @@
|
||||
<script lang="ts">
|
||||
import { getInitials } from '$lib/animations';
|
||||
import { fly } from 'svelte/transition';
|
||||
import { authController } from '.';
|
||||
import { flip } from '$lib/utils/flip';
|
||||
import { getInitials } from '$lib/animations';
|
||||
import { fly } from 'svelte/transition';
|
||||
import { authController } from '.';
|
||||
import { flip } from '$lib/utils/flip';
|
||||
|
||||
const { state } = authController;
|
||||
const { state } = authController;
|
||||
|
||||
type AuthEntry = {
|
||||
avatar: string;
|
||||
name: string;
|
||||
email: string;
|
||||
id: number;
|
||||
};
|
||||
$: authData = [
|
||||
$state.submitted
|
||||
? {
|
||||
avatar: getInitials($state.name),
|
||||
name: $state.name,
|
||||
email: $state.email,
|
||||
id: 0
|
||||
}
|
||||
: undefined,
|
||||
{
|
||||
avatar: 'BD',
|
||||
name: 'Benjamin Davis',
|
||||
email: 'benjamin.davis@example.com',
|
||||
id: 1
|
||||
},
|
||||
{
|
||||
avatar: 'OS',
|
||||
name: 'Olivia Smith',
|
||||
email: 'olivia.smith@example.com',
|
||||
id: 2
|
||||
},
|
||||
{
|
||||
avatar: 'EW',
|
||||
name: 'Ethan Wilson',
|
||||
email: 'ethan.wilson@example.com',
|
||||
id: 3
|
||||
}
|
||||
].filter(Boolean) as AuthEntry[];
|
||||
type AuthEntry = {
|
||||
avatar: string;
|
||||
name: string;
|
||||
email: string;
|
||||
id: number;
|
||||
};
|
||||
$: authData = [
|
||||
$state.submitted
|
||||
? {
|
||||
avatar: getInitials($state.name),
|
||||
name: $state.name,
|
||||
email: $state.email,
|
||||
id: 0
|
||||
}
|
||||
: undefined,
|
||||
{
|
||||
avatar: 'BD',
|
||||
name: 'Benjamin Davis',
|
||||
email: 'benjamin.davis@example.com',
|
||||
id: 1
|
||||
},
|
||||
{
|
||||
avatar: 'OS',
|
||||
name: 'Olivia Smith',
|
||||
email: 'olivia.smith@example.com',
|
||||
id: 2
|
||||
},
|
||||
{
|
||||
avatar: 'EW',
|
||||
name: 'Ethan Wilson',
|
||||
email: 'ethan.wilson@example.com',
|
||||
id: 3
|
||||
}
|
||||
].filter(Boolean) as AuthEntry[];
|
||||
</script>
|
||||
|
||||
<div class="pseudo-table">
|
||||
<div class="header">
|
||||
<span class="web-eyebrow">Name</span>
|
||||
<span class="web-eyebrow">Identifier</span>
|
||||
</div>
|
||||
{#each authData as user (user.id)}
|
||||
<div
|
||||
class="row"
|
||||
in:fly={{ duration: 100, x: -16, delay: 100 }}
|
||||
out:fly={{ duration: 100, x: -16 }}
|
||||
animate:flip={{ duration: 150 }}
|
||||
>
|
||||
<div class="u-flex u-cross-center u-gap-12">
|
||||
<div class="avatar is-size-small">{user.avatar}</div>
|
||||
<span class="truncated">{user.name}</span>
|
||||
</div>
|
||||
<span class="truncated">{user.email}</span>
|
||||
</div>
|
||||
{/each}
|
||||
<div class="header">
|
||||
<span class="web-eyebrow">Name</span>
|
||||
<span class="web-eyebrow">Identifier</span>
|
||||
</div>
|
||||
{#each authData as user (user.id)}
|
||||
<div
|
||||
class="row"
|
||||
in:fly={{ duration: 100, x: -16, delay: 100 }}
|
||||
out:fly={{ duration: 100, x: -16 }}
|
||||
animate:flip={{ duration: 150 }}
|
||||
>
|
||||
<div class="flex u-cross-center gap-3">
|
||||
<div class="avatar is-size-small">{user.avatar}</div>
|
||||
<span class="truncated">{user.name}</span>
|
||||
</div>
|
||||
<span class="truncated">{user.email}</span>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -1,211 +1,220 @@
|
||||
<script lang="ts">
|
||||
import { fade } from 'svelte/transition';
|
||||
import { authController } from '.';
|
||||
import { objectKeys } from '$lib/utils/object';
|
||||
import { flip } from '$lib/utils/flip';
|
||||
import { fade } from 'svelte/transition';
|
||||
import { authController } from '.';
|
||||
import { objectKeys } from '$lib/utils/object';
|
||||
import { flip } from '$lib/utils/flip';
|
||||
|
||||
const { state } = authController;
|
||||
const { state } = authController;
|
||||
|
||||
$: controlsEnabled = $state.showControls && Object.values($state.controls).some(Boolean);
|
||||
$: controlsEnabled = $state.showControls && Object.values($state.controls).some(Boolean);
|
||||
</script>
|
||||
|
||||
<div data-theme-ignore class="inner-phone theme-light">
|
||||
<p class="title">Create an Account</p>
|
||||
<p class="subtitle">Please enter your details</p>
|
||||
<div class="inputs">
|
||||
<fieldset>
|
||||
<label for="name">Your Name</label>
|
||||
<input type="name" id="name" placeholder="Enter your name" bind:value={$state.name} />
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<label for="email">Your Email</label>
|
||||
<input type="email" id="email" placeholder="Enter your email" bind:value={$state.email} />
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<label for="password">Create Password</label>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
placeholder="Enter Password"
|
||||
bind:value={$state.password}
|
||||
/>
|
||||
</fieldset>
|
||||
</div>
|
||||
<button class="sign-up">Sign Up</button>
|
||||
{#if controlsEnabled}
|
||||
<span class="with-sep" transition:fade={{ duration: 100 }}>or sign up with</span>
|
||||
<div class="oauth-btns" transition:fade={{ duration: 100 }}>
|
||||
{#each objectKeys($state.controls).filter((p) => $state.controls[p]) as provider (provider)}
|
||||
<button class="oauth" transition:fade={{ duration: 100 }} animate:flip={{ duration: 250 }}>
|
||||
<div class="inner">
|
||||
<span class="web-icon-{provider.toLowerCase()}" />
|
||||
<span>{provider}</span>
|
||||
</div>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
<div data-theme-ignore class="inner-phone light">
|
||||
<p class="title">Create an Account</p>
|
||||
<p class="subtitle">Please enter your details</p>
|
||||
<div class="inputs">
|
||||
<fieldset>
|
||||
<label for="name">Your Name</label>
|
||||
<input type="name" id="name" placeholder="Enter your name" bind:value={$state.name} />
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<label for="email">Your Email</label>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
placeholder="Enter your email"
|
||||
bind:value={$state.email}
|
||||
/>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<label for="password">Create Password</label>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
placeholder="Enter Password"
|
||||
bind:value={$state.password}
|
||||
/>
|
||||
</fieldset>
|
||||
</div>
|
||||
<button class="sign-up">Sign Up</button>
|
||||
{#if controlsEnabled}
|
||||
<span class="with-sep" transition:fade={{ duration: 100 }}>or sign up with</span>
|
||||
<div class="oauth-btns" transition:fade={{ duration: 100 }}>
|
||||
{#each objectKeys($state.controls).filter((p) => $state.controls[p]) as provider (provider)}
|
||||
<button
|
||||
class="oauth"
|
||||
transition:fade={{ duration: 100 }}
|
||||
animate:flip={{ duration: 250 }}
|
||||
>
|
||||
<div class="inner">
|
||||
<span class="web-icon-{provider.toLowerCase()}" />
|
||||
<span>{provider}</span>
|
||||
</div>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.inner-phone {
|
||||
padding-block: 3rem;
|
||||
padding-inline: 1rem;
|
||||
.inner-phone {
|
||||
padding-block: 3rem;
|
||||
padding-inline: 1rem;
|
||||
|
||||
color: rgba(67, 67, 71, 1);
|
||||
text-align: left;
|
||||
color: rgba(67, 67, 71, 1);
|
||||
text-align: left;
|
||||
|
||||
.title {
|
||||
color: #434347;
|
||||
font-family: Inter;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 22px; /* 137.5% */
|
||||
letter-spacing: -0.224px;
|
||||
}
|
||||
.title {
|
||||
color: #434347;
|
||||
font-family: Inter;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 22px; /* 137.5% */
|
||||
letter-spacing: -0.224px;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
||||
font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 20px; /* 142.857% */
|
||||
letter-spacing: -0.196px;
|
||||
}
|
||||
.subtitle {
|
||||
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
||||
font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 20px; /* 142.857% */
|
||||
letter-spacing: -0.196px;
|
||||
}
|
||||
|
||||
.inputs {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
margin-block-start: 1.5rem;
|
||||
.inputs {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
margin-block-start: 1.5rem;
|
||||
|
||||
fieldset {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.3125rem;
|
||||
width: 100%;
|
||||
fieldset {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.3125rem;
|
||||
width: 100%;
|
||||
|
||||
label {
|
||||
color: var(--color-greyscale-700, #56565c);
|
||||
font-family: Inter;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 16px; /* 133.333% */
|
||||
letter-spacing: -0.168px;
|
||||
}
|
||||
label {
|
||||
color: var(--color-greyscale-700, #56565c);
|
||||
font-family: Inter;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 16px; /* 133.333% */
|
||||
letter-spacing: -0.168px;
|
||||
}
|
||||
|
||||
input {
|
||||
all: unset;
|
||||
display: flex;
|
||||
padding: 8px 12px;
|
||||
align-items: flex-start;
|
||||
align-self: stretch;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #d8d8db;
|
||||
input {
|
||||
all: unset;
|
||||
display: flex;
|
||||
padding: 8px 12px;
|
||||
align-items: flex-start;
|
||||
align-self: stretch;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #d8d8db;
|
||||
|
||||
color: #434347;
|
||||
font-family: Inter;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 16px; /* 133.333% */
|
||||
letter-spacing: -0.168px;
|
||||
}
|
||||
}
|
||||
}
|
||||
color: #434347;
|
||||
font-family: Inter;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 16px; /* 133.333% */
|
||||
letter-spacing: -0.168px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sign-up {
|
||||
padding: 0.375rem 0.75rem;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
margin-block-start: 1.25rem;
|
||||
.sign-up {
|
||||
padding: 0.375rem 0.75rem;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
margin-block-start: 1.25rem;
|
||||
|
||||
border-radius: 0.5rem;
|
||||
background: var(--appwrite-purple, #7c67fe);
|
||||
box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.06);
|
||||
border-radius: 0.5rem;
|
||||
background: var(--appwrite-purple, #7c67fe);
|
||||
box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.06);
|
||||
|
||||
color: var(--color-bw-white, #fff);
|
||||
text-align: center;
|
||||
color: var(--color-bw-white, #fff);
|
||||
text-align: center;
|
||||
|
||||
/* Responsive/SubBody-500 */
|
||||
font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 22px; /* 157.143% */
|
||||
letter-spacing: -0.07px;
|
||||
}
|
||||
/* Responsive/SubBody-500 */
|
||||
font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 22px; /* 157.143% */
|
||||
letter-spacing: -0.07px;
|
||||
}
|
||||
|
||||
.with-sep {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
.with-sep {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
|
||||
font-family: Inter;
|
||||
font-size: 0.75rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.25rem; /* 166.667% */
|
||||
letter-spacing: -0.0105rem;
|
||||
color: hsl(var(--web-color-greyscale-500));
|
||||
font-family: Inter;
|
||||
font-size: 0.75rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.25rem; /* 166.667% */
|
||||
letter-spacing: -0.0105rem;
|
||||
color: hsl(var(--web-color-greyscale-500));
|
||||
|
||||
margin-block-start: 0.75rem;
|
||||
margin-block-start: 0.75rem;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: '';
|
||||
height: 1px;
|
||||
flex-grow: 1;
|
||||
background-color: hsl(var(--web-color-greyscale-200));
|
||||
}
|
||||
}
|
||||
&::before,
|
||||
&::after {
|
||||
content: '';
|
||||
height: 1px;
|
||||
flex-grow: 1;
|
||||
background-color: hsl(var(--web-color-greyscale-200));
|
||||
}
|
||||
}
|
||||
|
||||
.oauth-btns {
|
||||
--gap: 0.5rem;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--gap);
|
||||
margin-block-start: 0.75rem;
|
||||
}
|
||||
.oauth-btns {
|
||||
--gap: 0.5rem;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--gap);
|
||||
margin-block-start: 0.75rem;
|
||||
}
|
||||
|
||||
.oauth {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.oauth {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
border-radius: 0.5rem;
|
||||
border: 1px solid #d9d9d9;
|
||||
color: hsl(var(--web-color-greyscale-750));
|
||||
text-align: center;
|
||||
border-radius: 0.5rem;
|
||||
border: 1px solid #d9d9d9;
|
||||
color: hsl(var(--web-color-greyscale-750));
|
||||
text-align: center;
|
||||
|
||||
/* Responsive/Caption-500 */
|
||||
font-family: Inter;
|
||||
font-size: 0.875rem;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 1.375rem; /* 157.143% */
|
||||
letter-spacing: -0.01575rem;
|
||||
/* Responsive/Caption-500 */
|
||||
font-family: Inter;
|
||||
font-size: 0.875rem;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 1.375rem; /* 157.143% */
|
||||
letter-spacing: -0.01575rem;
|
||||
|
||||
flex: 1 1 calc(50% - var(--gap));
|
||||
padding-block: 0.375rem;
|
||||
position: relative;
|
||||
height: 2.125rem;
|
||||
flex: 1 1 calc(50% - var(--gap));
|
||||
padding-block: 0.375rem;
|
||||
position: relative;
|
||||
height: 2.125rem;
|
||||
|
||||
.inner {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
.inner {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
transform: translate(-50%, -50%) scale(var(--inverse-sx, 1), var(--inverse-sy, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
transform: translate(-50%, -50%) scale(var(--inverse-sx, 1), var(--inverse-sy, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
<script lang="ts">
|
||||
import { slide } from 'svelte/transition';
|
||||
import { databasesController } from '.';
|
||||
import { flip } from '$lib/utils/flip';
|
||||
import { slide } from 'svelte/transition';
|
||||
import { databasesController } from '.';
|
||||
import { flip } from '$lib/utils/flip';
|
||||
|
||||
const { state } = databasesController;
|
||||
const { state } = databasesController;
|
||||
</script>
|
||||
|
||||
<div class="pseudo-table">
|
||||
<div class="header">
|
||||
<span class="web-eyebrow">Document ID</span>
|
||||
<span class="web-eyebrow">Task</span>
|
||||
</div>
|
||||
{#each $state.tasks.slice(0, $state.tableSlice) as task (task.id)}
|
||||
<div class="row" transition:slide={{ duration: 150 }} animate:flip={{ duration: 150 }}>
|
||||
<div class="copy-button">
|
||||
<span class="web-icon-copy" />
|
||||
<span>{task.id}</span>
|
||||
</div>
|
||||
<span class="truncated">{task.title}</span>
|
||||
</div>
|
||||
{/each}
|
||||
<div class="header">
|
||||
<span class="web-eyebrow">Document ID</span>
|
||||
<span class="web-eyebrow">Task</span>
|
||||
</div>
|
||||
{#each $state.tasks.slice(0, $state.tableSlice) as task (task.id)}
|
||||
<div class="row" transition:slide={{ duration: 150 }} animate:flip={{ duration: 150 }}>
|
||||
<div class="copy-button">
|
||||
<span class="web-icon-copy" />
|
||||
<span>{task.id}</span>
|
||||
</div>
|
||||
<span class="truncated">{task.title}</span>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.copy-button {
|
||||
display: flex;
|
||||
padding: 0.25rem 0.5rem;
|
||||
align-items: center;
|
||||
gap: 0.375rem;
|
||||
.copy-button {
|
||||
display: flex;
|
||||
padding: 0.25rem 0.5rem;
|
||||
align-items: center;
|
||||
gap: 0.375rem;
|
||||
|
||||
border-radius: 62.4375rem;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
backdrop-filter: blur(2.6666667461395264px);
|
||||
border-radius: 62.4375rem;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
backdrop-filter: blur(2.6666667461395264px);
|
||||
|
||||
[class*='icon-'] {
|
||||
font-size: 1.25rem;
|
||||
color: hsl(var(--web-color-greyscale-600));
|
||||
}
|
||||
[class*='icon-'] {
|
||||
font-size: 1.25rem;
|
||||
color: hsl(var(--web-color-greyscale-600));
|
||||
}
|
||||
|
||||
span:not([class*='icon-']) {
|
||||
color: var(--greyscale-400, #adadb1);
|
||||
font-family: Inter;
|
||||
font-size: 0.875rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.25rem; /* 142.857% */
|
||||
span:not([class*='icon-']) {
|
||||
color: var(--greyscale-400, #adadb1);
|
||||
font-family: Inter;
|
||||
font-size: 0.875rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.25rem; /* 142.857% */
|
||||
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import Code from '$lib/animations/CodeWindow/Code.svelte';
|
||||
import Code from '$lib/animations/CodeWindow/Code.svelte';
|
||||
|
||||
let content = `
|
||||
let content = `
|
||||
const result = databases.createDocument(
|
||||
'Your-tasks',
|
||||
tasks,
|
||||
|
||||
@@ -7,88 +7,88 @@ import { createResettable } from '$lib/utils/resettable';
|
||||
import { getElSelector } from '../Products.svelte';
|
||||
|
||||
type Task = {
|
||||
id: string;
|
||||
title: string;
|
||||
checked: boolean;
|
||||
id: string;
|
||||
title: string;
|
||||
checked: boolean;
|
||||
};
|
||||
|
||||
type State = {
|
||||
tasks: Task[];
|
||||
tableSlice: number;
|
||||
tasks: Task[];
|
||||
tableSlice: number;
|
||||
};
|
||||
|
||||
const state = createResettable<State>({
|
||||
tasks: [
|
||||
{
|
||||
id: '3397fecdedb13397fecdedb1',
|
||||
title: 'Research user needs',
|
||||
checked: true
|
||||
}
|
||||
],
|
||||
tableSlice: 1
|
||||
tasks: [
|
||||
{
|
||||
id: '3397fecdedb13397fecdedb1',
|
||||
title: 'Research user needs',
|
||||
checked: true
|
||||
}
|
||||
],
|
||||
tableSlice: 1
|
||||
});
|
||||
|
||||
const execute = async () => {
|
||||
const phone = getElSelector('phone');
|
||||
const box = getElSelector('box');
|
||||
const code = getElSelector('code');
|
||||
const { update } = state.reset();
|
||||
const phone = getElSelector('phone');
|
||||
const box = getElSelector('box');
|
||||
const code = getElSelector('code');
|
||||
const { update } = state.reset();
|
||||
|
||||
await Promise.all([
|
||||
safeAnimate(phone, { x: 390, y: 0 }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(box, { x: 0, y: 32, opacity: 1 }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(code, { x: 80, y: 320, opacity: 1 }, { duration: 0.5 })?.finished
|
||||
]);
|
||||
await Promise.all([
|
||||
safeAnimate(phone, { x: 390, y: 0 }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(box, { x: 0, y: 32, opacity: 1 }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(code, { x: 80, y: 320, opacity: 1 }, { duration: 0.5 })?.finished
|
||||
]);
|
||||
|
||||
await sleep(250);
|
||||
await sleep(250);
|
||||
|
||||
update((p) => ({
|
||||
...p,
|
||||
tasks: [
|
||||
...p.tasks,
|
||||
{
|
||||
id: '3397fecdedb13397fecdedb2',
|
||||
title: 'Create wireframes',
|
||||
checked: false
|
||||
}
|
||||
]
|
||||
}));
|
||||
await sleep(250);
|
||||
update((p) => ({
|
||||
...p,
|
||||
tasks: [
|
||||
...p.tasks,
|
||||
{
|
||||
id: '3397fecdedb13397fecdedb2',
|
||||
title: 'Create wireframes',
|
||||
checked: false
|
||||
}
|
||||
]
|
||||
}));
|
||||
await sleep(250);
|
||||
|
||||
update((p) => ({
|
||||
...p,
|
||||
tableSlice: p.tableSlice + 1
|
||||
}));
|
||||
update((p) => ({
|
||||
...p,
|
||||
tableSlice: p.tableSlice + 1
|
||||
}));
|
||||
|
||||
await sleep(250);
|
||||
await sleep(250);
|
||||
|
||||
update((p) => ({
|
||||
...p,
|
||||
tasks: [
|
||||
...p.tasks,
|
||||
{
|
||||
id: '3397fecdedb13397fecdedb3',
|
||||
title: 'Create visual design',
|
||||
checked: false
|
||||
}
|
||||
]
|
||||
}));
|
||||
update((p) => ({
|
||||
...p,
|
||||
tasks: [
|
||||
...p.tasks,
|
||||
{
|
||||
id: '3397fecdedb13397fecdedb3',
|
||||
title: 'Create visual design',
|
||||
checked: false
|
||||
}
|
||||
]
|
||||
}));
|
||||
|
||||
await sleep(250);
|
||||
await sleep(250);
|
||||
|
||||
update((p) => ({
|
||||
...p,
|
||||
tableSlice: p.tableSlice + 1
|
||||
}));
|
||||
update((p) => ({
|
||||
...p,
|
||||
tableSlice: p.tableSlice + 1
|
||||
}));
|
||||
};
|
||||
|
||||
export const databasesController = {
|
||||
execute,
|
||||
state
|
||||
execute,
|
||||
state
|
||||
};
|
||||
|
||||
export const Databases = {
|
||||
Phone,
|
||||
Box,
|
||||
Code
|
||||
Phone,
|
||||
Box,
|
||||
Code
|
||||
};
|
||||
|
||||
@@ -1,127 +1,127 @@
|
||||
<script lang="ts">
|
||||
import { fly } from 'svelte/transition';
|
||||
import { databasesController } from '.';
|
||||
import TaskCheckbox from '../TaskCheckbox.svelte';
|
||||
import { fly } from 'svelte/transition';
|
||||
import { databasesController } from '.';
|
||||
import TaskCheckbox from '../TaskCheckbox.svelte';
|
||||
|
||||
const { state } = databasesController;
|
||||
const { state } = databasesController;
|
||||
</script>
|
||||
|
||||
<div data-theme-ignore class="inner-phone theme-light">
|
||||
<div class="header">
|
||||
<p class="title">Your tasks</p>
|
||||
<span class="icon-menu" aria-label="menu" />
|
||||
</div>
|
||||
<div data-theme-ignore class="inner-phone light">
|
||||
<div class="header">
|
||||
<p class="title">Your tasks</p>
|
||||
<span class="icon-menu" aria-label="menu" />
|
||||
</div>
|
||||
|
||||
<div class="date">Today</div>
|
||||
<div class="tasks">
|
||||
{#each $state.tasks as task (task.id)}
|
||||
<div class="task" data-checked={task.checked ? '' : undefined} in:fly={{ x: -16 }}>
|
||||
<TaskCheckbox bind:checked={task.checked} />
|
||||
<span class="title">{task.title}</span>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
<div class="date">Today</div>
|
||||
<div class="tasks">
|
||||
{#each $state.tasks as task (task.id)}
|
||||
<div class="task" data-checked={task.checked ? '' : undefined} in:fly={{ x: -16 }}>
|
||||
<TaskCheckbox bind:checked={task.checked} />
|
||||
<span class="title">{task.title}</span>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<button class="add-btn">
|
||||
<span class="web-icon-plus" />
|
||||
</button>
|
||||
<button class="add-btn">
|
||||
<span class="web-icon-plus" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.inner-phone {
|
||||
padding-block: 3rem;
|
||||
padding-inline: 1rem;
|
||||
.inner-phone {
|
||||
padding-block: 3rem;
|
||||
padding-inline: 1rem;
|
||||
|
||||
color: rgba(67, 67, 71, 1);
|
||||
text-align: left;
|
||||
color: rgba(67, 67, 71, 1);
|
||||
text-align: left;
|
||||
|
||||
position: relative;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.title {
|
||||
color: var(--color-greyscale-800, #2d2d31);
|
||||
font-family: Inter;
|
||||
font-size: 1rem;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 1.375rem; /* 137.5% */
|
||||
letter-spacing: -0.014rem;
|
||||
}
|
||||
.title {
|
||||
color: var(--color-greyscale-800, #2d2d31);
|
||||
font-family: Inter;
|
||||
font-size: 1rem;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 1.375rem; /* 137.5% */
|
||||
letter-spacing: -0.014rem;
|
||||
}
|
||||
|
||||
[class*='icon-'] {
|
||||
font-size: 1.25rem;
|
||||
color: hsl(var(--web-color-greyscale-500));
|
||||
}
|
||||
}
|
||||
[class*='icon-'] {
|
||||
font-size: 1.25rem;
|
||||
color: hsl(var(--web-color-greyscale-500));
|
||||
}
|
||||
}
|
||||
|
||||
.date {
|
||||
margin-block-start: 3rem;
|
||||
.date {
|
||||
margin-block-start: 3rem;
|
||||
|
||||
color: hsl(var(--web-color-greyscale-600));
|
||||
font-family: Inter;
|
||||
font-size: 0.75rem;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 1.25rem; /* 166.667% */
|
||||
}
|
||||
color: hsl(var(--web-color-greyscale-600));
|
||||
font-family: Inter;
|
||||
font-size: 0.75rem;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 1.25rem; /* 166.667% */
|
||||
}
|
||||
|
||||
.tasks {
|
||||
margin-block-start: 0.5rem;
|
||||
.tasks {
|
||||
margin-block-start: 0.5rem;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
|
||||
.task {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
.task {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
|
||||
border-radius: 0.5rem;
|
||||
border: 1px solid hsl(var(--web-color-greyscale-50));
|
||||
background: hsl(var(--web-color-white));
|
||||
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
||||
border-radius: 0.5rem;
|
||||
border: 1px solid hsl(var(--web-color-greyscale-50));
|
||||
background: hsl(var(--web-color-white));
|
||||
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
||||
|
||||
padding-block: 0.55rem;
|
||||
padding-inline: 0.88rem;
|
||||
padding-block: 0.55rem;
|
||||
padding-inline: 0.88rem;
|
||||
|
||||
/* Responsive/SubBody-400 */
|
||||
font-family: Inter;
|
||||
font-size: 0.875rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.375rem; /* 157.143% */
|
||||
letter-spacing: -0.00394rem;
|
||||
/* Responsive/SubBody-400 */
|
||||
font-family: Inter;
|
||||
font-size: 0.875rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.375rem; /* 157.143% */
|
||||
letter-spacing: -0.00394rem;
|
||||
|
||||
transition: opacity 200ms ease;
|
||||
transition: opacity 200ms ease;
|
||||
|
||||
&[data-checked] {
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
&[data-checked] {
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.add-btn {
|
||||
position: absolute;
|
||||
right: 1rem;
|
||||
bottom: 2.5rem;
|
||||
.add-btn {
|
||||
position: absolute;
|
||||
right: 1rem;
|
||||
bottom: 2.5rem;
|
||||
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.12);
|
||||
background-color: rgba(124, 103, 254, 1);
|
||||
color: rgba(237, 237, 240, 1);
|
||||
font-size: 1.5rem;
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.12);
|
||||
background-color: rgba(124, 103, 254, 1);
|
||||
color: rgba(237, 237, 240, 1);
|
||||
font-size: 1.5rem;
|
||||
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border-radius: 100%;
|
||||
}
|
||||
}
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border-radius: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { portal } from '$lib/actions';
|
||||
import Code from '$lib/animations/CodeWindow/Code.svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
import { functionsController } from '.';
|
||||
import { portal } from '$lib/actions';
|
||||
import Code from '$lib/animations/CodeWindow/Code.svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
import { functionsController } from '.';
|
||||
|
||||
let content = `
|
||||
let content = `
|
||||
const userId = req.headers['user-id'];
|
||||
|
||||
if (req.path === '/subscribe') {
|
||||
@@ -18,39 +18,39 @@ if (req.path === '/webhook') {
|
||||
|
||||
return res.json({ success: true });`.trim();
|
||||
|
||||
const { state } = functionsController;
|
||||
const { state } = functionsController;
|
||||
</script>
|
||||
|
||||
<Code {content} />
|
||||
|
||||
<div use:portal={{ target: '#code-bottom' }} class="bottom">
|
||||
{#if $state.submit !== 'idle'}
|
||||
<span class="web-icon-github" in:fade />
|
||||
{/if}
|
||||
{#if $state.submit === 'loading'}
|
||||
<span in:fade>Pushing to GitHub...</span>
|
||||
<div class="loader is-small" in:fade />
|
||||
{:else if $state.submit === 'success'}
|
||||
<span>Deployed to Appwrite Cloud</span>
|
||||
<span class="web-icon-check" />
|
||||
{/if}
|
||||
{#if $state.submit !== 'idle'}
|
||||
<span class="web-icon-github" in:fade />
|
||||
{/if}
|
||||
{#if $state.submit === 'loading'}
|
||||
<span in:fade>Pushing to GitHub...</span>
|
||||
<div class="loader is-small" in:fade />
|
||||
{:else if $state.submit === 'success'}
|
||||
<span>Deployed to Appwrite Cloud</span>
|
||||
<span class="web-icon-check" />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.bottom {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
.bottom {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
|
||||
height: 3rem;
|
||||
padding-inline: 1rem;
|
||||
height: 3rem;
|
||||
padding-inline: 1rem;
|
||||
|
||||
color: var(--color-bw-white, #fff);
|
||||
font-family: Inter;
|
||||
font-size: 0.875rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 150%; /* 1.3125rem */
|
||||
letter-spacing: -0.00875rem;
|
||||
}
|
||||
color: var(--color-bw-white, #fff);
|
||||
font-family: Inter;
|
||||
font-size: 0.875rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 150%; /* 1.3125rem */
|
||||
letter-spacing: -0.00875rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -6,53 +6,53 @@ import { createResettable } from '$lib/utils/resettable';
|
||||
import { getElSelector } from '../Products.svelte';
|
||||
|
||||
type State = {
|
||||
submit: 'idle' | 'loading' | 'success';
|
||||
submit: 'idle' | 'loading' | 'success';
|
||||
};
|
||||
|
||||
const state = createResettable<State>({
|
||||
submit: 'idle'
|
||||
submit: 'idle'
|
||||
});
|
||||
|
||||
const execute = async () => {
|
||||
const phone = getElSelector('phone');
|
||||
const box = getElSelector('box');
|
||||
const code = getElSelector('code');
|
||||
const phone = getElSelector('phone');
|
||||
const box = getElSelector('box');
|
||||
const code = getElSelector('code');
|
||||
|
||||
const { update } = state.reset();
|
||||
const { update } = state.reset();
|
||||
|
||||
await Promise.all([
|
||||
safeAnimate(phone, { x: 430, y: 0, width: '275px' }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(code, { x: 0, y: 200, opacity: 0 }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(box, { opacity: 0 }, { duration: 0.5 })?.finished
|
||||
]);
|
||||
await Promise.all([
|
||||
safeAnimate(phone, { x: 430, y: 0, width: '275px' }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(code, { x: 0, y: 200, opacity: 0 }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(box, { opacity: 0 }, { duration: 0.5 })?.finished
|
||||
]);
|
||||
|
||||
await sleep(250);
|
||||
await sleep(250);
|
||||
|
||||
await safeAnimate(code, { zIndex: 0 }, { duration: 0 })?.finished;
|
||||
await safeAnimate(code, { y: [200 - 16, 200], opacity: 1 }, { duration: 0.5 })?.finished;
|
||||
await safeAnimate(code, { zIndex: 0 }, { duration: 0 })?.finished;
|
||||
await safeAnimate(code, { y: [200 - 16, 200], opacity: 1 }, { duration: 0.5 })?.finished;
|
||||
|
||||
await sleep(250);
|
||||
await sleep(250);
|
||||
|
||||
update((p) => ({
|
||||
...p,
|
||||
submit: 'loading'
|
||||
}));
|
||||
update((p) => ({
|
||||
...p,
|
||||
submit: 'loading'
|
||||
}));
|
||||
|
||||
await sleep(1500);
|
||||
await sleep(1500);
|
||||
|
||||
update((p) => ({
|
||||
...p,
|
||||
submit: 'success'
|
||||
}));
|
||||
update((p) => ({
|
||||
...p,
|
||||
submit: 'success'
|
||||
}));
|
||||
};
|
||||
|
||||
export const functionsController = {
|
||||
execute,
|
||||
state
|
||||
execute,
|
||||
state
|
||||
};
|
||||
|
||||
export const Functions = {
|
||||
Phone,
|
||||
Phone,
|
||||
|
||||
Code
|
||||
Code
|
||||
};
|
||||
|
||||
@@ -1,325 +1,325 @@
|
||||
<script lang="ts">
|
||||
import { flip } from '$lib/utils/flip';
|
||||
import { crossfade, scale, slide } from 'svelte/transition';
|
||||
import { functionsController } from '.';
|
||||
import { flip } from '$lib/utils/flip';
|
||||
import { crossfade, scale, slide } from 'svelte/transition';
|
||||
import { functionsController } from '.';
|
||||
|
||||
const { state } = functionsController;
|
||||
const { state } = functionsController;
|
||||
|
||||
type Method = {
|
||||
icon: string;
|
||||
label: string;
|
||||
};
|
||||
type Method = {
|
||||
icon: string;
|
||||
label: string;
|
||||
};
|
||||
|
||||
$: methods = [
|
||||
$state.submit === 'success' && {
|
||||
icon: '/images/animations/stripe.png',
|
||||
label: 'Stripe'
|
||||
},
|
||||
{
|
||||
icon: '/images/animations/credit-card.svg',
|
||||
label: 'Card'
|
||||
},
|
||||
{
|
||||
icon: '/images/animations/paypal.svg',
|
||||
label: 'PayPal'
|
||||
},
|
||||
{
|
||||
icon: '/images/animations/apple.svg',
|
||||
label: 'Apple'
|
||||
}
|
||||
].filter(Boolean) as Method[];
|
||||
$: methods = [
|
||||
$state.submit === 'success' && {
|
||||
icon: '/images/animations/stripe.png',
|
||||
label: 'Stripe'
|
||||
},
|
||||
{
|
||||
icon: '/images/animations/credit-card.svg',
|
||||
label: 'Card'
|
||||
},
|
||||
{
|
||||
icon: '/images/animations/paypal.svg',
|
||||
label: 'PayPal'
|
||||
},
|
||||
{
|
||||
icon: '/images/animations/apple.svg',
|
||||
label: 'Apple'
|
||||
}
|
||||
].filter(Boolean) as Method[];
|
||||
</script>
|
||||
|
||||
<div data-theme-ignore class="inner-phone theme-light">
|
||||
<div class="header">
|
||||
<p class="title">Upgrade plan</p>
|
||||
<span class="icon-menu" aria-label="menu" />
|
||||
</div>
|
||||
<div data-theme-ignore class="inner-phone light">
|
||||
<div class="header">
|
||||
<p class="title">Upgrade plan</p>
|
||||
<span class="icon-menu" aria-label="menu" />
|
||||
</div>
|
||||
|
||||
<div class="plan">
|
||||
<p class="title">Premium plan</p>
|
||||
<div class="subscription">
|
||||
<p class="price">$20</p>
|
||||
<p class="period">/month</p>
|
||||
</div>
|
||||
<ul>
|
||||
<li>Premium plan</li>
|
||||
<li>Premium plan</li>
|
||||
<li>Premium plan</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="plan">
|
||||
<p class="title">Premium plan</p>
|
||||
<div class="subscription">
|
||||
<p class="price">$20</p>
|
||||
<p class="period">/month</p>
|
||||
</div>
|
||||
<ul>
|
||||
<li>Premium plan</li>
|
||||
<li>Premium plan</li>
|
||||
<li>Premium plan</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<ul class="methods">
|
||||
{#each methods as method, i (method.label)}
|
||||
<li
|
||||
in:scale={{ delay: 150 }}
|
||||
animate:flip={{ duration: 500 }}
|
||||
data-active={i == 0 ? '' : undefined}
|
||||
>
|
||||
<img src={method.icon} alt="" />
|
||||
<p>{method.label}</p>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
<ul class="methods">
|
||||
{#each methods as method, i (method.label)}
|
||||
<li
|
||||
in:scale={{ delay: 150 }}
|
||||
animate:flip={{ duration: 500 }}
|
||||
data-active={i == 0 ? '' : undefined}
|
||||
>
|
||||
<img src={method.icon} alt="" />
|
||||
<p>{method.label}</p>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
|
||||
{#if $state.submit !== 'success'}
|
||||
<div class="form">
|
||||
<p>Card information</p>
|
||||
<div class="bordered">
|
||||
<div>
|
||||
<p>placeholder</p>
|
||||
<img src="/images/animations/visa.png" alt="" />
|
||||
<img src="/images/animations/mastercard.png" alt="" />
|
||||
</div>
|
||||
<div>
|
||||
<p>MM/YY</p>
|
||||
<p>CVV</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if $state.submit !== 'success'}
|
||||
<div class="form">
|
||||
<p>Card information</p>
|
||||
<div class="bordered">
|
||||
<div>
|
||||
<p>placeholder</p>
|
||||
<img src="/images/animations/visa.png" alt="" />
|
||||
<img src="/images/animations/mastercard.png" alt="" />
|
||||
</div>
|
||||
<div>
|
||||
<p>MM/YY</p>
|
||||
<p>CVV</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<button>
|
||||
Pay $20.00
|
||||
{#if $state.submit === 'success'}
|
||||
<span in:slide={{ axis: 'x' }}>on Stripe</span>
|
||||
{/if}
|
||||
</button>
|
||||
<button>
|
||||
Pay $20.00
|
||||
{#if $state.submit === 'success'}
|
||||
<span in:slide={{ axis: 'x' }}>on Stripe</span>
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.inner-phone {
|
||||
padding-block: 3rem 1.5rem;
|
||||
padding-inline: 1rem;
|
||||
.inner-phone {
|
||||
padding-block: 3rem 1.5rem;
|
||||
padding-inline: 1rem;
|
||||
|
||||
color: rgba(67, 67, 71, 1);
|
||||
text-align: left;
|
||||
color: rgba(67, 67, 71, 1);
|
||||
text-align: left;
|
||||
|
||||
position: relative;
|
||||
height: 100%;
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
overflow: visible;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.title {
|
||||
color: #434347;
|
||||
font-family: Inter;
|
||||
font-size: 1rem;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 1.375rem; /* 137.5% */
|
||||
letter-spacing: -0.014rem;
|
||||
}
|
||||
.title {
|
||||
color: #434347;
|
||||
font-family: Inter;
|
||||
font-size: 1rem;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 1.375rem; /* 137.5% */
|
||||
letter-spacing: -0.014rem;
|
||||
}
|
||||
|
||||
[class*='icon-'] {
|
||||
font-size: 1.25rem;
|
||||
color: hsl(var(--web-color-greyscale-500));
|
||||
}
|
||||
}
|
||||
[class*='icon-'] {
|
||||
font-size: 1.25rem;
|
||||
color: hsl(var(--web-color-greyscale-500));
|
||||
}
|
||||
}
|
||||
|
||||
.plan {
|
||||
display: flex;
|
||||
padding: 0.75rem 1rem;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
.plan {
|
||||
display: flex;
|
||||
padding: 0.75rem 1rem;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
|
||||
border-radius: 0.75rem;
|
||||
background: rgba(237, 237, 240, 0.5);
|
||||
border-radius: 0.75rem;
|
||||
background: rgba(237, 237, 240, 0.5);
|
||||
|
||||
margin-block-start: 1rem;
|
||||
margin-block-start: 1rem;
|
||||
|
||||
.title {
|
||||
color: var(--color-greyscale-700, #56565c);
|
||||
font-family: Inter;
|
||||
font-size: 0.75rem;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
line-height: 1.25rem; /* 166.667% */
|
||||
}
|
||||
.title {
|
||||
color: var(--color-greyscale-700, #56565c);
|
||||
font-family: Inter;
|
||||
font-size: 0.75rem;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
line-height: 1.25rem; /* 166.667% */
|
||||
}
|
||||
|
||||
.subscription {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin-block-start: 0.15rem;
|
||||
.subscription {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin-block-start: 0.15rem;
|
||||
|
||||
.price {
|
||||
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
||||
font-family: Inter;
|
||||
font-size: 1.125rem;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
line-height: 1.25rem; /* 111.111% */
|
||||
}
|
||||
.price {
|
||||
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
||||
font-family: Inter;
|
||||
font-size: 1.125rem;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
line-height: 1.25rem; /* 111.111% */
|
||||
}
|
||||
|
||||
.period {
|
||||
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
||||
font-family: Inter;
|
||||
font-size: 0.75rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
}
|
||||
.period {
|
||||
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
||||
font-family: Inter;
|
||||
font-size: 0.75rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.125rem;
|
||||
margin-block-start: 0.75rem;
|
||||
ul {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.125rem;
|
||||
margin-block-start: 0.75rem;
|
||||
|
||||
li {
|
||||
color: var(--color-greyscale-500, #818186);
|
||||
font-family: Inter;
|
||||
font-size: 0.75rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.25rem; /* 166.667% */
|
||||
li {
|
||||
color: var(--color-greyscale-500, #818186);
|
||||
font-family: Inter;
|
||||
font-size: 0.75rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.25rem; /* 166.667% */
|
||||
|
||||
padding-inline-start: 1.5rem;
|
||||
padding-inline-start: 1.5rem;
|
||||
|
||||
position: relative;
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
&::before {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
|
||||
background-image: url('/images/animations/check-circle.svg');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
background-image: url('/images/animations/check-circle.svg');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.methods {
|
||||
margin-block-start: 1.25rem;
|
||||
.methods {
|
||||
margin-block-start: 1.25rem;
|
||||
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
overflow: hidden;
|
||||
margin-inline: -1rem;
|
||||
padding-inline: 1rem;
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
overflow: hidden;
|
||||
margin-inline: -1rem;
|
||||
padding-inline: 1rem;
|
||||
|
||||
li {
|
||||
flex-shrink: 0;
|
||||
li {
|
||||
flex-shrink: 0;
|
||||
|
||||
display: flex;
|
||||
width: 5.5rem;
|
||||
padding: 0.75rem 0.75rem 0.625rem 0.75rem;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
gap: 0.125rem;
|
||||
display: flex;
|
||||
width: 5.5rem;
|
||||
padding: 0.75rem 0.75rem 0.625rem 0.75rem;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
gap: 0.125rem;
|
||||
|
||||
border-radius: 0.75rem;
|
||||
border: 1px solid var(--greyscale-50, #ededf0);
|
||||
border-radius: 0.75rem;
|
||||
border: 1px solid var(--greyscale-50, #ededf0);
|
||||
|
||||
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
||||
font-family: Inter;
|
||||
font-size: 0.75rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.25rem; /* 166.667% */
|
||||
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
||||
font-family: Inter;
|
||||
font-size: 0.75rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.25rem; /* 166.667% */
|
||||
|
||||
&[data-active] {
|
||||
border-color: var(--appwrite-purple, #7c67fe);
|
||||
}
|
||||
}
|
||||
}
|
||||
&[data-active] {
|
||||
border-color: var(--appwrite-purple, #7c67fe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form {
|
||||
margin-block-start: 1.25rem;
|
||||
.form {
|
||||
margin-block-start: 1.25rem;
|
||||
|
||||
> p {
|
||||
color: var(--dark-neutrals-150, #373b4d);
|
||||
font-family: Inter;
|
||||
font-size: 0.75rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 150%; /* 1.125rem */
|
||||
}
|
||||
> p {
|
||||
color: var(--dark-neutrals-150, #373b4d);
|
||||
font-family: Inter;
|
||||
font-size: 0.75rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 150%; /* 1.125rem */
|
||||
}
|
||||
|
||||
.bordered {
|
||||
margin-block-start: 0.25rem;
|
||||
.bordered {
|
||||
margin-block-start: 0.25rem;
|
||||
|
||||
border-radius: 0.5rem;
|
||||
border: 1px solid #ededf0;
|
||||
background: var(--color-bw-white, #fff);
|
||||
border-radius: 0.5rem;
|
||||
border: 1px solid #ededf0;
|
||||
background: var(--color-bw-white, #fff);
|
||||
|
||||
> div:first-child {
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
padding: 0.65rem 0.75rem;
|
||||
border-bottom: 1px solid #ededf0;
|
||||
> div:first-child {
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
padding: 0.65rem 0.75rem;
|
||||
border-bottom: 1px solid #ededf0;
|
||||
|
||||
> :nth-child(2) {
|
||||
margin-inline-start: auto;
|
||||
}
|
||||
}
|
||||
> :nth-child(2) {
|
||||
margin-inline-start: auto;
|
||||
}
|
||||
}
|
||||
|
||||
> div:nth-child(2) {
|
||||
display: flex;
|
||||
> div:nth-child(2) {
|
||||
display: flex;
|
||||
|
||||
> p {
|
||||
padding: 0.65rem 0.75rem;
|
||||
}
|
||||
> p {
|
||||
padding: 0.65rem 0.75rem;
|
||||
}
|
||||
|
||||
> p:first-child {
|
||||
flex-grow: 3;
|
||||
}
|
||||
> p:first-child {
|
||||
flex-grow: 3;
|
||||
}
|
||||
|
||||
> p:last-child {
|
||||
flex-grow: 1;
|
||||
border-inline-start: 1px solid #ededf0;
|
||||
}
|
||||
}
|
||||
> p:last-child {
|
||||
flex-grow: 1;
|
||||
border-inline-start: 1px solid #ededf0;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
color: var(--light-neutrals-50, #c4c6d7);
|
||||
font-family: Inter;
|
||||
font-size: 0.75rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 150%; /* 1.125rem */
|
||||
}
|
||||
}
|
||||
}
|
||||
p {
|
||||
color: var(--light-neutrals-50, #c4c6d7);
|
||||
font-family: Inter;
|
||||
font-size: 0.75rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 150%; /* 1.125rem */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> button {
|
||||
display: flex;
|
||||
text-align: center;
|
||||
padding: 0.5rem 1rem;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
> button {
|
||||
display: flex;
|
||||
text-align: center;
|
||||
padding: 0.5rem 1rem;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
|
||||
border-radius: 0.5rem;
|
||||
background: var(--appwrite-purple, #7c67fe);
|
||||
box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.06);
|
||||
border-radius: 0.5rem;
|
||||
background: var(--appwrite-purple, #7c67fe);
|
||||
box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.06);
|
||||
|
||||
color: var(--color-bw-white, #fff);
|
||||
text-align: center;
|
||||
font-family: Inter;
|
||||
font-size: 0.875rem;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 1.375rem; /* 157.143% */
|
||||
letter-spacing: -0.01225rem;
|
||||
color: var(--color-bw-white, #fff);
|
||||
text-align: center;
|
||||
font-family: Inter;
|
||||
font-size: 0.875rem;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 1.375rem; /* 157.143% */
|
||||
letter-spacing: -0.01225rem;
|
||||
|
||||
margin-block-start: auto;
|
||||
margin-block-start: auto;
|
||||
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div data-theme-ignore class="inner-phone theme-light">
|
||||
<div data-theme-ignore class="inner-phone light">
|
||||
<div class="header">
|
||||
<p class="title">Your tasks</p>
|
||||
<span class="icon-menu" aria-label="menu" />
|
||||
|
||||
@@ -12,42 +12,42 @@ const executions = createResettable(0);
|
||||
const realtime = createResettable(0);
|
||||
|
||||
const execute = async () => {
|
||||
const phone = getElSelector('phone');
|
||||
const pd = getElSelector('pd');
|
||||
const phone = getElSelector('phone');
|
||||
const pd = getElSelector('pd');
|
||||
|
||||
const graphBox = getElSelector('graph-box');
|
||||
const graphBox = getElSelector('graph-box');
|
||||
|
||||
const boxesAndStates = [
|
||||
{ box: getElSelector('post-auth'), state: authentication.reset() },
|
||||
{ box: getElSelector('post-storage'), state: storage.reset() },
|
||||
{ box: getElSelector('post-bandwidth'), state: bandwidth.reset() },
|
||||
{ box: getElSelector('post-functions'), state: executions.reset() },
|
||||
{ box: getElSelector('post-databases'), state: databases.reset() },
|
||||
{ box: getElSelector('post-realtime'), state: realtime.reset() },
|
||||
{ box: getElSelector('post-requests'), state: requests.reset() }
|
||||
];
|
||||
const boxesAndStates = [
|
||||
{ box: getElSelector('post-auth'), state: authentication.reset() },
|
||||
{ box: getElSelector('post-storage'), state: storage.reset() },
|
||||
{ box: getElSelector('post-bandwidth'), state: bandwidth.reset() },
|
||||
{ box: getElSelector('post-functions'), state: executions.reset() },
|
||||
{ box: getElSelector('post-databases'), state: databases.reset() },
|
||||
{ box: getElSelector('post-realtime'), state: realtime.reset() },
|
||||
{ box: getElSelector('post-requests'), state: requests.reset() }
|
||||
];
|
||||
|
||||
await Promise.all([
|
||||
safeAnimate(pd, { opacity: 0, y: -16 }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(graphBox, { opacity: 0, visibility: 'hidden' }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(phone, { x: '-50%', width: '660px' }, { duration: 1, delay: 0.5 })?.finished
|
||||
]);
|
||||
await Promise.all([
|
||||
safeAnimate(pd, { opacity: 0, y: -16 }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(graphBox, { opacity: 0, visibility: 'hidden' }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(phone, { x: '-50%', width: '660px' }, { duration: 1, delay: 0.5 })?.finished
|
||||
]);
|
||||
|
||||
boxesAndStates.forEach(({ box, state }, i) => {
|
||||
safeAnimate(box, { opacity: 1, y: [1200, 0] }, { duration: 0.5, delay: i * 0.1 })?.finished;
|
||||
animate(state.set, { duration: 2, delay: (i + 1) * 0.25 });
|
||||
});
|
||||
boxesAndStates.forEach(({ box, state }, i) => {
|
||||
safeAnimate(box, { opacity: 1, y: [1200, 0] }, { duration: 0.5, delay: i * 0.1 })?.finished;
|
||||
animate(state.set, { duration: 2, delay: (i + 1) * 0.25 });
|
||||
});
|
||||
};
|
||||
|
||||
export const postController = {
|
||||
execute,
|
||||
state: {
|
||||
requests,
|
||||
databases,
|
||||
authentication,
|
||||
storage,
|
||||
bandwidth,
|
||||
executions,
|
||||
realtime
|
||||
}
|
||||
execute,
|
||||
state: {
|
||||
requests,
|
||||
databases,
|
||||
authentication,
|
||||
storage,
|
||||
bandwidth,
|
||||
executions,
|
||||
realtime
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,297 +1,300 @@
|
||||
<script lang="ts">
|
||||
import { toScale } from '$lib/utils/toScale';
|
||||
import { postController } from '.';
|
||||
import { elId } from '../Products.svelte';
|
||||
import { toScale } from '$lib/utils/toScale';
|
||||
import { postController } from '.';
|
||||
import { elId } from '../Products.svelte';
|
||||
|
||||
const {
|
||||
state: { authentication, bandwidth, databases, executions, requests, storage, realtime }
|
||||
} = postController;
|
||||
const {
|
||||
state: { authentication, bandwidth, databases, executions, requests, storage, realtime }
|
||||
} = postController;
|
||||
|
||||
const formatK = (num: number) => {
|
||||
if (num > 999) {
|
||||
return `${(num / 1000).toFixed(1)}K`;
|
||||
}
|
||||
return Math.floor(num);
|
||||
};
|
||||
const formatK = (num: number) => {
|
||||
if (num > 999) {
|
||||
return `${(num / 1000).toFixed(1)}K`;
|
||||
}
|
||||
return Math.floor(num);
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="gradient-box auth" id="post-auth-{$elId}">
|
||||
<div class="u-flex u-cross-center u-gap-8">
|
||||
<p class="icon-user-group" />
|
||||
<p class="f-eyebrow">Authentication</p>
|
||||
</div>
|
||||
<p class="f-display mbs-16">{formatK(toScale($authentication, [0, 1], [0, 4000]))}</p>
|
||||
<div class="u-flex u-cross-center justify-between mbs-4">
|
||||
<p class="f-sub">Users</p>
|
||||
<p class="f-idk">Sessions: 20K</p>
|
||||
</div>
|
||||
<div class="flex u-cross-center gap-2">
|
||||
<p class="icon-user-group" />
|
||||
<p class="f-eyebrow">Authentication</p>
|
||||
</div>
|
||||
<p class="f-display mbs-16">{formatK(toScale($authentication, [0, 1], [0, 4000]))}</p>
|
||||
<div class="flex u-cross-center justify-between mbs-4">
|
||||
<p class="f-sub">Users</p>
|
||||
<p class="f-idk">Sessions: 20K</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gradient-box storage" id="post-storage-{$elId}">
|
||||
<div class="u-flex u-cross-center u-gap-8">
|
||||
<p class="icon-folder" />
|
||||
<p class="f-eyebrow">Storage</p>
|
||||
</div>
|
||||
<p class="f-display mbs-16">
|
||||
{toScale($storage, [0, 1], [0, 8]).toFixed(1)} <span class="f-tiny-display">GB</span>
|
||||
</p>
|
||||
<div class="u-flex u-cross-center justify-between mbs-4">
|
||||
<p class="f-sub">Storage</p>
|
||||
<p class="f-idk">Buckets: 44</p>
|
||||
</div>
|
||||
<div class="flex u-cross-center gap-2">
|
||||
<p class="icon-folder" />
|
||||
<p class="f-eyebrow">Storage</p>
|
||||
</div>
|
||||
<p class="f-display mbs-16">
|
||||
{toScale($storage, [0, 1], [0, 8]).toFixed(1)} <span class="f-tiny-display">GB</span>
|
||||
</p>
|
||||
<div class="flex u-cross-center justify-between mbs-4">
|
||||
<p class="f-sub">Storage</p>
|
||||
<p class="f-idk">Buckets: 44</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gradient-box bandwidth" id="post-bandwidth-{$elId}">
|
||||
<p class="f-display">
|
||||
{toScale($bandwidth, [0, 1], [0, 1.2]).toFixed(2)} <span class="f-tiny-display">GB</span>
|
||||
</p>
|
||||
<p class="f-sub">Bandwidth</p>
|
||||
<img class="mbs-16" src="./images/animations/bandwidth-graph.svg" alt="" />
|
||||
<p class="f-display">
|
||||
{toScale($bandwidth, [0, 1], [0, 1.2]).toFixed(2)} <span class="f-tiny-display">GB</span>
|
||||
</p>
|
||||
<p class="f-sub">Bandwidth</p>
|
||||
<img class="mbs-16" src="./images/animations/bandwidth-graph.svg" alt="" />
|
||||
</div>
|
||||
|
||||
<div class="gradient-box functions" id="post-functions-{$elId}">
|
||||
<div class="u-flex u-cross-center u-gap-8">
|
||||
<p class="icon-lightning-bolt" />
|
||||
<p class="f-eyebrow">Functions</p>
|
||||
</div>
|
||||
<p class="f-display mbs-16">{toScale($executions, [0, 1], [0, 846]).toFixed(0)}</p>
|
||||
<div class="u-flex u-cross-center justify-between mbs-4">
|
||||
<p class="f-sub">Executions</p>
|
||||
</div>
|
||||
<div class="flex u-cross-center gap-2">
|
||||
<p class="icon-lightning-bolt" />
|
||||
<p class="f-eyebrow">Functions</p>
|
||||
</div>
|
||||
<p class="f-display mbs-16">{toScale($executions, [0, 1], [0, 846]).toFixed(0)}</p>
|
||||
<div class="flex u-cross-center justify-between mbs-4">
|
||||
<p class="f-sub">Executions</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gradient-box databases" id="post-databases-{$elId}">
|
||||
<div class="u-flex u-cross-center u-gap-8">
|
||||
<p class="icon-database" />
|
||||
<p class="f-eyebrow">Databases</p>
|
||||
</div>
|
||||
<p class="f-display mbs-16">{toScale($databases, [0, 1], [0, 8]).toFixed(0)}</p>
|
||||
<div class="u-flex u-cross-center justify-between mbs-4">
|
||||
<p class="f-sub">Databases</p>
|
||||
<p class="f-idk">Documents: 20</p>
|
||||
</div>
|
||||
<div class="flex u-cross-center gap-2">
|
||||
<p class="icon-database" />
|
||||
<p class="f-eyebrow">Databases</p>
|
||||
</div>
|
||||
<p class="f-display mbs-16">{toScale($databases, [0, 1], [0, 8]).toFixed(0)}</p>
|
||||
<div class="flex u-cross-center justify-between mbs-4">
|
||||
<p class="f-sub">Databases</p>
|
||||
<p class="f-idk">Documents: 20</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gradient-box requests" id="post-requests-{$elId}">
|
||||
<p class="f-display">{formatK(toScale($requests, [0, 1], [0, 6849]))}</p>
|
||||
<p class="f-sub">Requests</p>
|
||||
<img class="mbs-16" src="./images/animations/requests-graph.svg" alt="" />
|
||||
<p class="f-display">{formatK(toScale($requests, [0, 1], [0, 6849]))}</p>
|
||||
<p class="f-sub">Requests</p>
|
||||
<img class="mbs-16" src="./images/animations/requests-graph.svg" alt="" />
|
||||
</div>
|
||||
|
||||
<div class="gradient-box realtime" id="post-realtime-{$elId}">
|
||||
<p class="f-display">{formatK(toScale($realtime, [0, 1], [0, 100000]))}</p>
|
||||
<p class="f-sub">Realtime connections</p>
|
||||
<img class="mbs-16" src="./images/animations/realtime-graph.svg" alt="" />
|
||||
<p class="f-display">{formatK(toScale($realtime, [0, 1], [0, 100000]))}</p>
|
||||
<p class="f-sub">Realtime connections</p>
|
||||
<img class="mbs-16" src="./images/animations/realtime-graph.svg" alt="" />
|
||||
</div>
|
||||
|
||||
<div class="gradient-overlay u-flex u-flex-vertical">
|
||||
<h3>See your products grow</h3>
|
||||
<p>
|
||||
Keep track of your projects progress on the Appwrite Console and see them grow into products
|
||||
users love and use every day.
|
||||
</p>
|
||||
<div class="gradient-overlay flex u-flex-vertical">
|
||||
<h3>See your products grow</h3>
|
||||
<p>
|
||||
Keep track of your projects progress on the Appwrite Console and see them grow into products
|
||||
users love and use every day.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
@use '$scss/abstract/mixins/border-gradient' as gradients;
|
||||
|
||||
// Utilities
|
||||
.f-eyebrow {
|
||||
color: #adadb0;
|
||||
/* Eyebrow headings/level 3 */
|
||||
font-family: Inter;
|
||||
font-size: 0.75rem;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 150%; /* 1.125rem */
|
||||
letter-spacing: 0.09rem;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
// Utilities
|
||||
.f-eyebrow {
|
||||
color: #adadb0;
|
||||
/* Eyebrow headings/level 3 */
|
||||
font-family: Inter;
|
||||
font-size: 0.75rem;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 150%; /* 1.125rem */
|
||||
letter-spacing: 0.09rem;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.f-display {
|
||||
color: #ededf0;
|
||||
font-family: Aeonik Pro;
|
||||
font-size: 2rem;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 2.25rem; /* 112.5% */
|
||||
}
|
||||
.f-display {
|
||||
color: #ededf0;
|
||||
font-family: Aeonik Pro;
|
||||
font-size: 2rem;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 2.25rem; /* 112.5% */
|
||||
}
|
||||
|
||||
.f-tiny-display {
|
||||
color: var(--greyscale-50, #ededf0);
|
||||
text-align: center;
|
||||
font-family: Inter;
|
||||
font-size: 0.875rem;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 1rem; /* 114.286% */
|
||||
}
|
||||
.f-tiny-display {
|
||||
color: var(--greyscale-50, #ededf0);
|
||||
text-align: center;
|
||||
font-family: Inter;
|
||||
font-size: 0.875rem;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 1rem; /* 114.286% */
|
||||
}
|
||||
|
||||
.f-sub {
|
||||
color: #97979b;
|
||||
font-family: Inter;
|
||||
font-size: 0.875rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.125rem; /* 128.571% */
|
||||
}
|
||||
.f-sub {
|
||||
color: #97979b;
|
||||
font-family: Inter;
|
||||
font-size: 0.875rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.125rem; /* 128.571% */
|
||||
}
|
||||
|
||||
.f-idk {
|
||||
color: var(--primary, #e4e4e7);
|
||||
text-align: right;
|
||||
font-family: Inter;
|
||||
font-size: 0.875rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 150%; /* 1.3125rem */
|
||||
opacity: 40%;
|
||||
}
|
||||
.f-idk {
|
||||
color: var(--primary, #e4e4e7);
|
||||
text-align: right;
|
||||
font-family: Inter;
|
||||
font-size: 0.875rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 150%; /* 1.3125rem */
|
||||
opacity: 40%;
|
||||
}
|
||||
|
||||
.mbs-16 {
|
||||
margin-block-start: 1rem;
|
||||
}
|
||||
.mbs-16 {
|
||||
margin-block-start: 1rem;
|
||||
}
|
||||
|
||||
.mbs-4 {
|
||||
margin-block-start: 0.25rem;
|
||||
}
|
||||
.mbs-4 {
|
||||
margin-block-start: 0.25rem;
|
||||
}
|
||||
|
||||
.justify-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
.justify-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
// Components
|
||||
.gradient-box {
|
||||
@include gradients.border-gradient;
|
||||
--m-border-gradient-before: linear-gradient(
|
||||
180deg,
|
||||
rgba(255, 255, 255, 0.12) 0%,
|
||||
rgba(255, 255, 255, 0) 125.11%
|
||||
);
|
||||
--m-border-radius: 1rem;
|
||||
// Components
|
||||
.gradient-box {
|
||||
@include gradients.border-gradient;
|
||||
--m-border-gradient-before: linear-gradient(
|
||||
180deg,
|
||||
rgba(255, 255, 255, 0.12) 0%,
|
||||
rgba(255, 255, 255, 0) 125.11%
|
||||
);
|
||||
--m-border-radius: 1rem;
|
||||
|
||||
position: absolute;
|
||||
background: var(--card, rgba(35, 35, 37, 0.9));
|
||||
box-shadow: 0px 0px 0px 0px rgba(0, 0, 0, 0.06), -2px 4px 9px 0px rgba(0, 0, 0, 0.06),
|
||||
-8px 15px 17px 0px rgba(0, 0, 0, 0.05), -19px 34px 23px 0px rgba(0, 0, 0, 0.03),
|
||||
-33px 60px 27px 0px rgba(0, 0, 0, 0.01), -52px 94px 30px 0px rgba(0, 0, 0, 0);
|
||||
backdrop-filter: blur(8px);
|
||||
position: absolute;
|
||||
background: var(--card, rgba(35, 35, 37, 0.9));
|
||||
box-shadow:
|
||||
0px 0px 0px 0px rgba(0, 0, 0, 0.06),
|
||||
-2px 4px 9px 0px rgba(0, 0, 0, 0.06),
|
||||
-8px 15px 17px 0px rgba(0, 0, 0, 0.05),
|
||||
-19px 34px 23px 0px rgba(0, 0, 0, 0.03),
|
||||
-33px 60px 27px 0px rgba(0, 0, 0, 0.01),
|
||||
-52px 94px 30px 0px rgba(0, 0, 0, 0);
|
||||
backdrop-filter: blur(8px);
|
||||
|
||||
padding: 1.5rem;
|
||||
padding: 1.5rem;
|
||||
|
||||
z-index: 9999;
|
||||
z-index: 9999;
|
||||
|
||||
min-width: 20rem;
|
||||
}
|
||||
min-width: 20rem;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.gradient-overlay {
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
bottom: -7.5rem;
|
||||
width: 100%;
|
||||
height: 30rem;
|
||||
.gradient-overlay {
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
bottom: -7.5rem;
|
||||
width: 100%;
|
||||
height: 30rem;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 1.25rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 1.25rem;
|
||||
|
||||
padding-block-start: 15rem;
|
||||
padding-block-start: 15rem;
|
||||
|
||||
opacity: 0;
|
||||
animation: fadeIn 0.75s ease-in-out 1.5s forwards;
|
||||
opacity: 0;
|
||||
animation: fadeIn 0.75s ease-in-out 1.5s forwards;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
inset: 0;
|
||||
position: absolute;
|
||||
//background: #19191d; // old bg
|
||||
//filter: blur(125px); // break Safari
|
||||
background: #19191dcc;
|
||||
filter: blur(67px);
|
||||
&::before {
|
||||
content: '';
|
||||
inset: 0;
|
||||
position: absolute;
|
||||
//background: #19191d; // old bg
|
||||
//filter: blur(125px); // break Safari
|
||||
background: #19191dcc;
|
||||
filter: blur(67px);
|
||||
}
|
||||
|
||||
}
|
||||
h3 {
|
||||
position: relative;
|
||||
color: var(--primary, #e4e4e7);
|
||||
text-align: center;
|
||||
|
||||
h3 {
|
||||
position: relative;
|
||||
color: var(--primary, #e4e4e7);
|
||||
text-align: center;
|
||||
/* Desktop/Display */
|
||||
font-family: Aeonik Pro;
|
||||
font-size: 4rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 4.25rem; /* 106.25% */
|
||||
letter-spacing: -0.04rem;
|
||||
}
|
||||
|
||||
/* Desktop/Display */
|
||||
font-family: Aeonik Pro;
|
||||
font-size: 4rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 4.25rem; /* 106.25% */
|
||||
letter-spacing: -0.04rem;
|
||||
}
|
||||
p {
|
||||
position: relative;
|
||||
|
||||
p {
|
||||
position: relative;
|
||||
color: var(--secondary, #adadb0);
|
||||
text-align: center;
|
||||
|
||||
color: var(--secondary, #adadb0);
|
||||
text-align: center;
|
||||
/* Desktop/Description */
|
||||
font-family: Inter;
|
||||
font-size: 1.25rem;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 1.75rem; /* 140% */
|
||||
letter-spacing: -0.0175rem;
|
||||
max-width: 40rem;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
/* Desktop/Description */
|
||||
font-family: Inter;
|
||||
font-size: 1.25rem;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 1.75rem; /* 140% */
|
||||
letter-spacing: -0.0175rem;
|
||||
max-width: 40rem;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
// Specifics
|
||||
.auth {
|
||||
opacity: 0;
|
||||
left: 4rem;
|
||||
top: -11rem;
|
||||
}
|
||||
|
||||
// Specifics
|
||||
.auth {
|
||||
opacity: 0;
|
||||
left: 4rem;
|
||||
top: -11rem;
|
||||
}
|
||||
.storage {
|
||||
opacity: 0;
|
||||
left: -10rem;
|
||||
top: -2rem;
|
||||
}
|
||||
|
||||
.storage {
|
||||
opacity: 0;
|
||||
left: -10rem;
|
||||
top: -2rem;
|
||||
}
|
||||
.bandwidth {
|
||||
opacity: 0;
|
||||
left: -4rem;
|
||||
top: 11rem;
|
||||
}
|
||||
|
||||
.bandwidth {
|
||||
opacity: 0;
|
||||
left: -4rem;
|
||||
top: 11rem;
|
||||
}
|
||||
.functions {
|
||||
opacity: 0;
|
||||
left: -6rem;
|
||||
top: 35rem;
|
||||
}
|
||||
|
||||
.functions {
|
||||
opacity: 0;
|
||||
left: -6rem;
|
||||
top: 35rem;
|
||||
}
|
||||
.databases {
|
||||
opacity: 0;
|
||||
top: -13rem;
|
||||
right: 10rem;
|
||||
}
|
||||
|
||||
.databases {
|
||||
opacity: 0;
|
||||
top: -13rem;
|
||||
right: 10rem;
|
||||
}
|
||||
.requests {
|
||||
opacity: 0;
|
||||
top: 17rem;
|
||||
right: -18rem;
|
||||
}
|
||||
|
||||
.requests {
|
||||
opacity: 0;
|
||||
top: 17rem;
|
||||
right: -18rem;
|
||||
}
|
||||
|
||||
.realtime {
|
||||
opacity: 0;
|
||||
top: -1rem;
|
||||
right: -7rem;
|
||||
}
|
||||
.realtime {
|
||||
opacity: 0;
|
||||
top: -1rem;
|
||||
right: -7rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,39 +1,39 @@
|
||||
<script lang="ts">
|
||||
import { slide } from 'svelte/transition';
|
||||
import { storageController } from '.';
|
||||
import { flip } from '$lib/utils/flip';
|
||||
import { slide } from 'svelte/transition';
|
||||
import { storageController } from '.';
|
||||
import { flip } from '$lib/utils/flip';
|
||||
|
||||
const { state } = storageController;
|
||||
const { state } = storageController;
|
||||
</script>
|
||||
|
||||
<div class="pseudo-table">
|
||||
<div class="header">
|
||||
<span class="web-eyebrow">Filename</span>
|
||||
<span class="web-eyebrow">Type</span>
|
||||
<span class="web-eyebrow">Size</span>
|
||||
</div>
|
||||
{#each $state.files as file (file.src)}
|
||||
<div class="row" in:slide={{ duration: 150 }} animate:flip={{ duration: 150 }}>
|
||||
<div class="img-wrapper">
|
||||
<img src={file.src} alt="" />
|
||||
<span>{file.filename}</span>
|
||||
</div>
|
||||
<span class="truncated">{file.type}</span>
|
||||
<span class="truncated">{file.size}</span>
|
||||
</div>
|
||||
{/each}
|
||||
<div class="header">
|
||||
<span class="web-eyebrow">Filename</span>
|
||||
<span class="web-eyebrow">Type</span>
|
||||
<span class="web-eyebrow">Size</span>
|
||||
</div>
|
||||
{#each $state.files as file (file.src)}
|
||||
<div class="row" in:slide={{ duration: 150 }} animate:flip={{ duration: 150 }}>
|
||||
<div class="img-wrapper">
|
||||
<img src={file.src} alt="" />
|
||||
<span>{file.filename}</span>
|
||||
</div>
|
||||
<span class="truncated">{file.type}</span>
|
||||
<span class="truncated">{file.size}</span>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.header,
|
||||
.row {
|
||||
grid-template-columns: 7rem 1fr 1fr !important;
|
||||
gap: 1.5rem 3rem;
|
||||
}
|
||||
.header,
|
||||
.row {
|
||||
grid-template-columns: 7rem 1fr 1fr !important;
|
||||
gap: 1.5rem 3rem;
|
||||
}
|
||||
|
||||
.img-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
.img-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import Code from '$lib/animations/CodeWindow/Code.svelte';
|
||||
import Code from '$lib/animations/CodeWindow/Code.svelte';
|
||||
|
||||
let content = `
|
||||
let content = `
|
||||
const result = storage.createFile(
|
||||
'my-bucket',
|
||||
ID.unique(),
|
||||
|
||||
@@ -7,130 +7,131 @@ import { createResettable } from '$lib/utils/resettable';
|
||||
import { getElSelector } from '../Products.svelte';
|
||||
|
||||
type File = {
|
||||
src: string;
|
||||
filename: string;
|
||||
type: string;
|
||||
size: string;
|
||||
src: string;
|
||||
filename: string;
|
||||
type: string;
|
||||
size: string;
|
||||
};
|
||||
|
||||
type State = {
|
||||
files: File[];
|
||||
files: File[];
|
||||
};
|
||||
|
||||
const state = createResettable<State>({
|
||||
files: []
|
||||
files: []
|
||||
});
|
||||
|
||||
const execute = async () => {
|
||||
const phone = getElSelector('phone');
|
||||
const box = getElSelector('box');
|
||||
const code = getElSelector('code');
|
||||
const overlay = getElSelector('overlay');
|
||||
const drawer = getElSelector('drawer');
|
||||
const upload = getElSelector('upload');
|
||||
const uploadBtn = getElSelector('upload-btn');
|
||||
const uploadImg = getElSelector('upload-img');
|
||||
const uploadLoading = getElSelector('upload-loading');
|
||||
const uploadText = getElSelector('upload-text');
|
||||
const phone = getElSelector('phone');
|
||||
const box = getElSelector('box');
|
||||
const code = getElSelector('code');
|
||||
const overlay = getElSelector('overlay');
|
||||
const drawer = getElSelector('drawer');
|
||||
const upload = getElSelector('upload');
|
||||
const uploadBtn = getElSelector('upload-btn');
|
||||
const uploadImg = getElSelector('upload-img');
|
||||
const uploadLoading = getElSelector('upload-loading');
|
||||
const uploadText = getElSelector('upload-text');
|
||||
|
||||
const { update } = state.reset();
|
||||
const { update } = state.reset();
|
||||
|
||||
await Promise.all([
|
||||
safeAnimate(phone, { x: 0, y: 0 }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(box, { opacity: 0 }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(code, { opacity: 0 }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(uploadLoading, { opacity: 0 }, { duration: 0 })?.finished
|
||||
]);
|
||||
await Promise.all([
|
||||
safeAnimate(phone, { x: 0, y: 0 }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(box, { opacity: 0 }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(code, { opacity: 0 }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(uploadLoading, { opacity: 0 }, { duration: 0 })?.finished
|
||||
]);
|
||||
|
||||
await safeAnimate(code, { zIndex: 20 }, { duration: 0 })?.finished;
|
||||
await safeAnimate(code, { zIndex: 20 }, { duration: 0 })?.finished;
|
||||
|
||||
update((p) => ({
|
||||
...p,
|
||||
files: [
|
||||
...p.files,
|
||||
{
|
||||
src: '/images/animations/storage-1.png',
|
||||
filename: 'Profile.png',
|
||||
type: 'image/png',
|
||||
size: '362.6 KB'
|
||||
}
|
||||
]
|
||||
}));
|
||||
update((p) => ({
|
||||
...p,
|
||||
files: [
|
||||
...p.files,
|
||||
{
|
||||
src: '/images/animations/storage-1.png',
|
||||
filename: 'Profile.png',
|
||||
type: 'image/png',
|
||||
size: '362.6 KB'
|
||||
}
|
||||
]
|
||||
}));
|
||||
|
||||
await sleep(250);
|
||||
await sleep(250);
|
||||
|
||||
await Promise.all([
|
||||
safeAnimate(overlay, { opacity: 1 }, { duration: 0.25 })?.finished,
|
||||
safeAnimate(drawer, { y: [128, 0], opacity: 1 }, { duration: 0.5 })?.finished
|
||||
]);
|
||||
await Promise.all([
|
||||
safeAnimate(overlay, { opacity: 1 }, { duration: 0.25 })?.finished,
|
||||
safeAnimate(drawer, { y: [128, 0], opacity: 1 }, { duration: 0.5 })?.finished
|
||||
]);
|
||||
|
||||
await sleep(250);
|
||||
await sleep(250);
|
||||
|
||||
await safeAnimate(uploadBtn, { scale: [1, 0.9, 1] }, { duration: 0.25 })?.finished;
|
||||
await safeAnimate(uploadBtn, { scale: [1, 0.9, 1] }, { duration: 0.25 })?.finished;
|
||||
|
||||
await safeAnimate(code, { x: 300, y: 32 }, { duration: 0 })?.finished;
|
||||
await safeAnimate(code, { x: 300, y: 32 }, { duration: 0 })?.finished;
|
||||
|
||||
await Promise.all([
|
||||
safeAnimate(code, { y: [32 - 16, 32], opacity: 1 }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(upload, { y: [-16, 0], opacity: 1 }, { duration: 0.5 })?.finished
|
||||
]);
|
||||
await Promise.all([
|
||||
safeAnimate(code, { y: [32 - 16, 32], opacity: 1 }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(upload, { y: [-16, 0], opacity: 1 }, { duration: 0.5 })?.finished
|
||||
]);
|
||||
|
||||
await sleep(250);
|
||||
await sleep(250);
|
||||
|
||||
await safeAnimate(box, { x: 300, y: 300 }, { duration: 0 })?.finished;
|
||||
await safeAnimate(box, { x: 300, y: 300 }, { duration: 0 })?.finished;
|
||||
|
||||
await Promise.all([
|
||||
safeAnimate(uploadImg, { x: [64, 48], y: [80, 64], opacity: 1 }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(box, { y: [300 - 16, 300], opacity: 1 }, { duration: 1 })?.finished
|
||||
]);
|
||||
await Promise.all([
|
||||
safeAnimate(uploadImg, { x: [64, 48], y: [80, 64], opacity: 1 }, { duration: 0.5 })
|
||||
?.finished,
|
||||
safeAnimate(box, { y: [300 - 16, 300], opacity: 1 }, { duration: 1 })?.finished
|
||||
]);
|
||||
|
||||
await sleep(250);
|
||||
await sleep(250);
|
||||
|
||||
await Promise.all([
|
||||
safeAnimate(uploadText, { opacity: 0 }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(uploadLoading, { opacity: 1 }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(uploadImg, { opacity: 0, y: 64 + 8 }, { duration: 0.5 })?.finished
|
||||
]);
|
||||
await sleep(250);
|
||||
await Promise.all([
|
||||
safeAnimate(uploadText, { opacity: 0 }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(uploadLoading, { opacity: 1 }, { duration: 0.5 })?.finished,
|
||||
safeAnimate(uploadImg, { opacity: 0, y: 64 + 8 }, { duration: 0.5 })?.finished
|
||||
]);
|
||||
await sleep(250);
|
||||
|
||||
await safeAnimate(upload, { opacity: 0, y: 48 }, { duration: 0.5 })?.finished;
|
||||
await safeAnimate(upload, { opacity: 0, y: 48 }, { duration: 0.5 })?.finished;
|
||||
|
||||
update((p) => ({
|
||||
...p,
|
||||
files: [
|
||||
...p.files,
|
||||
{
|
||||
src: '/images/animations/storage-2.png',
|
||||
filename: 'Vector.svg',
|
||||
type: 'vector/svg',
|
||||
size: '1.5 KB'
|
||||
}
|
||||
]
|
||||
}));
|
||||
update((p) => ({
|
||||
...p,
|
||||
files: [
|
||||
...p.files,
|
||||
{
|
||||
src: '/images/animations/storage-2.png',
|
||||
filename: 'Vector.svg',
|
||||
type: 'vector/svg',
|
||||
size: '1.5 KB'
|
||||
}
|
||||
]
|
||||
}));
|
||||
|
||||
await sleep(250);
|
||||
await sleep(250);
|
||||
|
||||
update((p) => ({
|
||||
...p,
|
||||
files: [
|
||||
...p.files,
|
||||
{
|
||||
src: '/images/animations/storage-3.png',
|
||||
filename: 'img2.webp',
|
||||
type: 'image/webp',
|
||||
size: '3.2 MB'
|
||||
}
|
||||
]
|
||||
}));
|
||||
update((p) => ({
|
||||
...p,
|
||||
files: [
|
||||
...p.files,
|
||||
{
|
||||
src: '/images/animations/storage-3.png',
|
||||
filename: 'img2.webp',
|
||||
type: 'image/webp',
|
||||
size: '3.2 MB'
|
||||
}
|
||||
]
|
||||
}));
|
||||
};
|
||||
|
||||
export const storageController = {
|
||||
execute,
|
||||
state
|
||||
execute,
|
||||
state
|
||||
};
|
||||
|
||||
export const Storage = {
|
||||
Phone,
|
||||
Box,
|
||||
Code
|
||||
Phone,
|
||||
Box,
|
||||
Code
|
||||
};
|
||||
|
||||
@@ -1,284 +1,284 @@
|
||||
<script lang="ts">
|
||||
import { fly } from 'svelte/transition';
|
||||
import { storageController } from '.';
|
||||
import { elId } from '../Products.svelte';
|
||||
import TaskCheckbox from '../TaskCheckbox.svelte';
|
||||
import { databasesController } from '../databases';
|
||||
import { fly } from 'svelte/transition';
|
||||
import { storageController } from '.';
|
||||
import { elId } from '../Products.svelte';
|
||||
import TaskCheckbox from '../TaskCheckbox.svelte';
|
||||
import { databasesController } from '../databases';
|
||||
|
||||
const { state: dbState } = databasesController;
|
||||
const fixedTasks = $dbState.tasks;
|
||||
const { state: dbState } = databasesController;
|
||||
const fixedTasks = $dbState.tasks;
|
||||
|
||||
const { state } = storageController;
|
||||
const { state } = storageController;
|
||||
</script>
|
||||
|
||||
<div data-theme-ignore class="inner-phone theme-light">
|
||||
<div class="header">
|
||||
<p class="title">Your tasks</p>
|
||||
<span class="icon-menu" aria-label="menu" />
|
||||
</div>
|
||||
<div data-theme-ignore class="inner-phone light">
|
||||
<div class="header">
|
||||
<p class="title">Your tasks</p>
|
||||
<span class="icon-menu" aria-label="menu" />
|
||||
</div>
|
||||
|
||||
<div class="date">Today</div>
|
||||
<div class="tasks">
|
||||
{#each fixedTasks as task (task.id)}
|
||||
<div class="task" data-checked={task.checked ? '' : undefined} in:fly={{ x: -16 }}>
|
||||
<TaskCheckbox bind:checked={task.checked} />
|
||||
<span class="title">{task.title}</span>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
<div class="date">Today</div>
|
||||
<div class="tasks">
|
||||
{#each fixedTasks as task (task.id)}
|
||||
<div class="task" data-checked={task.checked ? '' : undefined} in:fly={{ x: -16 }}>
|
||||
<TaskCheckbox bind:checked={task.checked} />
|
||||
<span class="title">{task.title}</span>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<button class="add-btn">
|
||||
<span class="web-icon-plus" />
|
||||
</button>
|
||||
<button class="add-btn">
|
||||
<span class="web-icon-plus" />
|
||||
</button>
|
||||
|
||||
<div class="overlay" id="overlay-{$elId}">
|
||||
<div class="drawer" id="drawer-{$elId}">
|
||||
<p class="title">Edit images for website</p>
|
||||
<p class="subtitle">Edit the attached images to use in the website</p>
|
||||
<div class="overlay" id="overlay-{$elId}">
|
||||
<div class="drawer" id="drawer-{$elId}">
|
||||
<p class="title">Edit images for website</p>
|
||||
<p class="subtitle">Edit the attached images to use in the website</p>
|
||||
|
||||
<div class="upload" id="upload-btn-{$elId}">Upload media...</div>
|
||||
<div class="images">
|
||||
{#each $state.files.slice(1) as file}
|
||||
<img src={file.src} alt="" transition:fly={{ x: 16 }} />
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="upload" id="upload-btn-{$elId}">Upload media...</div>
|
||||
<div class="images">
|
||||
{#each $state.files.slice(1) as file}
|
||||
<img src={file.src} alt="" transition:fly={{ x: 16 }} />
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="upload-media" id="upload-{$elId}">
|
||||
<p class="title">Upload media</p>
|
||||
<div class="drop-zone">
|
||||
<span id="upload-text-{$elId}"> Drop media here </span>
|
||||
<div class="loading-overlay" id="upload-loading-{$elId}">
|
||||
<div class="loader" />
|
||||
</div>
|
||||
</div>
|
||||
<img id="upload-img-{$elId}" src="/images/animations/storage-2.png" alt="" />
|
||||
<p class="title">Upload media</p>
|
||||
<div class="drop-zone">
|
||||
<span id="upload-text-{$elId}"> Drop media here </span>
|
||||
<div class="loading-overlay" id="upload-loading-{$elId}">
|
||||
<div class="loader" />
|
||||
</div>
|
||||
</div>
|
||||
<img id="upload-img-{$elId}" src="/images/animations/storage-2.png" alt="" />
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.inner-phone {
|
||||
padding-block: 3rem;
|
||||
padding-inline: 1rem;
|
||||
.inner-phone {
|
||||
padding-block: 3rem;
|
||||
padding-inline: 1rem;
|
||||
|
||||
color: rgba(67, 67, 71, 1);
|
||||
text-align: left;
|
||||
color: rgba(67, 67, 71, 1);
|
||||
text-align: left;
|
||||
|
||||
position: relative;
|
||||
height: 100%;
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
overflow: visible;
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.title {
|
||||
color: var(--color-greyscale-800, #2d2d31);
|
||||
font-family: Inter;
|
||||
font-size: 1rem;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 1.375rem; /* 137.5% */
|
||||
letter-spacing: -0.014rem;
|
||||
}
|
||||
.title {
|
||||
color: var(--color-greyscale-800, #2d2d31);
|
||||
font-family: Inter;
|
||||
font-size: 1rem;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 1.375rem; /* 137.5% */
|
||||
letter-spacing: -0.014rem;
|
||||
}
|
||||
|
||||
[class*='icon-'] {
|
||||
font-size: 1.25rem;
|
||||
color: hsl(var(--web-color-greyscale-500));
|
||||
}
|
||||
}
|
||||
[class*='icon-'] {
|
||||
font-size: 1.25rem;
|
||||
color: hsl(var(--web-color-greyscale-500));
|
||||
}
|
||||
}
|
||||
|
||||
.date {
|
||||
margin-block-start: 3rem;
|
||||
.date {
|
||||
margin-block-start: 3rem;
|
||||
|
||||
color: hsl(var(--web-color-greyscale-600));
|
||||
font-family: Inter;
|
||||
font-size: 0.75rem;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 1.25rem; /* 166.667% */
|
||||
}
|
||||
color: hsl(var(--web-color-greyscale-600));
|
||||
font-family: Inter;
|
||||
font-size: 0.75rem;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 1.25rem; /* 166.667% */
|
||||
}
|
||||
|
||||
.tasks {
|
||||
margin-block-start: 0.5rem;
|
||||
.tasks {
|
||||
margin-block-start: 0.5rem;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
|
||||
.task {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
.task {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
|
||||
border-radius: 0.5rem;
|
||||
border: 1px solid hsl(var(--web-color-greyscale-50));
|
||||
background: hsl(var(--web-color-white));
|
||||
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
||||
border-radius: 0.5rem;
|
||||
border: 1px solid hsl(var(--web-color-greyscale-50));
|
||||
background: hsl(var(--web-color-white));
|
||||
color: var(--greyscale-700, var(--color-greyscale-700, #56565c));
|
||||
|
||||
padding-block: 0.55rem;
|
||||
padding-inline: 0.88rem;
|
||||
padding-block: 0.55rem;
|
||||
padding-inline: 0.88rem;
|
||||
|
||||
/* Responsive/SubBody-400 */
|
||||
font-family: Inter;
|
||||
font-size: 0.875rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.375rem; /* 157.143% */
|
||||
letter-spacing: -0.00394rem;
|
||||
/* Responsive/SubBody-400 */
|
||||
font-family: Inter;
|
||||
font-size: 0.875rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.375rem; /* 157.143% */
|
||||
letter-spacing: -0.00394rem;
|
||||
|
||||
transition: opacity 200ms ease;
|
||||
transition: opacity 200ms ease;
|
||||
|
||||
&[data-checked] {
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
&[data-checked] {
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.add-btn {
|
||||
position: absolute;
|
||||
right: 1rem;
|
||||
bottom: 2.5rem;
|
||||
.add-btn {
|
||||
position: absolute;
|
||||
right: 1rem;
|
||||
bottom: 2.5rem;
|
||||
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.12);
|
||||
background-color: rgba(124, 103, 254, 1);
|
||||
color: rgba(237, 237, 240, 1);
|
||||
font-size: 1.5rem;
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.12);
|
||||
background-color: rgba(124, 103, 254, 1);
|
||||
color: rgba(237, 237, 240, 1);
|
||||
font-size: 1.5rem;
|
||||
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border-radius: 100%;
|
||||
}
|
||||
}
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border-radius: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.overlay {
|
||||
opacity: 0;
|
||||
.overlay {
|
||||
opacity: 0;
|
||||
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
overflow: hidden;
|
||||
|
||||
background: rgba(0, 0, 0, 0.32);
|
||||
border-radius: 2rem;
|
||||
background: rgba(0, 0, 0, 0.32);
|
||||
border-radius: 2rem;
|
||||
|
||||
.drawer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
height: 60%;
|
||||
opacity: 0;
|
||||
.drawer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
height: 60%;
|
||||
opacity: 0;
|
||||
|
||||
background-color: white;
|
||||
border-radius: 0.88463rem 0.88463rem 2rem 2rem;
|
||||
background-color: white;
|
||||
border-radius: 0.88463rem 0.88463rem 2rem 2rem;
|
||||
|
||||
padding: 1rem;
|
||||
padding: 1rem;
|
||||
|
||||
.title {
|
||||
color: #434347;
|
||||
font-family: Inter;
|
||||
font-size: 0.88463rem;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 1.21638rem; /* 137.5% */
|
||||
letter-spacing: -0.01238rem;
|
||||
}
|
||||
.title {
|
||||
color: #434347;
|
||||
font-family: Inter;
|
||||
font-size: 0.88463rem;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 1.21638rem; /* 137.5% */
|
||||
letter-spacing: -0.01238rem;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
color: var(--greyscale-500, var(--color-greyscale-500, #818186));
|
||||
font-family: Inter;
|
||||
font-size: 0.77406rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.10575rem; /* 142.857% */
|
||||
letter-spacing: -0.01081rem;
|
||||
.subtitle {
|
||||
color: var(--greyscale-500, var(--color-greyscale-500, #818186));
|
||||
font-family: Inter;
|
||||
font-size: 0.77406rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.10575rem; /* 142.857% */
|
||||
letter-spacing: -0.01081rem;
|
||||
|
||||
margin-block-start: 0.2rem;
|
||||
}
|
||||
margin-block-start: 0.2rem;
|
||||
}
|
||||
|
||||
.upload {
|
||||
display: flex;
|
||||
padding: 0.44231rem 0.66344rem;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
align-self: stretch;
|
||||
.upload {
|
||||
display: flex;
|
||||
padding: 0.44231rem 0.66344rem;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
align-self: stretch;
|
||||
|
||||
border-radius: 0.66344rem;
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 0.66344rem;
|
||||
border: 1px dashed #d9d9d9;
|
||||
|
||||
color: var(--greyscale-500, var(--color-greyscale-500, #818186));
|
||||
font-family: Inter;
|
||||
font-size: 0.77406rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.10575rem; /* 142.857% */
|
||||
letter-spacing: -0.01081rem;
|
||||
color: var(--greyscale-500, var(--color-greyscale-500, #818186));
|
||||
font-family: Inter;
|
||||
font-size: 0.77406rem;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.10575rem; /* 142.857% */
|
||||
letter-spacing: -0.01081rem;
|
||||
|
||||
margin-block-start: 2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
margin-block-start: 2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.upload-media {
|
||||
position: absolute;
|
||||
right: calc(0% - 24px);
|
||||
bottom: 8rem;
|
||||
background-color: white;
|
||||
box-shadow: 0px 4px 24px 0px rgba(0, 0, 0, 0.05);
|
||||
border-radius: 1rem;
|
||||
padding: 0.75rem;
|
||||
.upload-media {
|
||||
position: absolute;
|
||||
right: calc(0% - 24px);
|
||||
bottom: 8rem;
|
||||
background-color: white;
|
||||
box-shadow: 0px 4px 24px 0px rgba(0, 0, 0, 0.05);
|
||||
border-radius: 1rem;
|
||||
padding: 0.75rem;
|
||||
|
||||
opacity: 0;
|
||||
opacity: 0;
|
||||
|
||||
.title {
|
||||
color: var(--color-greyscale-800, #2d2d31);
|
||||
font-family: Inter;
|
||||
font-size: 0.85rem;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 1.375rem; /* 137.5% */
|
||||
letter-spacing: -0.014rem;
|
||||
}
|
||||
.title {
|
||||
color: var(--color-greyscale-800, #2d2d31);
|
||||
font-family: Inter;
|
||||
font-size: 0.85rem;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 1.375rem; /* 137.5% */
|
||||
letter-spacing: -0.014rem;
|
||||
}
|
||||
|
||||
.drop-zone {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border: 0.885px dashed #d9d9d9;
|
||||
border-radius: 0.5rem;
|
||||
.drop-zone {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border: 0.885px dashed #d9d9d9;
|
||||
border-radius: 0.5rem;
|
||||
|
||||
color: var(--greyscale-500, var(--color-greyscale-500, #818186));
|
||||
padding: 2rem 1.25rem;
|
||||
margin-block-start: 0.5rem;
|
||||
font-size: 0.65rem;
|
||||
font-family: Inter;
|
||||
color: var(--greyscale-500, var(--color-greyscale-500, #818186));
|
||||
padding: 2rem 1.25rem;
|
||||
margin-block-start: 0.5rem;
|
||||
font-size: 0.65rem;
|
||||
font-family: Inter;
|
||||
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
.loading-overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
opacity: 0;
|
||||
z-index: 100;
|
||||
.loading-overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
opacity: 0;
|
||||
z-index: 100;
|
||||
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
}
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
img {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.images {
|
||||
display: flex;
|
||||
margin-block-start: 0.5rem;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
.images {
|
||||
display: flex;
|
||||
margin-block-start: 0.5rem;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -25,34 +25,21 @@
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="scroll-indicator"
|
||||
class="scroll-indicator relative h-full w-px shrink-0 rounded-full"
|
||||
use:rect={elRect}
|
||||
style:--y={`${y}px`}
|
||||
style:--percentage={`${easedPercentage * 100}%`}
|
||||
>
|
||||
<div class="web-dot" />
|
||||
<div class="0)] absolute -top-[8px] left-1/2 translate-[-50%_var(--y," />
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.scroll-indicator {
|
||||
position: relative;
|
||||
|
||||
width: 1px;
|
||||
flex-shrink: 0;
|
||||
height: 100%;
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
hsl(var(--web-color-accent)) 0%,
|
||||
hsl(var(--web-color-greyscale-700)) var(--percentage),
|
||||
hsl(var(--web-color-greyscale-700)) 100%
|
||||
);
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
.web-dot {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
translate: -50% var(--y, 0);
|
||||
top: -8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user