Skip to content

Commit 8ca7967

Browse files
authored
Merge branch 'main' into blog-authors-update-roles
2 parents dc4f06e + 579a714 commit 8ca7967

File tree

29 files changed

+531
-87
lines changed

29 files changed

+531
-87
lines changed

markdoc.config.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
"type": "esm",
88
"property": "default",
99
"watch": true
10+
},
11+
"partials": {
12+
"auth-security.md": "./src/partials/auth-security.md"
1013
}
1114
}
1215
]

src/lib/components/Feedback.svelte

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<script lang="ts">
22
import { page } from '$app/stores';
3+
import { fade } from 'svelte/transition';
4+
import { loggedIn, user } from '$lib/utils/console';
35
import { PUBLIC_GROWTH_ENDPOINT } from '$env/static/public';
46
57
export let date: string | undefined = undefined;
@@ -14,6 +16,9 @@
1416
async function handleSubmit() {
1517
submitting = true;
1618
error = undefined;
19+
20+
const userId = loggedIn && $user?.$id ? $user.$id : undefined;
21+
1722
const response = await fetch(`${PUBLIC_GROWTH_ENDPOINT}/feedback/docs`, {
1823
method: 'POST',
1924
headers: {
@@ -23,7 +28,10 @@
2328
email,
2429
type: feedbackType,
2530
route: $page.route.id,
26-
comment
31+
comment,
32+
metaFields: {
33+
userId
34+
}
2735
})
2836
});
2937
submitting = false;
@@ -33,6 +41,7 @@
3341
}
3442
comment = email = '';
3543
submitted = true;
44+
setTimeout(() => (showFeedback = false), 500);
3645
}
3746
3847
function reset() {
@@ -45,6 +54,10 @@
4554
$: if (!showFeedback) {
4655
reset();
4756
}
57+
58+
$: if (showFeedback && loggedIn && $user?.email) {
59+
email = $user?.email;
60+
}
4861
</script>
4962

5063
<section class="web-content-footer">
@@ -60,7 +73,7 @@
6073
class="web-radio-button"
6174
aria-label="helpful"
6275
on:click={() => {
63-
showFeedback = feedbackType === 'positive' ? false : true;
76+
showFeedback = feedbackType !== 'positive';
6477
feedbackType = 'positive';
6578
}}
6679
>
@@ -70,7 +83,7 @@
7083
class="web-radio-button"
7184
aria-label="unhelpful"
7285
on:click={() => {
73-
showFeedback = feedbackType === 'negative' ? false : true;
86+
showFeedback = feedbackType !== 'negative';
7487
feedbackType = 'negative';
7588
}}
7689
>
@@ -104,6 +117,7 @@
104117
on:submit|preventDefault={handleSubmit}
105118
class="web-card is-normal"
106119
style="--card-padding:1rem"
120+
out:fade={{ duration: 450 }}
107121
>
108122
<div class="flex flex-col gap-2">
109123
<label for="message">

src/lib/components/FooterNav.svelte

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@
3232
{ label: 'Solid', href: '/docs/quick-starts/solid' }
3333
],
3434
Products: [
35-
{ label: 'Auth', href: '/docs/products/auth' },
35+
{ label: 'Auth', href: '/products/auth' },
3636
{ label: 'Databases', href: '/docs/products/databases' },
37-
{ label: 'Functions', href: '/docs/products/functions' },
37+
{ label: 'Functions', href: '/products/functions' },
3838
{ label: 'Messaging', href: '/products/messaging' },
39-
{ label: 'Storage', href: '/docs/products/storage' },
39+
{ label: 'Storage', href: '/products/storage' },
4040
{ label: 'Realtime', href: '/docs/apis/realtime' }
4141
],
4242
Learn: [

src/lib/components/PreFooter.svelte

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@
33
import { trackEvent } from '$lib/actions/analytics';
44
</script>
55

6-
<img src="/images/bgs/pre-footer.png" alt="" class="web-pre-footer-bg" loading="lazy" style="z-index:-1" />
6+
<img
7+
src="/images/bgs/pre-footer.png"
8+
alt=""
9+
class="web-pre-footer-bg"
10+
loading="lazy"
11+
style="z-index:-1"
12+
/>
713

814
<div class="web-u-row-gap-80 relative grid gap-8 md:grid-cols-2">
915
<section class="web-hero flex items-center justify-center gap-y-8">

src/lib/components/ProductsSubmenu.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
icon: '/images/icons/illustrated/dark/auth.png'
2121
},
2222
{
23-
name: 'Database',
23+
name: 'Databases',
2424
href: '/docs/products/databases',
2525
description: 'Scalable and robust databases.',
2626
icon: '/images/icons/illustrated/dark/databases.png'

src/lib/layouts/Docs.svelte

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@
3434
}
3535
3636
const CTX_KEY = Symbol('docs');
37+
const TUT_CTX_KEY = Symbol('tut-docs');
3738
export const isInDocs = () => getContext<boolean>(CTX_KEY) ?? false;
39+
export const isInTutorialDocs = () => getContext<boolean>(TUT_CTX_KEY) ?? false;
3840
</script>
3941

