Merge branch 'feat-pink-v2' of https://github.com/appwrite/console into feat-pink-v2

This commit is contained in:
Torsten Dittmann
2025-02-03 22:49:06 +01:00
11 changed files with 169 additions and 82 deletions
+2 -2
View File
@@ -21,9 +21,9 @@
"dependencies": {
"@appwrite.io/console": "https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@9193",
"@appwrite.io/pink-icons": "0.25.0",
"@appwrite.io/pink-icons-svelte": "https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@95d82961",
"@appwrite.io/pink-icons-svelte": "https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@28ac795",
"@appwrite.io/pink-legacy": "^1.0.0",
"@appwrite.io/pink-svelte": "https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@95d82961",
"@appwrite.io/pink-svelte": "https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@28ac795",
"@popperjs/core": "^2.11.8",
"@sentry/sveltekit": "^8.38.0",
"@stripe/stripe-js": "^3.5.0",
+14 -14
View File
@@ -15,14 +15,14 @@ importers:
specifier: 0.25.0
version: 0.25.0
'@appwrite.io/pink-icons-svelte':
specifier: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@95d82961
version: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@95d82961(svelte@4.2.19)
specifier: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@28ac795
version: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@28ac795(svelte@4.2.19)
'@appwrite.io/pink-legacy':
specifier: ^1.0.0
version: 1.0.0
'@appwrite.io/pink-svelte':
specifier: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@95d82961
version: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@95d82961(react-dom@18.3.1(react@18.3.1))(svelte@4.2.19)
specifier: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@28ac795
version: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@28ac795(react-dom@18.3.1(react@18.3.1))(svelte@4.2.19)
'@popperjs/core':
specifier: ^2.11.8
version: 2.11.8
@@ -218,14 +218,14 @@ packages:
resolution: {tarball: https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@9193}
version: 1.2.1
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@95d82961':
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@95d82961}
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@28ac795':
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@28ac795}
version: 1.0.0-next.7
peerDependencies:
svelte: ^4.0.0
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@95d8296180fa037dc1c582b2fddb023d546f8314':
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@95d8296180fa037dc1c582b2fddb023d546f8314}
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@28ac79582e305e680ab7a5f131f2a3f594d86682':
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@28ac79582e305e680ab7a5f131f2a3f594d86682}
version: 1.0.0-next.7
peerDependencies:
svelte: ^4.0.0
@@ -239,8 +239,8 @@ packages:
'@appwrite.io/pink-legacy@1.0.0':
resolution: {integrity: sha512-EZk/wX8oDhIsCXf2A0oQjdNOaHvh5MnWbLQI4pAiGrdy5qQGPoU19AK6iVX6z3QoOq7geoEu0zVwAowBy5hZbQ==}
'@appwrite.io/pink-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@95d82961':
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@95d82961}
'@appwrite.io/pink-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@28ac795':
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@28ac795}
version: 1.0.0-next.85
peerDependencies:
react-dom: ^18.0.0
@@ -4089,11 +4089,11 @@ snapshots:
'@appwrite.io/console@https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@9193': {}
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@95d82961(svelte@4.2.19)':
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@28ac795(svelte@4.2.19)':
dependencies:
svelte: 4.2.19
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@95d8296180fa037dc1c582b2fddb023d546f8314(svelte@4.2.19)':
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@28ac79582e305e680ab7a5f131f2a3f594d86682(svelte@4.2.19)':
dependencies:
svelte: 4.2.19
@@ -4106,9 +4106,9 @@ snapshots:
'@appwrite.io/pink-icons': 1.0.0
the-new-css-reset: 1.11.3
'@appwrite.io/pink-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@95d82961(react-dom@18.3.1(react@18.3.1))(svelte@4.2.19)':
'@appwrite.io/pink-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@28ac795(react-dom@18.3.1(react@18.3.1))(svelte@4.2.19)':
dependencies:
'@appwrite.io/pink-icons-svelte': https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@95d8296180fa037dc1c582b2fddb023d546f8314(svelte@4.2.19)
'@appwrite.io/pink-icons-svelte': https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@28ac79582e305e680ab7a5f131f2a3f594d86682(svelte@4.2.19)
'@floating-ui/dom': 1.6.13
'@melt-ui/pp': 0.3.2(@melt-ui/svelte@0.86.2(svelte@4.2.19))(svelte@4.2.19)
'@melt-ui/svelte': 0.86.2(svelte@4.2.19)
+23 -15
View File
@@ -6,7 +6,7 @@
Link,
Tooltip,
Card,
ActionList,
ActionMenu,
Input,
Button,
Avatar
@@ -78,7 +78,7 @@
<Navbar.Base {...$$props}>
<div slot="left" class="left">
<div class="only-mobile">
<div class="only-mobile-tablet">
<button
class="sideNavToggle"
on:click={() => {
@@ -142,17 +142,20 @@
<div class="account-container">
<Card.Base padding="xxs" shadow={true}>
<Layout.Stack gap="xxs">
<ActionList.Root>
<ActionList.Item.Anchor
icon={IconUser}
title="Account"
href={`${base}/account`} />
<ActionMenu.Root>
<Layout.Stack gap="xxs">
<ActionMenu.Item.Anchor
leadingIcon={IconUser}
size="l"
href={`${base}/account`}>
Account</ActionMenu.Item.Anchor>
<ActionList.Item.Button
icon={IconLogoutRight}
on:click={logout}
title="Sign out" />
</ActionList.Root>
<ActionMenu.Item.Button
leadingIcon={IconLogoutRight}
size="l"
on:click={logout}>Sign out</ActionMenu.Item.Button>
</Layout.Stack>
</ActionMenu.Root>
<Input.Select
value={$app.theme === 'auto' ? 'system' : $app.theme}
name="mode"
@@ -279,13 +282,18 @@
}
@media (min-width: 768px) {
.only-desktop {
display: flex;
}
.only-mobile {
display: none;
}
}
@media (min-width: 1024px) {
.only-mobile-tablet {
display: none;
}
.only-desktop {
display: flex;
}
}
:global(.icons div:first-of-type:not(:has(.progress-card))) {
height: 20px;
+61 -39
View File
@@ -1,4 +1,6 @@
<script lang="ts">
import { fade } from 'svelte/transition';
import { page } from '$app/stores';
import {
Icon,
Sidebar,
@@ -8,7 +10,8 @@
Link,
Button,
Layout,
Avatar
Avatar,
Typography
} from '@appwrite.io/pink-svelte';
import {
@@ -29,6 +32,8 @@
import type { ComponentType } from 'svelte';
import { showSupportModal } from '$routes/(console)/wizard/support/store';
import MobileSupportModal from '$routes/(console)/wizard/support/mobileSupportModal.svelte';
import { getSidebarState, updateSidebarState } from '$lib/helpers/sidebar';
import { isTabletViewport } from '$lib/stores/viewport';
type $$Props = HTMLElement & {
state?: 'closed' | 'open' | 'icons';
@@ -43,7 +48,7 @@
subNavigation?: ComponentType;
};
export let state: $$Props['state'] = 'closed';
export let state: $$Props['state'] = 'icons';
export let project: $$Props['project'];
export let avatar: $$Props['avatar'];
export let progressCard: $$Props['progressCard'] = undefined;
@@ -59,6 +64,9 @@
}
}
$: state = $isTabletViewport ? 'closed' : getSidebarState();
$: pathname = $page.url.pathname;
const projectOptions = [
{ name: 'Auth', icon: IconUserGroup, slug: 'auth' },
{ name: 'Databases', icon: IconDatabase, slug: 'databases' },
@@ -70,10 +78,16 @@
</script>
<div class:only-mobile={project === undefined}>
<Sidebar.Base {...$$props} bind:state resizable={subNavigation === undefined}>
<Sidebar.Base
{...$$props}
bind:state
resizable={true}
onResize={(sidebarState) => {
updateSidebarState(sidebarState);
}}>
<div slot="top">
<div class="only-mobile top">
<div class="icons">
<div class="only-mobile-tablet top">
<div class="icons search-icon">
<Link.Button
variant="quiet-muted"
on:click={() => {
@@ -103,11 +117,17 @@
on:click={() => {
sideBarIsOpen = false;
}}>
<ProgressCircle size="s" progress={progressCard.percentage} />
<div class="info" class:no-text={state === 'icons'}>
<span class="title">{progressCard.title}</span>
<span class="description">{progressCard.percentage}% complete</span>
<div class="progressCircle">
<ProgressCircle size="s" progress={progressCard.percentage} />
</div>
{#if state !== 'icons'}
<div class="info" in:fade={{ delay: 200, duration: 200 }}>
<Typography.Text variant="m-600"
>{progressCard.title}</Typography.Text>
<Typography.Text
>{progressCard.percentage}% complete</Typography.Text>
</div>
{/if}
</a>
<span slot="tooltip">Getting started</span>
</Tooltip>
@@ -144,6 +164,7 @@
<a
href={`/console/project-${project.$id}/${projectOption.slug}`}
class="link"
class:active={pathname.includes(projectOption.slug)}
on:click={() => {
sideBarIsOpen = false;
}}
@@ -302,11 +323,24 @@
}
}
}
.active {
background: var(--color-bgcolor-neutral-secondary, #f4f4f7);
.link-text {
color: var(--color-fgcolor-neutral-primary);
}
.link-icon {
color: var(--color-fgcolor-neutral-primary);
}
}
.icons .link {
gap: 0;
}
.search-icon {
display: flex;
}
.link-text {
width: 128px;
transition: all 0.2s ease-in-out;
@@ -402,7 +436,8 @@
}
@media (min-width: 1024px) {
.only-mobile {
.only-mobile,
.only-mobile-tablet {
display: none;
}
.only-desktop {
@@ -411,13 +446,10 @@
}
.progress-card {
width: 170px;
height: 60px;
width: 168px;
padding: var(--base-8, 8px);
display: flex;
padding: 8px;
flex-direction: row;
justify-content: center;
align-items: center;
gap: var(--space-5, 10px);
margin-block-end: var(--space-6, 12px);
align-self: stretch;
@@ -426,36 +458,24 @@
background: var(--color-bgcolor-neutral-default, #fafafb);
transition: all 0.2s ease-in-out;
@media (min-width: 1024px) {
width: 178px;
}
.info {
position: absolute;
display: flex;
flex-direction: column;
max-height: 40px;
overflow: hidden;
opacity: 1;
transition: opacity 0.2s ease-in-out 0.2s;
margin-left: var(--base-36, 36px);
}
.no-text {
display: none;
}
.title {
color: var(--color-fgcolor-neutral-secondary, #56565c);
font-size: var(--font-size-s, 14px);
font-style: normal;
font-weight: 600;
line-height: 140%; /* 19.6px */
letter-spacing: -0.063px;
}
.description {
color: var(--color-fgcolor-neutral-secondary, #56565c);
/* Desktop/Body M 400 */
font-size: var(--font-size-s, 14px);
font-style: normal;
font-weight: 400;
line-height: 140%; /* 19.6px */
letter-spacing: -0.063px;
.progressCircle {
display: flex;
height: 100%;
align-items: center;
}
}
@@ -463,10 +483,12 @@
width: var(--base-32, 32px);
border-color: transparent;
background: transparent;
padding-left: var(--base-4, 4px);
}
.divider {
margin-block: var(--space-2, 4px);
margin-block-start: var(--space-2, 4px);
margin-block-end: var(--space-6, 12px);
width: 100%;
}
+29
View File
@@ -0,0 +1,29 @@
import { get } from 'svelte/store';
import { user } from '$lib/stores/user';
import { sdk } from '$lib/stores/sdk';
const userPreferences = () => get(user)?.prefs;
export function updateSidebarState(state: 'closed' | 'open' | 'icons') {
if (state === 'open' || state === 'icons') {
const currentPrefs = userPreferences();
const newPrefs = {
...currentPrefs,
sidebarState: state
};
sdk.forConsole.account.updatePrefs(newPrefs);
}
}
export function getSidebarState(): 'open' | 'icons' {
const currentPrefs = userPreferences();
if (currentPrefs && currentPrefs.sidebarState) {
if (currentPrefs.sidebarState === 'open' || currentPrefs.sidebarState === 'icons') {
return currentPrefs.sidebarState;
}
}
return 'open';
}
+2
View File
@@ -23,6 +23,8 @@
block-size: 152px;
border-bottom: 1px solid var(--color-border-neutral, #2d2d31);
background: var(--color-bgcolor-neutral-primary, #1d1d21);
margin-left: -190px;
padding-left: 190px;
}
.cover-container {
position: relative;
+2
View File
@@ -77,6 +77,8 @@
<style lang="scss">
.main-footer {
margin-block-start: auto;
background-color: hsl(var(--p-body-bg-color));
z-index: 1;
}
.main-footer-start .inline-links-item {
+7 -4
View File
@@ -1,14 +1,11 @@
<script lang="ts">
import { page } from '$app/stores';
import { slide } from '$lib/helpers/transition';
import { getContext } from 'svelte';
import type { Writable } from 'svelte/store';
export let state: 'closed' | 'open' | 'icons' = 'open';
export let subNavigation;
$: project = $page.params.project;
$: subNavigation = $page.data.subNavigation;
// We need to have this second variable, because we only want narrow
// to change automatically if we change from having a second side nav to
@@ -44,14 +41,20 @@
.level-2-nav {
display: none;
@media (min-width: 768px) {
@media (min-width: 1024px) {
display: block;
position: fixed;
z-index: 10;
left: 200px;
transition: left 0.2s ease-in-out;
margin-left: -5px;
}
}
:global(.level-2-nav nav) {
padding-left: 15px !important;
}
.icons {
left: 54px;
}
+22 -7
View File
@@ -15,7 +15,7 @@
import { type Models } from '@appwrite.io/console';
import { isCloud } from '$lib/system';
import SideNavigation from '$lib/layout/navigation.svelte';
import { isSmallViewport } from '$lib/stores/viewport';
import { isTabletViewport } from '$lib/stores/viewport';
import { hasOnboardingDismissed } from '$lib/helpers/onboarding';
import { isSidebarOpen } from '$lib/stores/sidebar';
@@ -27,9 +27,11 @@
$: selectedProject = loadedProjects.find((project) => project.isSelected);
let y: number;
let showContentTransition = true;
page.subscribe(({ url }) => {
$showSubNavigation = url.searchParams.get('openNavbar') === 'true';
showContentTransition = !url.pathname.includes('organization');
});
/**
@@ -70,10 +72,10 @@
};
let showAccountMenu = false;
let subNavigation: undefined | ComponentType = undefined;
let subNavigation: undefined | ComponentType = $page.data.subNavigation;
let state: undefined | 'open' | 'closed' | 'icons' = 'closed';
$: state = $isSidebarOpen ? 'open' : 'closed';
$: state = subNavigation && !$isSmallViewport ? 'icons' : $isSidebarOpen ? 'open' : 'closed';
$: state = !$isTabletViewport ? 'icons' : $isSidebarOpen ? 'open' : 'closed';
function handleResize() {
$isSidebarOpen = false;
@@ -115,6 +117,7 @@
<SideNavigation bind:state bind:subNavigation />
<div
class="content"
class:has-transition={showContentTransition}
class:icons-content={state === 'icons'}
class:no-sidebar={!showSideNavigation}>
<section class="main-content" data-test={showSideNavigation}>
@@ -149,9 +152,7 @@
@media (min-width: 1024px) {
width: 100%;
padding-left: 190px;
transition: all 0.3s ease-in-out;
&.icons-content {
padding-left: 54px;
@@ -159,6 +160,12 @@
}
}
.has-transition {
@media (min-width: 1024px) {
transition: all 0.3s ease-in-out;
}
}
.no-sidebar {
padding-left: 0;
}
@@ -167,16 +174,24 @@
min-height: calc(100vh - 30px);
}
:global(main:has(.level-2-nav)) {
.main-content {
@media (min-width: 1024px) {
padding-left: 200px;
}
}
}
.overlay {
position: fixed;
width: calc(100vw - 200px);
width: 100vw;
height: 100vh;
right: 0;
top: 0;
z-index: 10;
background-color: #56565c1a;
backdrop-filter: blur(5px);
transition: backdrop-filter 0.5s ease-in-out;
transition: backdrop-filter 0.2s ease-in-out;
@media (min-width: 1024px) {
display: none;
+5
View File
@@ -1,11 +1,16 @@
import { writable } from 'svelte/store';
export const isSmallViewport = writable(false);
export const isTabletViewport = writable(false);
export function updateViewport() {
if (typeof window !== 'undefined') {
isSmallViewport.set(
typeof window !== 'undefined' ? window.matchMedia('(max-width: 768px)').matches : false
);
isTabletViewport.set(
typeof window !== 'undefined' ? window.matchMedia('(max-width: 1024px)').matches : false
);
}
}
+2 -1
View File
@@ -27,6 +27,7 @@
}
onMount(async () => {
updateViewport();
// handle sources
if (isCloud) {
const urlParams = $page.url.searchParams;
@@ -106,7 +107,7 @@
}
</script>
<svelte:window on:resize={updateViewport} />
<svelte:window on:resize={updateViewport} on:load={updateViewport} />
<Root theme={resolveTheme($app.themeInUse)}>
<Notifications />