Add skeleton, updates to client email formatting
This commit is contained in:
+3
-5
@@ -392,7 +392,7 @@ def client_email(data: BookingSubmission) -> str:
|
|||||||
</h1>
|
</h1>
|
||||||
<p style="margin:0 0 32px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
|
<p style="margin:0 0 32px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
|
||||||
font-size:16px;color:#555;line-height:1.65;">
|
font-size:16px;color:#555;line-height:1.65;">
|
||||||
We’ve received your enquiry and Aless will be in touch shortly to arrange
|
We’ve received your enquiry and we will be in touch shortly to arrange
|
||||||
a <strong style="color:#213021;">Meet & Greet</strong> with you and
|
a <strong style="color:#213021;">Meet & Greet</strong> with you and
|
||||||
{data.petName}.
|
{data.petName}.
|
||||||
</p>
|
</p>
|
||||||
@@ -431,7 +431,7 @@ def client_email(data: BookingSubmission) -> str:
|
|||||||
</div>
|
</div>
|
||||||
<div style="font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
|
<div style="font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
|
||||||
font-size:14px;color:#666;line-height:1.6;">
|
font-size:14px;color:#666;line-height:1.6;">
|
||||||
We will review your details and reach out within 1–2 business days
|
We will review your details and reach out within 1 business days
|
||||||
to schedule a free Meet & Greet. No commitment required — just a
|
to schedule a free Meet & Greet. No commitment required — just a
|
||||||
chance for {data.petName} to make a new best friend.
|
chance for {data.petName} to make a new best friend.
|
||||||
</div>
|
</div>
|
||||||
@@ -441,9 +441,7 @@ def client_email(data: BookingSubmission) -> str:
|
|||||||
|
|
||||||
<p style="margin:0;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
|
<p style="margin:0;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
|
||||||
font-size:14px;color:#888;line-height:1.6;">
|
font-size:14px;color:#888;line-height:1.6;">
|
||||||
Questions? Just reply to this email or reach us at
|
Questions? Just reply to this email or reach us at 022 642 1011.
|
||||||
<a href="mailto:{REPLY_TO}" style="color:#213021;font-weight:600;
|
|
||||||
text-decoration:none;">{REPLY_TO}</a>.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -40,11 +40,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.instagram-panel {
|
.instagram-panel {
|
||||||
padding: 34px 360px 44px 44px;
|
padding: 42px 44px 112px;
|
||||||
border-radius: 32px;
|
border-radius: 32px;
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle at top left, rgba(255, 255, 255, 0.52), transparent 42%),
|
radial-gradient(circle at top left, rgba(255, 255, 255, 0.52), transparent 42%),
|
||||||
linear-gradient(135deg, rgba(255, 250, 236, 0.96), rgba(255, 240, 188, 0.94));
|
linear-gradient(135deg, rgba(255, 252, 242, 0.98), rgba(255, 243, 198, 0.96));
|
||||||
box-shadow:
|
box-shadow:
|
||||||
inset 0 0 0 1px rgba(17, 20, 24, 0.06),
|
inset 0 0 0 1px rgba(17, 20, 24, 0.06),
|
||||||
0 26px 50px rgba(106, 80, 16, 0.14);
|
0 26px 50px rgba(106, 80, 16, 0.14);
|
||||||
@@ -53,7 +53,9 @@
|
|||||||
|
|
||||||
.instagram-copy {
|
.instagram-copy {
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
text-align: left;
|
max-width: 620px;
|
||||||
|
margin: 0 auto;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.instagram-kicker {
|
.instagram-kicker {
|
||||||
@@ -70,12 +72,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.instagram-copy :global(h2) {
|
.instagram-copy :global(h2) {
|
||||||
max-width: 11ch;
|
max-width: 12ch;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.instagram-blurb {
|
.instagram-blurb {
|
||||||
max-width: 420px;
|
max-width: 520px;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.instagram-button {
|
.instagram-button {
|
||||||
@@ -84,13 +90,30 @@
|
|||||||
|
|
||||||
.instagram-dog-wrap {
|
.instagram-dog-wrap {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 24px;
|
left: 50%;
|
||||||
bottom: -12px;
|
bottom: -74px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: clamp(240px, 30vw, 360px);
|
width: clamp(300px, 36vw, 430px);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.instagram-dog-wrap::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
bottom: 54px;
|
||||||
|
width: 92%;
|
||||||
|
height: 56%;
|
||||||
|
border-radius: 999px 999px 40px 40px;
|
||||||
|
background:
|
||||||
|
radial-gradient(circle at 50% 35%, rgba(255, 244, 194, 0.95), rgba(255, 224, 122, 0.88));
|
||||||
|
transform: translateX(-50%);
|
||||||
|
filter: blur(2px);
|
||||||
|
z-index: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.instagram-dog {
|
.instagram-dog {
|
||||||
@@ -117,7 +140,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.instagram-copy {
|
.instagram-copy {
|
||||||
text-align: center;
|
max-width: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.instagram-copy :global(h2) {
|
.instagram-copy :global(h2) {
|
||||||
@@ -142,6 +165,12 @@
|
|||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.instagram-dog-wrap::before {
|
||||||
|
width: 86%;
|
||||||
|
height: 52%;
|
||||||
|
bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.instagram-dog {
|
.instagram-dog {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,730 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export let pathname = '/';
|
||||||
|
|
||||||
|
const serviceRoutes = new Set(['/pack-walks', '/dog-walking', '/puppy-visits']);
|
||||||
|
const legalRoutes = new Set(['/terms-and-conditions', '/privacy-policy']);
|
||||||
|
|
||||||
|
const heroLines = [0, 1, 2];
|
||||||
|
const shortLines = [0, 1];
|
||||||
|
const cardTriplet = [0, 1, 2];
|
||||||
|
const cardQuartet = [0, 1, 2, 3];
|
||||||
|
const doubleStack = [0, 1];
|
||||||
|
|
||||||
|
function getVariant(path: string) {
|
||||||
|
if (path === '/') return 'home';
|
||||||
|
if (serviceRoutes.has(path)) return 'service';
|
||||||
|
if (path === '/about' || path === '/about-us') return 'about';
|
||||||
|
if (path === '/our-pricing') return 'pricing';
|
||||||
|
if (path === '/contact-us') return 'contact';
|
||||||
|
if (legalRoutes.has(path)) return 'legal';
|
||||||
|
return 'generic';
|
||||||
|
}
|
||||||
|
|
||||||
|
$: variant = getVariant(pathname);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="route-skeleton" data-skeleton-variant={variant}>
|
||||||
|
<div class="skeleton-shell">
|
||||||
|
<header class="skeleton-header">
|
||||||
|
<div class="skeleton-inner skeleton-nav">
|
||||||
|
<div class="skeleton-row skeleton-nav-links" aria-hidden="true">
|
||||||
|
{#each cardQuartet as _}
|
||||||
|
<span class="skeleton-pill skeleton-shimmer"></span>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span class="skeleton-logo skeleton-shimmer" aria-hidden="true"></span>
|
||||||
|
|
||||||
|
<div class="skeleton-row skeleton-nav-actions" aria-hidden="true">
|
||||||
|
<span class="skeleton-circle skeleton-shimmer"></span>
|
||||||
|
<span class="skeleton-button skeleton-shimmer"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
{#if variant === 'home'}
|
||||||
|
<main class="skeleton-main">
|
||||||
|
<section class="skeleton-section skeleton-home-hero">
|
||||||
|
<div class="skeleton-inner skeleton-home-hero-grid">
|
||||||
|
<div class="skeleton-copy">
|
||||||
|
<span class="skeleton-kicker skeleton-shimmer"></span>
|
||||||
|
<span class="skeleton-title skeleton-title-lg skeleton-shimmer"></span>
|
||||||
|
<span class="skeleton-title skeleton-title-md skeleton-shimmer"></span>
|
||||||
|
{#each heroLines as _}
|
||||||
|
<span class="skeleton-line skeleton-shimmer"></span>
|
||||||
|
{/each}
|
||||||
|
<div class="skeleton-row skeleton-hero-actions">
|
||||||
|
<span class="skeleton-button skeleton-button-wide skeleton-shimmer"></span>
|
||||||
|
<span class="skeleton-button skeleton-button-outline skeleton-shimmer"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="skeleton-media skeleton-media-hero skeleton-shimmer"></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="skeleton-section">
|
||||||
|
<div class="skeleton-inner">
|
||||||
|
<div class="skeleton-strip skeleton-shimmer"></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="skeleton-section">
|
||||||
|
<div class="skeleton-inner">
|
||||||
|
<div class="skeleton-section-heading skeleton-section-heading-left">
|
||||||
|
<span class="skeleton-title skeleton-title-sm skeleton-shimmer"></span>
|
||||||
|
{#each shortLines as _}
|
||||||
|
<span class="skeleton-line skeleton-line-short skeleton-shimmer"></span>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
<div class="skeleton-grid skeleton-grid-3">
|
||||||
|
{#each cardTriplet as _}
|
||||||
|
<article class="skeleton-card skeleton-shimmer"></article>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="skeleton-section">
|
||||||
|
<div class="skeleton-inner">
|
||||||
|
<div class="skeleton-section-heading">
|
||||||
|
<span class="skeleton-title skeleton-title-sm skeleton-shimmer"></span>
|
||||||
|
<span class="skeleton-line skeleton-line-short skeleton-shimmer"></span>
|
||||||
|
</div>
|
||||||
|
<div class="skeleton-grid skeleton-grid-2">
|
||||||
|
{#each doubleStack as _}
|
||||||
|
<article class="skeleton-quote-card skeleton-shimmer">
|
||||||
|
<span class="skeleton-line skeleton-line-medium"></span>
|
||||||
|
<span class="skeleton-line"></span>
|
||||||
|
<span class="skeleton-line skeleton-line-medium"></span>
|
||||||
|
</article>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="skeleton-section skeleton-section-last">
|
||||||
|
<div class="skeleton-inner">
|
||||||
|
<div class="skeleton-booking">
|
||||||
|
<div class="skeleton-booking-header">
|
||||||
|
<span class="skeleton-title skeleton-title-sm skeleton-shimmer"></span>
|
||||||
|
<div class="skeleton-row skeleton-stepper">
|
||||||
|
<span class="skeleton-chip skeleton-shimmer"></span>
|
||||||
|
<span class="skeleton-chip skeleton-shimmer"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="skeleton-grid skeleton-grid-2">
|
||||||
|
<article class="skeleton-form-card skeleton-shimmer"></article>
|
||||||
|
<article class="skeleton-form-card skeleton-shimmer"></article>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
{:else if variant === 'service'}
|
||||||
|
<main class="skeleton-main">
|
||||||
|
<section class="skeleton-section skeleton-service-hero">
|
||||||
|
<div class="skeleton-inner skeleton-home-hero-grid">
|
||||||
|
<div class="skeleton-copy">
|
||||||
|
<span class="skeleton-kicker skeleton-shimmer"></span>
|
||||||
|
<span class="skeleton-title skeleton-title-lg skeleton-shimmer"></span>
|
||||||
|
{#each heroLines as _}
|
||||||
|
<span class="skeleton-line skeleton-shimmer"></span>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
<div class="skeleton-media skeleton-media-hero skeleton-shimmer"></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="skeleton-section">
|
||||||
|
<div class="skeleton-inner">
|
||||||
|
<div class="skeleton-section-heading">
|
||||||
|
<span class="skeleton-title skeleton-title-sm skeleton-shimmer"></span>
|
||||||
|
<span class="skeleton-line skeleton-line-short skeleton-shimmer"></span>
|
||||||
|
</div>
|
||||||
|
<div class="skeleton-grid skeleton-grid-3">
|
||||||
|
{#each cardTriplet as _}
|
||||||
|
<article class="skeleton-plan-card skeleton-shimmer"></article>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="skeleton-section">
|
||||||
|
<div class="skeleton-inner">
|
||||||
|
<div class="skeleton-grid skeleton-grid-3">
|
||||||
|
{#each cardTriplet as _}
|
||||||
|
<article class="skeleton-card skeleton-card-short skeleton-shimmer"></article>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="skeleton-section skeleton-section-last">
|
||||||
|
<div class="skeleton-inner">
|
||||||
|
<div class="skeleton-booking skeleton-shimmer"></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
{:else if variant === 'about'}
|
||||||
|
<main class="skeleton-main">
|
||||||
|
<section class="skeleton-section skeleton-about-hero">
|
||||||
|
<div class="skeleton-inner skeleton-centered-heading">
|
||||||
|
<span class="skeleton-title skeleton-title-lg skeleton-shimmer"></span>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{#each doubleStack as index}
|
||||||
|
<section class="skeleton-section">
|
||||||
|
<div class:skeleton-about-grid-reverse={index % 2 === 1} class="skeleton-inner skeleton-about-grid">
|
||||||
|
<div class="skeleton-copy">
|
||||||
|
<span class="skeleton-title skeleton-title-sm skeleton-shimmer"></span>
|
||||||
|
{#each heroLines as _}
|
||||||
|
<span class="skeleton-line skeleton-shimmer"></span>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
<div class="skeleton-media skeleton-media-tall skeleton-shimmer"></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{/each}
|
||||||
|
|
||||||
|
<section class="skeleton-section">
|
||||||
|
<div class="skeleton-inner">
|
||||||
|
<div class="skeleton-section-heading">
|
||||||
|
<span class="skeleton-title skeleton-title-sm skeleton-shimmer"></span>
|
||||||
|
</div>
|
||||||
|
<div class="skeleton-grid skeleton-grid-3">
|
||||||
|
{#each cardTriplet as _}
|
||||||
|
<article class="skeleton-card skeleton-shimmer"></article>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="skeleton-section skeleton-section-last">
|
||||||
|
<div class="skeleton-inner">
|
||||||
|
<div class="skeleton-contact-card skeleton-shimmer"></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
{:else if variant === 'pricing'}
|
||||||
|
<main class="skeleton-main">
|
||||||
|
<section class="skeleton-section skeleton-about-hero">
|
||||||
|
<div class="skeleton-inner skeleton-centered-heading">
|
||||||
|
<span class="skeleton-title skeleton-title-lg skeleton-shimmer"></span>
|
||||||
|
<span class="skeleton-line skeleton-line-short skeleton-shimmer"></span>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{#each doubleStack as _}
|
||||||
|
<section class="skeleton-section">
|
||||||
|
<div class="skeleton-inner">
|
||||||
|
<div class="skeleton-section-heading skeleton-section-heading-left">
|
||||||
|
<span class="skeleton-title skeleton-title-sm skeleton-shimmer"></span>
|
||||||
|
<span class="skeleton-line skeleton-line-short skeleton-shimmer"></span>
|
||||||
|
</div>
|
||||||
|
<div class="skeleton-grid skeleton-grid-3">
|
||||||
|
{#each cardTriplet as _}
|
||||||
|
<article class="skeleton-plan-card skeleton-shimmer"></article>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{/each}
|
||||||
|
|
||||||
|
<section class="skeleton-section skeleton-section-last">
|
||||||
|
<div class="skeleton-inner">
|
||||||
|
<div class="skeleton-booking skeleton-shimmer"></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
{:else if variant === 'contact'}
|
||||||
|
<main class="skeleton-main">
|
||||||
|
<section class="skeleton-section skeleton-about-hero">
|
||||||
|
<div class="skeleton-inner skeleton-centered-heading">
|
||||||
|
<span class="skeleton-title skeleton-title-lg skeleton-shimmer"></span>
|
||||||
|
<span class="skeleton-line skeleton-line-short skeleton-shimmer"></span>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="skeleton-section skeleton-section-last">
|
||||||
|
<div class="skeleton-inner">
|
||||||
|
<div class="skeleton-booking">
|
||||||
|
<div class="skeleton-booking-header">
|
||||||
|
<span class="skeleton-title skeleton-title-sm skeleton-shimmer"></span>
|
||||||
|
<div class="skeleton-row skeleton-stepper">
|
||||||
|
<span class="skeleton-chip skeleton-shimmer"></span>
|
||||||
|
<span class="skeleton-chip skeleton-shimmer"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="skeleton-grid skeleton-grid-2">
|
||||||
|
<article class="skeleton-form-card skeleton-shimmer"></article>
|
||||||
|
<article class="skeleton-form-card skeleton-shimmer"></article>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
{:else}
|
||||||
|
<main class="skeleton-main">
|
||||||
|
<section class="skeleton-section skeleton-about-hero">
|
||||||
|
<div class="skeleton-inner skeleton-centered-heading">
|
||||||
|
<span class="skeleton-title skeleton-title-lg skeleton-shimmer"></span>
|
||||||
|
<span class="skeleton-line skeleton-line-short skeleton-shimmer"></span>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="skeleton-section skeleton-section-last">
|
||||||
|
<div class="skeleton-inner">
|
||||||
|
<div class="skeleton-legal-card skeleton-shimmer">
|
||||||
|
{#each cardQuartet as _}
|
||||||
|
<span class="skeleton-line skeleton-line-long"></span>
|
||||||
|
{/each}
|
||||||
|
{#each heroLines as _}
|
||||||
|
<span class="skeleton-line"></span>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<footer class="skeleton-footer">
|
||||||
|
<div class="skeleton-inner skeleton-footer-grid">
|
||||||
|
<article class="skeleton-footer-card skeleton-shimmer"></article>
|
||||||
|
<article class="skeleton-footer-card skeleton-shimmer"></article>
|
||||||
|
<article class="skeleton-footer-card skeleton-shimmer"></article>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.route-skeleton {
|
||||||
|
min-height: 100vh;
|
||||||
|
background:
|
||||||
|
radial-gradient(circle at top left, rgba(229, 214, 194, 0.45), transparent 34%),
|
||||||
|
linear-gradient(180deg, #fcfaf6 0%, #f7f3eb 100%);
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-shell {
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-header {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1;
|
||||||
|
backdrop-filter: blur(14px);
|
||||||
|
background: rgba(252, 250, 246, 0.84);
|
||||||
|
border-bottom: 1px solid rgba(33, 48, 33, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-main,
|
||||||
|
.skeleton-footer {
|
||||||
|
padding: 0 0 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-section {
|
||||||
|
padding: 32px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-section-last {
|
||||||
|
padding-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-inner {
|
||||||
|
max-width: var(--max-w);
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-nav,
|
||||||
|
.skeleton-row,
|
||||||
|
.skeleton-home-hero-grid,
|
||||||
|
.skeleton-about-grid,
|
||||||
|
.skeleton-footer-grid,
|
||||||
|
.skeleton-booking-header,
|
||||||
|
.skeleton-grid {
|
||||||
|
display: grid;
|
||||||
|
gap: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-nav {
|
||||||
|
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
|
||||||
|
align-items: center;
|
||||||
|
min-height: 92px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-nav-links {
|
||||||
|
gap: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-nav-actions {
|
||||||
|
gap: 14px;
|
||||||
|
justify-content: end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-logo {
|
||||||
|
display: block;
|
||||||
|
width: 188px;
|
||||||
|
height: 46px;
|
||||||
|
border-radius: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-pill,
|
||||||
|
.skeleton-circle,
|
||||||
|
.skeleton-button,
|
||||||
|
.skeleton-logo,
|
||||||
|
.skeleton-kicker,
|
||||||
|
.skeleton-title,
|
||||||
|
.skeleton-line,
|
||||||
|
.skeleton-media,
|
||||||
|
.skeleton-strip,
|
||||||
|
.skeleton-card,
|
||||||
|
.skeleton-plan-card,
|
||||||
|
.skeleton-quote-card,
|
||||||
|
.skeleton-chip,
|
||||||
|
.skeleton-form-card,
|
||||||
|
.skeleton-booking,
|
||||||
|
.skeleton-contact-card,
|
||||||
|
.skeleton-legal-card,
|
||||||
|
.skeleton-footer-card {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
background: rgba(33, 48, 33, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-shimmer::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
transform: translateX(-100%);
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
rgba(255, 255, 255, 0) 0%,
|
||||||
|
rgba(255, 255, 255, 0.58) 50%,
|
||||||
|
rgba(255, 255, 255, 0) 100%
|
||||||
|
);
|
||||||
|
animation: skeleton-shimmer 1.25s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-pill {
|
||||||
|
width: 88px;
|
||||||
|
height: 14px;
|
||||||
|
border-radius: 999px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-circle {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 999px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-button {
|
||||||
|
width: 148px;
|
||||||
|
height: 48px;
|
||||||
|
border-radius: 999px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-button-wide {
|
||||||
|
width: 182px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-button-outline {
|
||||||
|
width: 154px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-home-hero,
|
||||||
|
.skeleton-service-hero,
|
||||||
|
.skeleton-about-hero {
|
||||||
|
padding-top: 52px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-home-hero-grid,
|
||||||
|
.skeleton-about-grid {
|
||||||
|
grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-about-grid-reverse {
|
||||||
|
grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-copy {
|
||||||
|
display: grid;
|
||||||
|
gap: 16px;
|
||||||
|
align-content: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-kicker {
|
||||||
|
width: 96px;
|
||||||
|
height: 14px;
|
||||||
|
border-radius: 999px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-title {
|
||||||
|
border-radius: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-title-lg {
|
||||||
|
width: min(540px, 100%);
|
||||||
|
height: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-title-md {
|
||||||
|
width: min(460px, 88%);
|
||||||
|
height: 54px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-title-sm {
|
||||||
|
width: min(320px, 70%);
|
||||||
|
height: 44px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-line {
|
||||||
|
width: min(620px, 100%);
|
||||||
|
height: 16px;
|
||||||
|
border-radius: 999px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-line-short {
|
||||||
|
width: min(420px, 72%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-line-medium {
|
||||||
|
width: 86%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-line-long {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-hero-actions {
|
||||||
|
gap: 16px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-media {
|
||||||
|
border-radius: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-media-hero {
|
||||||
|
min-height: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-media-tall {
|
||||||
|
min-height: 360px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-strip {
|
||||||
|
height: 112px;
|
||||||
|
border-radius: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-section-heading {
|
||||||
|
display: grid;
|
||||||
|
gap: 16px;
|
||||||
|
justify-items: center;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-section-heading-left {
|
||||||
|
justify-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-centered-heading {
|
||||||
|
display: grid;
|
||||||
|
gap: 16px;
|
||||||
|
justify-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-grid-2 {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-grid-3 {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-card,
|
||||||
|
.skeleton-plan-card,
|
||||||
|
.skeleton-quote-card,
|
||||||
|
.skeleton-form-card {
|
||||||
|
border-radius: 30px;
|
||||||
|
min-height: 220px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-card-short {
|
||||||
|
min-height: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-plan-card {
|
||||||
|
min-height: 280px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-quote-card {
|
||||||
|
min-height: 190px;
|
||||||
|
padding: 28px;
|
||||||
|
display: grid;
|
||||||
|
align-content: start;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-booking {
|
||||||
|
padding: 30px;
|
||||||
|
border-radius: 34px;
|
||||||
|
background: rgba(255, 255, 255, 0.72);
|
||||||
|
border: 1px solid rgba(33, 48, 33, 0.08);
|
||||||
|
box-shadow: 0 16px 38px rgba(33, 48, 33, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-booking-header {
|
||||||
|
grid-template-columns: minmax(0, 1fr) auto;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-stepper {
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-chip {
|
||||||
|
width: 108px;
|
||||||
|
height: 38px;
|
||||||
|
border-radius: 999px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-form-card {
|
||||||
|
min-height: 260px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-contact-card {
|
||||||
|
min-height: 220px;
|
||||||
|
border-radius: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-legal-card {
|
||||||
|
min-height: 420px;
|
||||||
|
border-radius: 36px;
|
||||||
|
padding: 36px;
|
||||||
|
display: grid;
|
||||||
|
align-content: start;
|
||||||
|
gap: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-footer {
|
||||||
|
padding-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-footer-grid {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-footer-card {
|
||||||
|
min-height: 210px;
|
||||||
|
border-radius: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes skeleton-shimmer {
|
||||||
|
100% {
|
||||||
|
transform: translateX(100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.skeleton-shimmer::after {
|
||||||
|
animation: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
.skeleton-home-hero-grid,
|
||||||
|
.skeleton-about-grid,
|
||||||
|
.skeleton-about-grid-reverse,
|
||||||
|
.skeleton-grid-3,
|
||||||
|
.skeleton-footer-grid {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-home-hero-grid,
|
||||||
|
.skeleton-about-grid,
|
||||||
|
.skeleton-about-grid-reverse {
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.skeleton-inner {
|
||||||
|
padding: 0 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-nav {
|
||||||
|
grid-template-columns: 1fr auto;
|
||||||
|
gap: 16px;
|
||||||
|
min-height: 78px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-nav-links {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-nav-actions .skeleton-circle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-home-hero,
|
||||||
|
.skeleton-service-hero,
|
||||||
|
.skeleton-about-hero {
|
||||||
|
padding-top: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-home-hero-grid,
|
||||||
|
.skeleton-about-grid,
|
||||||
|
.skeleton-about-grid-reverse,
|
||||||
|
.skeleton-grid-2,
|
||||||
|
.skeleton-grid-3,
|
||||||
|
.skeleton-footer-grid,
|
||||||
|
.skeleton-booking-header {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-title-lg {
|
||||||
|
height: 46px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-title-md,
|
||||||
|
.skeleton-title-sm {
|
||||||
|
height: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-media-hero {
|
||||||
|
min-height: 320px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-media-tall,
|
||||||
|
.skeleton-card,
|
||||||
|
.skeleton-quote-card,
|
||||||
|
.skeleton-plan-card,
|
||||||
|
.skeleton-form-card,
|
||||||
|
.skeleton-footer-card {
|
||||||
|
min-height: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-strip {
|
||||||
|
height: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-booking,
|
||||||
|
.skeleton-legal-card {
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
import { navigating, page } from '$app/stores';
|
||||||
import { afterNavigate, disableScrollHandling } from '$app/navigation';
|
import { afterNavigate, disableScrollHandling } from '$app/navigation';
|
||||||
import { initClickTracking, trackPageView } from '$lib/analytics';
|
import { initClickTracking, trackPageView } from '$lib/analytics';
|
||||||
|
import RouteSkeleton from '$lib/components/RouteSkeleton.svelte';
|
||||||
import '$lib/styles/variables.css';
|
import '$lib/styles/variables.css';
|
||||||
import '$lib/styles/base.css';
|
import '$lib/styles/base.css';
|
||||||
import '$lib/styles/layout.css';
|
import '$lib/styles/layout.css';
|
||||||
@@ -13,6 +15,26 @@
|
|||||||
|
|
||||||
onMount(() => initClickTracking());
|
onMount(() => initClickTracking());
|
||||||
|
|
||||||
|
function shouldShowSkeleton() {
|
||||||
|
const navigation = $navigating;
|
||||||
|
|
||||||
|
if (!navigation?.to?.url) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fromPath = navigation.from?.url.pathname ?? $page.url.pathname;
|
||||||
|
const toPath = navigation.to.url.pathname;
|
||||||
|
|
||||||
|
if (navigation.to.url.hash && toPath === fromPath) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return toPath !== fromPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
$: loadingPath = $navigating?.to?.url.pathname ?? $page.url.pathname;
|
||||||
|
$: showRouteSkeleton = shouldShowSkeleton();
|
||||||
|
|
||||||
afterNavigate(({ from, to }) => {
|
afterNavigate(({ from, to }) => {
|
||||||
if (!from || !to || to.url.hash) {
|
if (!from || !to || to.url.hash) {
|
||||||
return;
|
return;
|
||||||
@@ -38,4 +60,32 @@
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<div class="layout-shell">
|
||||||
|
<div class:layout-content-loading={showRouteSkeleton} class="layout-content" aria-hidden={showRouteSkeleton}>
|
||||||
<slot />
|
<slot />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if showRouteSkeleton}
|
||||||
|
<div class="layout-skeleton-layer" role="status" aria-label="Loading page" aria-live="polite">
|
||||||
|
<RouteSkeleton pathname={loadingPath} />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.layout-shell {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-content-loading {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-skeleton-layer {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 30;
|
||||||
|
overflow-y: auto;
|
||||||
|
background: rgba(251, 251, 251, 0.98);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { render } from '@testing-library/svelte';
|
import { render } from '@testing-library/svelte';
|
||||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||||
|
import { setMockNavigating, setMockPage } from '../test/mocks/app-stores';
|
||||||
|
|
||||||
const afterNavigate = vi.fn();
|
const afterNavigate = vi.fn();
|
||||||
const disableScrollHandling = vi.fn();
|
const disableScrollHandling = vi.fn();
|
||||||
@@ -49,4 +50,25 @@ describe('root layout navigation behavior', () => {
|
|||||||
|
|
||||||
expect(disableScrollHandling).not.toHaveBeenCalled();
|
expect(disableScrollHandling).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('shows a route skeleton while navigating to a new page', async () => {
|
||||||
|
setMockPage('https://www.goodwalk.co.nz/about');
|
||||||
|
setMockNavigating('https://www.goodwalk.co.nz/contact-us', 'https://www.goodwalk.co.nz/about');
|
||||||
|
|
||||||
|
const { default: Layout } = await import('./+layout.svelte');
|
||||||
|
const { getByLabelText, container } = render(Layout);
|
||||||
|
|
||||||
|
expect(getByLabelText('Loading page')).toBeInTheDocument();
|
||||||
|
expect(container.querySelector('[data-skeleton-variant="contact"]')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not show the skeleton for hash-only navigation', async () => {
|
||||||
|
setMockPage('https://www.goodwalk.co.nz/about');
|
||||||
|
setMockNavigating('https://www.goodwalk.co.nz/about#team', 'https://www.goodwalk.co.nz/about');
|
||||||
|
|
||||||
|
const { default: Layout } = await import('./+layout.svelte');
|
||||||
|
const { queryByLabelText } = render(Layout);
|
||||||
|
|
||||||
|
expect(queryByLabelText('Loading page')).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { GET } from './+server';
|
|||||||
|
|
||||||
describe('robots endpoint', () => {
|
describe('robots endpoint', () => {
|
||||||
it('returns the crawl policy and sitemap location', async () => {
|
it('returns the crawl policy and sitemap location', async () => {
|
||||||
const response = GET();
|
const response = await GET({} as never);
|
||||||
const body = await response.text();
|
const body = await response.text();
|
||||||
|
|
||||||
expect(response.headers.get('content-type')).toBe('text/plain; charset=utf-8');
|
expect(response.headers.get('content-type')).toBe('text/plain; charset=utf-8');
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ describe('sitemap endpoint', () => {
|
|||||||
vi.useFakeTimers();
|
vi.useFakeTimers();
|
||||||
vi.setSystemTime(new Date('2026-05-01T09:15:00Z'));
|
vi.setSystemTime(new Date('2026-05-01T09:15:00Z'));
|
||||||
|
|
||||||
const response = GET();
|
const response = await GET({} as never);
|
||||||
const body = await response.text();
|
const body = await response.text();
|
||||||
|
|
||||||
expect(response.headers.get('content-type')).toBe('application/xml; charset=utf-8');
|
expect(response.headers.get('content-type')).toBe('application/xml; charset=utf-8');
|
||||||
|
|||||||
@@ -31,7 +31,12 @@ export function createMockPage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const pageStore = writable<MockPageStoreValue>(createMockPage());
|
export const pageStore = writable<MockPageStoreValue>(createMockPage());
|
||||||
export const navigatingStore = writable<null>(null);
|
export type MockNavigatingStoreValue = {
|
||||||
|
from: { url: URL } | null;
|
||||||
|
to: { url: URL } | null;
|
||||||
|
} | null;
|
||||||
|
|
||||||
|
export const navigatingStore = writable<MockNavigatingStoreValue>(null);
|
||||||
const updatedWritable = writable(false);
|
const updatedWritable = writable(false);
|
||||||
|
|
||||||
export const updatedStore = {
|
export const updatedStore = {
|
||||||
@@ -46,3 +51,17 @@ export function setMockPage(url: string, overrides: Partial<MockPageStoreValue>
|
|||||||
export function resetMockPage() {
|
export function resetMockPage() {
|
||||||
pageStore.set(createMockPage());
|
pageStore.set(createMockPage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setMockNavigating(
|
||||||
|
to: string,
|
||||||
|
from = 'https://www.goodwalk.co.nz/'
|
||||||
|
) {
|
||||||
|
navigatingStore.set({
|
||||||
|
from: { url: new URL(from) },
|
||||||
|
to: { url: new URL(to) }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resetMockNavigating() {
|
||||||
|
navigatingStore.set(null);
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -9,6 +9,6 @@
|
|||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"types": ["node"]
|
"types": ["node", "vitest/globals", "@testing-library/jest-dom"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-1
@@ -1,7 +1,13 @@
|
|||||||
import '@testing-library/jest-dom/vitest';
|
import '@testing-library/jest-dom/vitest';
|
||||||
import { cleanup } from '@testing-library/svelte';
|
import { cleanup } from '@testing-library/svelte';
|
||||||
import { afterEach, beforeAll, vi } from 'vitest';
|
import { afterEach, beforeAll, vi } from 'vitest';
|
||||||
import { navigatingStore, pageStore, resetMockPage, updatedStore } from './src/test/mocks/app-stores';
|
import {
|
||||||
|
navigatingStore,
|
||||||
|
pageStore,
|
||||||
|
resetMockNavigating,
|
||||||
|
resetMockPage,
|
||||||
|
updatedStore
|
||||||
|
} from './src/test/mocks/app-stores';
|
||||||
|
|
||||||
vi.mock('$app/stores', () => ({
|
vi.mock('$app/stores', () => ({
|
||||||
page: { subscribe: pageStore.subscribe },
|
page: { subscribe: pageStore.subscribe },
|
||||||
@@ -81,6 +87,7 @@ beforeAll(() => {
|
|||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
cleanup();
|
cleanup();
|
||||||
resetMockPage();
|
resetMockPage();
|
||||||
|
resetMockNavigating();
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
document.head.innerHTML = '';
|
document.head.innerHTML = '';
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user