Header and Footer
Relevant source files
The following files were used as context for generating this wiki page:
The Header and Footer are foundational UI components for the Grapevine website, providing consistent navigation, branding, and essential information across all pages. They are implemented as React components and integrated into the application's root layout, ensuring their presence throughout the user's journey. The Header is a responsive, interactive element that adapts to screen size and scroll behavior, while the Footer offers a structured sitemap and legal information.
These components are defined in components/header.tsx and components/footer.tsx and are rendered within the RootLayout in app/layout.tsx. Their styling relies on Tailwind CSS and custom theme variables defined in app/globals.css.
Sources: components/header.tsx, components/footer.tsx, app/layout.tsx:15-17
Root Layout Integration
The Header and Footer components are rendered in the RootLayout component, which wraps the main page content (children). This ensures they appear on every page of the application. The main content area is given top padding to prevent it from being obscured by the fixed-position header.
Sources: app/layout.tsx:142-144
The diagram below illustrates the basic structure of a page within the application.
This diagram shows how the Header and Footer components wrap the main page content within the RootLayout.
Sources: app/layout.tsx:138-146, lib/seo.ts:71-89
Header Component (components/header.tsx)
The Header is a client-side component ("use client") that provides primary navigation, branding, and a call-to-action button. It is designed to be responsive and interactive, with distinct layouts for desktop and mobile devices.
Sources: components/header.tsx:1
State Management
The Header's dynamic behavior is managed by several state variables using React's useState hook.
| State Variable | Type | Description |
|---|---|---|
mobileMenuOpen | boolean | Toggles the visibility of the mobile navigation menu. |
isScrolled | boolean | Becomes true if the user has scrolled more than 10 pixels, used to apply a background/shadow effect. |
isVisible | boolean | Controls the header's visibility based on scroll direction. Hides on scroll down, shows on scroll up. |
lastScrollY | number | Stores the last vertical scroll position to determine the scroll direction. |
Sources: components/header.tsx:10-14
Scroll Behavior
The header's visibility changes based on the user's scroll activity. This is managed within a useEffect hook that adds a scroll event listener to the window.
- The header becomes semi-transparent with a shadow (
isScrolled) when the user scrolls down more than 10 pixels. - The header slides out of view (
isVisible: false) when the user scrolls down. - The header slides back into view (
isVisible: true) when the user scrolls up or is near the top of the page.
Sources: components/header.tsx:16-31
The following flowchart illustrates the logic inside the handleScroll function.
This diagram shows the decision-making process for updating the header's isScrolled and isVisible states upon a scroll event.
Sources: components/header.tsx:17-29
Navigation
Navigation is split into desktop and mobile views.
Desktop Navigation
For large screens (lg breakpoint and up), a horizontal list of navigation links is displayed. The currently active link is highlighted based on the pathname from usePathname. A "Book a demo" button is also displayed, which links to the /contact page.
Sources: components/header.tsx:77-93
The menu items are defined in an array:
// components/header.tsx:47-53
const menuItems = [
{ label: "TMCs", href: "/tmcs" },
{ label: "Corporate", href: "/corporate" },
{ label: "Product", href: "/product" },
{ label: "About", href: "/about" },
// { label: "Resources", href: "/resources" },
];
Mobile Navigation
For smaller screens, a hamburger menu button toggles a slide-in panel from the right. The menu button animates between a hamburger icon and a close icon (X). When the menu is open, a semi-transparent backdrop is shown, and clicking it closes the menu. Body scroll is disabled when the mobile menu is open.
Sources: components/header.tsx:33-41, components/header.tsx:96-120, components/header.tsx:123-178
The following state diagram shows the transitions for the mobile menu.
This diagram illustrates the states of the mobile menu and the user actions that trigger transitions between them.
Sources: components/header.tsx:33-41, components/header.tsx:97, components/header.tsx:129, components/header.tsx:159
Footer Component (components/footer.tsx)
The Footer is a client-side component that provides structured navigation, company contact information, legal links, and social media links. It has a dark background (bg-navy) and uses a multi-column grid layout that adjusts for different screen sizes.
Sources: components/footer.tsx:1, components/footer.tsx:30
Structure and Link Groups
The footer is organized into several sections: a main brand section, three link columns (Platform, Company, Legal), and a bottom bar with copyright and social media icons.
The link groups are defined as arrays of objects within the component.
Platform Links
| Label | Href |
|---|---|
| Corporate | /corporate |
| TMCs | /tmcs |
| Product | /product |
Sources: components/footer.tsx:13-17
Company Links
| Label | Href |
|---|---|
| About us | /about |
| Contact | /contact |
Sources: components/footer.tsx:19-22
Legal Links
| Label | Href |
|---|---|
| Privacy Policy | /policy/privacy |
| Cookies Policy | /policy/cookies |
Sources: components/footer.tsx:24-27
The diagram below shows the high-level structure of the footer content.
This diagram outlines the main content blocks within the footer component.
Sources: components/footer.tsx:32-132
Contact and Social Information
The footer prominently displays contact information and links to social media profiles.
- Email:
info@grapevine.travel - Address: Soho Works White City, 17 Top Wood Lane, London, W12 7RR
- Social:
- LinkedIn:
https://www.linkedin.com/company/grapevinetravel - X (Twitter):
https://x.com/grapevine_trvl
- LinkedIn:
Sources: components/footer.tsx:55-70, components/footer.tsx:135-152
Conditional Rendering
The footer includes a "Sources Section" that is only rendered on the home page. This is controlled by checking if the current pathname is equal to /.
// components/footer.tsx:10, 155-163
const pathname = usePathname();
const isHomePage = pathname === "/";
// ...
{isHomePage && (
<div className="border-border-navy-subtle mt-8 border-t pt-6 md:mt-10 md:pt-8">
{/* ... content ... */}
</div>
)}
This demonstrates conditional rendering based on the current route.
Sources: components/footer.tsx:10, components/footer.tsx:155-163
Styling and Theming
Both the Header and Footer are styled using Tailwind CSS. The colors are sourced from a set of CSS custom properties defined in app/globals.css, which creates a consistent theme.
- The Header uses
bg-navyfor its background. - The Footer also uses
bg-navyfor its background, withtext-lightfor text andtext-primaryfor headings and highlights.
Key theme colors used:
--color-primary:#1980ef--color-navy:#0c0e2d--color-light:#f3f7fc
Sources: app/globals.css:5, app/globals.css:10-11, components/header.tsx:57, components/footer.tsx:30
SEO Integration
The RootLayout where the Header and Footer are placed also handles the injection of site-wide JSON-LD schema for SEO. It calls generateOrganizationSchema from lib/seo.ts and embeds the result in the document's <head>. This provides search engines with structured data about the organization.
Sources: app/layout.tsx:139-141, lib/seo.ts:71-89