Skip to content

Commit 0caf3eb

Browse files
Merge pull request #68 from communitiesuk/Service-navigation-with-nested-navigation-mobile-view-component
Service navigation with nested navigation mobile view component
2 parents 88644d6 + 89f0600 commit 0caf3eb

File tree

22 files changed

+3486
-375
lines changed

22 files changed

+3486
-375
lines changed

src/lib/components/ui/HeaderNav.svelte renamed to src/lib/components/layout/service-navigation-nested-mobile/HeaderNav.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@
1414
homeHref = "/",
1515
navigationItems = [],
1616
currentSection = $bindable(""),
17-
mobileNavIsOpen = false, // Receive open state from parent
17+
mobileNavIsOpen = $bindable(false), // Make this prop bindable
1818
onToggle, // Callback function prop
1919
} = $props<{
2020
serviceName?: string;
2121
homeHref?: string;
2222
navigationItems: NavigationItem[];
2323
currentSection?: string;
24-
mobileNavIsOpen?: boolean; // Prop to receive state
24+
mobileNavIsOpen?: boolean;
2525
onToggle: () => void; // Callback function prop
2626
}>();
2727

src/lib/components/ui/MobileNav.svelte renamed to src/lib/components/layout/service-navigation-nested-mobile/MobileNav.svelte

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
isOpen?: boolean;
3232
sections: NavSection[];
3333
currentSection?: string;
34-
onNavigate: (href: string) => void; // Define prop type
34+
onNavigate: (href: string, event: MouseEvent) => void; // Update prop type to include event
3535
}>();
3636
3737
// Track which sections are expanded
@@ -41,7 +41,7 @@
4141
function toggleSection(sectionTitle: string) {
4242
expandedSections[sectionTitle] = !expandedSections[sectionTitle];
4343
}
44-
44+
4545
// Initialise expanded sections based on current section
4646
$effect(() => {
4747
if (currentSection) {
@@ -71,7 +71,7 @@
7171
// Only handle clicks if not prevented already (e.g. by router)
7272
if (!event.defaultPrevented) {
7373
// dispatch("navigate", href); // Remove dispatch
74-
onNavigate(href); // Call the prop instead
74+
onNavigate(href, event); // Call the prop instead, passing the event
7575
}
7676
}
7777
</script>
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<!--
2+
This component acts as a parent container for HeaderNav and MobileNav,
3+
managing the shared state and interactions for nested mobile navigation.
4+
-->
5+
<script lang="ts">
6+
// Removed import for $effect and $state as they are globals in Svelte 5
7+
import { page } from "$app/stores";
8+
import { goto } from "$app/navigation";
9+
10+
import HeaderNav from "./HeaderNav.svelte";
11+
import MobileNav from "./MobileNav.svelte";
12+
import type { NavigationItem } from "./HeaderNav.svelte";
13+
import type { NavSection } from "./MobileNav.svelte";
14+
15+
// --- Props ---
16+
let {
17+
serviceName = "Service Name",
18+
homeHref = "/",
19+
// Used for the top desktop navigation and determining the current section
20+
navigationItems = [],
21+
// Used for the detailed structure within the mobile flyout menu
22+
mobileNavSections = [],
23+
} = $props<{
24+
serviceName?: string;
25+
homeHref?: string;
26+
navigationItems: NavigationItem[];
27+
mobileNavSections: NavSection[];
28+
}>();
29+
30+
// --- State ---
31+
let isMobileNavOpen = $state(false); // State for mobile menu visibility - reinstated $state
32+
let currentSection = $state(""); // Tracks the active top-level section - reinstated $state
33+
34+
// --- Effects ---
35+
// Update current section based on route changes
36+
$effect(() => {
37+
const path = $page.url.pathname;
38+
39+
// Find the matching top-level navigation item based on the current path
40+
const activeItem = navigationItems.find((item) =>
41+
path === "/"
42+
? item.href === "/"
43+
: item.href !== "/" && path.startsWith(item.href),
44+
);
45+
46+
currentSection = activeItem
47+
? activeItem.text
48+
: path === "/"
49+
? navigationItems[0]?.text || ""
50+
: "";
51+
});
52+
53+
// --- Handlers ---
54+
// Toggle the mobile nav open/closed state
55+
function handleToggleMobileNav() {
56+
isMobileNavOpen = !isMobileNavOpen;
57+
}
58+
59+
// Handle navigation request from mobile menu
60+
function handleMobileNavigation(href: string) {
61+
isMobileNavOpen = false; // Close the menu
62+
if (typeof window !== "undefined") {
63+
goto(href); // Navigate using SvelteKit's router
64+
}
65+
}
66+
</script>
67+
68+
<!-- Render the HeaderNav -->
69+
<HeaderNav
70+
{serviceName}
71+
{homeHref}
72+
{navigationItems}
73+
{currentSection}
74+
mobileNavIsOpen={isMobileNavOpen}
75+
onToggle={handleToggleMobileNav}
76+
/>
77+
78+
<!-- Render the MobileNav -->
79+
<MobileNav
80+
isOpen={isMobileNavOpen}
81+
sections={mobileNavSections}
82+
{currentSection}
83+
onNavigate={handleMobileNavigation}
84+
/>

0 commit comments

Comments
 (0)