Files
gw-svelte/src/lib/components/ui/Footer.svelte
T

188 lines
6.5 KiB
Svelte
Raw Normal View History

2026-05-02 08:26:18 +12:00
<script lang="ts">
2026-06-17 21:51:29 +12:00
import Icon from '$lib/components/ui/Icon.svelte';
2026-05-02 08:26:18 +12:00
import type { FooterContent, LinkItem } from '$lib/types';
import { locationPages } from '$lib/content/locations';
2026-05-02 08:26:18 +12:00
export let footer: FooterContent;
2026-07-04 09:59:57 +12:00
// 'minimal' is a typography test running on the /variants/* pages.
export let variant: 'default' | 'minimal' = 'default';
2026-05-02 08:26:18 +12:00
2026-05-02 08:26:18 +12:00
const socialLinks: LinkItem[] = [
{ label: 'Instagram', href: 'https://www.instagram.com/goodwalk.nz/', external: true },
{ label: 'Facebook', href: 'https://facebook.com/goodwalk.nz', external: true },
{ label: 'Google', href: 'https://g.page/r/CUsvrWPhkYrAEB0', external: true }
];
2026-05-05 22:47:14 +12:00
const aboutLink: LinkItem = { label: 'About Us', href: '/about' };
2026-05-15 01:28:10 +12:00
function scrollToTop() {
window.scrollTo({ top: 0, behavior: 'smooth' });
}
2026-05-05 22:47:14 +12:00
function withAboutLink(links: LinkItem[]) {
if (links.some((link) => link.href === aboutLink.href || link.label === aboutLink.label)) {
return links;
}
const contactIndex = links.findIndex((link) => link.href === '/contact-us');
if (contactIndex === -1) {
return [...links, aboutLink];
}
return [...links.slice(0, contactIndex), aboutLink, ...links.slice(contactIndex)];
}
$: navigationLinks = withAboutLink(footer.navigationLinks);
2026-05-02 08:26:18 +12:00
</script>
2026-07-04 09:59:57 +12:00
<footer data-track-location="footer" class:footer--min={variant === 'minimal'}>
2026-05-02 08:26:18 +12:00
<div class="footer-inner">
<div class="footer-brand">
<enhanced:img
src="$lib/images/goodwalk-auckland-dog-walking-logo.png"
2026-05-02 08:26:18 +12:00
alt="Goodwalk Auckland dog walking service logo"
class="footer-logo"
2026-05-02 19:44:45 +12:00
loading="lazy"
decoding="async"
2026-05-02 08:26:18 +12:00
/>
<p>{footer.brandText}</p>
2026-05-15 16:27:39 +12:00
<div class="footer-social-cluster">
<div class="footer-social-invite" aria-hidden="true">
<span>Join the fun</span>
<Icon name="fas fa-arrow-turn-down" className="footer-social-invite-arrow" />
</div>
<div class="social-links">
2026-05-26 23:30:22 +12:00
<a href={socialLinks[0].href} target="_blank" rel="noopener" aria-label="Instagram" data-track-event="social_click" data-track-type="footer_social" data-track-label="Footer Instagram">
2026-05-15 16:27:39 +12:00
<Icon name="fab fa-instagram" />
</a>
2026-05-26 23:30:22 +12:00
<a href={socialLinks[1].href} target="_blank" rel="noopener" aria-label="Facebook" data-track-event="social_click" data-track-type="footer_social" data-track-label="Footer Facebook">
2026-05-15 16:27:39 +12:00
<Icon name="fab fa-facebook-f" />
</a>
2026-05-26 23:30:22 +12:00
<a href={socialLinks[2].href} target="_blank" rel="noopener" aria-label="Google" data-track-event="social_click" data-track-type="footer_social" data-track-label="Footer Google">
2026-05-15 16:27:39 +12:00
<Icon name="fab fa-google" />
</a>
</div>
2026-05-02 08:26:18 +12:00
</div>
2026-05-13 09:39:52 +12:00
{#if footer.email || footer.phone}
<div class="footer-contact">
{#if footer.email}
2026-05-26 23:30:22 +12:00
<a href="mailto:{footer.email}" class="footer-contact-link" data-track-event="contact_click" data-track-type="email" data-track-label="Footer email">
2026-05-13 09:39:52 +12:00
<Icon name="fas fa-envelope" />
{footer.email}
</a>
{/if}
{#if footer.phone}
2026-05-26 23:30:22 +12:00
<a href="tel:{footer.phone.replace(/[^0-9+]/g, '')}" class="footer-contact-link" data-track-event="contact_click" data-track-type="phone" data-track-label="Footer phone">
2026-05-13 09:39:52 +12:00
<Icon name="fas fa-phone" />
{footer.phone}
</a>
{/if}
</div>
{/if}
2026-05-02 08:26:18 +12:00
</div>
2026-05-26 23:30:22 +12:00
<div class="footer-explore" data-track-location="footer_explore">
2026-05-05 22:48:18 +12:00
<p class="footer-col-label">Explore Goodwalk</p>
2026-05-02 08:26:18 +12:00
<ul class="footer-nav">
2026-05-05 22:47:14 +12:00
{#each navigationLinks as link}
2026-05-02 08:26:18 +12:00
<li>
<a
href={link.href}
target={link.external ? '_blank' : undefined}
rel={link.external ? 'noopener' : undefined}
2026-05-26 23:30:22 +12:00
data-track-event="nav_click"
data-track-type="footer_nav"
data-track-label={link.label}
2026-05-02 08:26:18 +12:00
>
{link.label}
</a>
</li>
{/each}
</ul>
</div>
2026-05-26 23:30:22 +12:00
<div class="footer-locations" data-track-location="footer_locations">
2026-05-18 09:43:29 +12:00
<p class="footer-col-label">
<a href="/locations">Areas we serve</a>
</p>
<ul class="footer-nav">
{#each locationPages as loc}
2026-05-26 23:30:22 +12:00
<li><a href="/locations/{loc.slug}" data-track-event="nav_click" data-track-type="footer_location" data-track-label={loc.suburb}>{loc.suburb}</a></li>
{/each}
</ul>
</div>
2026-05-02 08:26:18 +12:00
</div>
<div class="footer-bottom">
<span>{footer.copyright}</span>
2026-05-26 23:30:22 +12:00
<nav class="footer-legal" data-track-location="footer_legal">
<a href="/terms-and-conditions" data-track-event="nav_click" data-track-type="footer_legal" data-track-label="Terms and Conditions">Terms &amp; Conditions</a>
<a href="/privacy-policy" data-track-event="nav_click" data-track-type="footer_legal" data-track-label="Privacy Policy">Privacy Policy</a>
2026-05-02 08:26:18 +12:00
</nav>
2026-05-26 23:30:22 +12:00
<button type="button" class="footer-back-top" aria-label="Back to top" on:click={scrollToTop} data-track-event="nav_click" data-track-type="footer_back_to_top" data-track-label="Back to top">
2026-05-15 01:28:10 +12:00
↑ Back to top
</button>
2026-05-02 08:26:18 +12:00
</div>
</footer>
2026-07-04 09:59:57 +12:00
<style>
/*
* Minimal footer variant (typography test on /variants/* pages). One calm
* type scale, lighter weights, more air. Structure and colour unchanged.
* Two sizes do all the work: 14px for links/text, 12px for meta. Labels drop
* the display font for tracked body caps, which reads cleaner at small sizes.
*/
.footer--min :global(.footer-logo) {
height: 26px;
margin-bottom: 22px;
}
.footer--min :global(.footer-brand p) {
font-size: 14px;
line-height: 1.75;
opacity: 0.78;
}
.footer--min :global(.footer-col-label) {
font-family: var(--font-body);
font-size: 11px;
font-weight: 600;
letter-spacing: 0.18em;
opacity: 0.5;
margin-bottom: 18px;
}
.footer--min :global(.footer-nav a),
.footer--min :global(.footer-contact-link) {
font-size: 14px;
font-weight: 400;
letter-spacing: 0.005em;
opacity: 0.72;
}
.footer--min :global(.footer-nav a) {
padding: 7px 0;
}
.footer--min :global(.footer-nav a:hover),
.footer--min :global(.footer-contact-link:hover) {
opacity: 1;
}
.footer--min :global(.footer-bottom) {
font-size: 12px;
letter-spacing: 0.01em;
opacity: 0.5;
}
.footer--min :global(.footer-back-top) {
font-size: 12px;
font-weight: 500;
letter-spacing: 0.01em;
text-transform: none;
}
</style>