4042
<script lang="ts">
@@ -43,6 +45,7 @@
4345
import { getContext, setContext } from 'svelte';
4446
import { GITHUB_REPO_LINK, GITHUB_STARS } from '$lib/constants';
4547
import { PUBLIC_APPWRITE_DASHBOARD } from '$env/static/public';
48+
import { page } from '$app/stores';
4649
4750
export let variant: DocsLayoutVariant = 'default';
4851
export let isReferences = false;
@@ -63,7 +66,9 @@
6366
showSidenav: false
6467
}));
6568
});
66-
setContext(CTX_KEY, true);
69+
70+
const key = $page.route.id?.includes('tutorials') ? TUT_CTX_KEY : CTX_KEY;
71+
setContext(key, true);
6772
6873
const handleKeydown = (e: KeyboardEvent) => {
6974
if (e.key === 'Escape' && ($layoutState.showReferences || $layoutState.showSidenav)) {

src/lib/layouts/DocsArticle.svelte

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,17 @@
1313
</script>
1414

1515
<script lang="ts">
16-
import { scrollToTop } from '$lib/actions/scrollToTop';
17-
16+
import { setContext } from 'svelte';
17+
import { writable } from 'svelte/store';
1818
import { Feedback } from '$lib/components';
19+
import { scrollToTop } from '$lib/actions/scrollToTop';
1920
2021
export let title: string;
2122
export let toc: Array<TocItem>;
2223
export let back: string | undefined = undefined;
2324
export let date: string | undefined = undefined;
25+
26+
const reducedArticleSize = setContext('articleHasNumericBadge', writable(false));
2427
</script>
2528

2629
<main class="contents" id="main">
@@ -59,8 +62,9 @@
5962
</div>
6063
<div class="web-article-header-end" />
6164
</header>
62-
<div class="web-article-content">
65+
<div class="web-article-content" class:web-reduced-article-size={$reducedArticleSize}>
6366
<slot />
67+
6468
<Feedback {date} />
6569
</div>
6670
<aside class="web-references-menu ps-6">
@@ -110,3 +114,12 @@
110114
</aside>
111115
</article>
112116
</main>
117+
118+
<style>
119+
@media (min-width: 1280px) and (max-width: 1330px) {
120+
.web-reduced-article-size {
121+
/* original/default is 41.5rem */
122+
max-inline-size: 40.5rem;
123+
}
124+
}
125+
</style>

src/lib/layouts/DocsTutorial.svelte

Lines changed: 117 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
import type { Tutorial } from '$markdoc/layouts/Tutorial.svelte';
55
import type { TocItem } from './DocsArticle.svelte';
66
import Heading from '$markdoc/nodes/Heading.svelte';
7-
import { onMount } from 'svelte';
7+
import { onMount, tick } from 'svelte';
8+
import { page } from '$app/stores';
89
910
export let toc: Array<TocItem>;
1011
export let back: string;
@@ -31,13 +32,66 @@
3132
3233
let slotContent: HTMLElement | null = null;
3334
35+
function scrollToElement(pageHash: string) {
36+
const element = document.getElementById(pageHash);
37+
if (element) {
38+
const offset = 50;
39+
const rect = element.getBoundingClientRect();
40+
window.scroll({ top: window.scrollY + rect.top - offset });
41+
}
42+
}
43+
44+
/**
45+
* Due to underlying logic with anchor links & the auto-scroll via hash values in the URL,
46+
* we have an issue where if the first item is not scrolled enough it isn't marked as `selected`.
47+
*
48+
* We do below workaround for the time being without breaking things to scroll to the first item.
49+
*/
50+
async function preSelectItemOnInit() {
51+
await tick();
52+
53+
if (!$page.url.hash) return;
54+
const tocItem = toc.slice(1);
55+
56+
// no sub-items, return.
57+
if (!tocItem.length) return;
58+
59+
const pageHash = $page.url.hash.replace('#', '');
60+
const tocItemHref = tocItem[0].href.replace('#', '');
61+
62+
if (pageHash !== tocItemHref) return;
63+
64+
scrollToElement(pageHash);
65+
}
66+
67+
// same issue as above, only happens on the first item.
68+
function scrollToItem(parent: TocItem, index: number) {
69+
const tocItem = toc.slice(1);
70+
71+
if (!tocItem.length) return;
72+
const tocItemHref = parent.href.replace('#', '');
73+
74+
const element = document.getElementById(tocItemHref);
75+
76+
if (index === 0) {
77+
scrollToElement(tocItemHref);
78+
} else {
79+
element?.scrollIntoView();
80+
}
81+
82+
// because we used `preventDefault`.
83+
history.pushState(null, '', parent.href);
84+
}
85+
3486
onMount(() => {
3587
if (!slotContent) return;
3688
3789
// dynamically modify all `label` headers to `body`.
38-
slotContent.querySelectorAll<HTMLHeadingElement>('h2.web-label').forEach((header) => {
39-
header.classList.replace('web-label', 'web-main-body-500');
90+
slotContent.querySelectorAll<HTMLHeadingElement>('h2.text-label').forEach((header) => {
91+
header.classList.replace('text-label', 'web-main-body-500');
4092
});
93+
94+
preSelectItemOnInit();
4195
});
4296
</script>
4397

@@ -77,7 +131,9 @@
77131
/>
78132
</a>
79133
{/if}
80-
<h1 class="web-title lg:-ml-5">{firstStepItem?.title}</h1>
134+
<h1 class="web-title {currentStep === 1 ? 'lg:-ml-5' : ''}">
135+
{firstStepItem?.title}
136+
</h1>
81137
</div>
82138
</div>
83139
<div class="web-article-header-end" />
@@ -87,16 +143,18 @@
87143
<section class="web-article-content-sub-section">
88144
<header class="web-article-content-header">
89145
<span class="web-numeric-badge">{currentStep}</span>
90-
<Heading level={1} id={currentStepItem.href} step={currentStep}>
91-
{getCorrectTitle(currentStepItem, 1)}
92-
</Heading>
146+
<div class="tutorial-heading">
147+
<Heading level={1} id={currentStepItem.href} step={currentStep}>
148+
{getCorrectTitle(currentStepItem, 1)}
149+
</Heading>
150+
</div>
93151
</header>
94152

95-
<div class="u-padding-block-start-32" bind:this={slotContent}>
153+
<div class="web-u-padding-block-start-32" bind:this={slotContent}>
96154
<slot />
97155
</div>
98156

99-
<div class="flex justify-between">
157+
<div class="web-u-padding-block-start-32 flex justify-between">
100158
{#if prevStep}
101159
<a href={prevStep.href} class="web-button is-text previous-step-anchor">
102160
<span class="icon-cheveron-left" aria-hidden="true" />
@@ -135,6 +193,7 @@
135193
<ol class="web-references-menu-list">
136194
{#each tutorials as tutorial, index}
137195
{@const isCurrentStep = currentStep === tutorial.step}
196+
{@const absoluteToc = toc.slice(1)}
138197
<li class="web-references-menu-item">
139198
<a
140199
href={tutorial.href}
@@ -148,14 +207,16 @@
148207
>{index === 0 ? 'Introduction' : tutorial.title}</span
149208
>
150209
</a>
151-
{#if isCurrentStep && toc.length}
210+
{#if isCurrentStep && absoluteToc.length}
152211
<ol
153212
class="web-references-menu-list u-margin-block-start-16 u-margin-inline-start-32"
154213
>
155-
{#each toc.slice(1) as parent}
214+
{#each absoluteToc as parent, innerIndex}
156215
<li class="web-references-menu-item">
157216
<a
158217
href={parent.href}
218+
on:click|preventDefault={() =>
219+
scrollToItem(parent, innerIndex)}
159220
class="web-references-menu-link is-inner"
160221
class:tutorial-scroll-indicator={parent.selected}
161222
class:is-selected={parent.selected}
@@ -208,4 +269,49 @@
208269
background: unset;
209270
padding-inline-start: unset;
210271
}
272+
273+
.u-margin-block-start-16 {
274+
margin-block-start: 1rem;
275+
}
276+
277+
.u-margin-inline-start-32 {
278+
margin-inline-start: 2rem;
279+
}
280+
281+
.web-references-menu-item:has(.is-selected)::before {
282+
/* maintains the distance correctly for the children items */
283+
inset-inline-start: -3.55rem;
284+
}
285+
286+
/* Static slider: default slider for each selected link */
287+
.web-references-menu-list > .web-references-menu-item > .is-selected::before {
288+
content: ' ';
289+
position: absolute;
290+
inset-block-start: 0;
291+
block-size: 1.375rem;
292+
inline-size: 0.0625rem;
293+
inset-inline-start: -1.3125rem;
294+
background-color: hsl(var(--p-references-menu-link-color-text));
295+
}
296+
297+
/* Hide static slider if any child menu item is selected */
298+
.web-references-menu-list
299+
> .web-references-menu-item:has(.web-references-menu-list .is-selected)
300+
> .is-selected::before {
301+
background-color: transparent;
302+
}
303+
304+
/* Transparent slider for selected child items because we use parent level */
305+
.web-references-menu-list
306+
> .web-references-menu-item
307+
> .web-references-menu-list
308+
> .web-references-menu-item
309+
> .is-selected::before {
310+
content: '';
311+
background-color: transparent;
312+
}
313+
314+
:global(.tutorial-heading h2) {
315+
margin-bottom: unset;
316+
}
211317
</style>

0 commit comments

Comments
 (0)