Interactive Components
Relevant source files
The following files were used as context for generating this wiki page:
The Grapevine website utilizes several interactive components built with React and TypeScript to engage users, capture data, and dynamically display content. These components are primarily client-side ("use client") and leverage state management, form validation, and API communication to provide a responsive user experience. Key examples include the ContactForm for booking discovery calls, the NewsletterSignup for marketing engagement, and the Features component for showcasing product capabilities in a dynamic carousel.
These components are central to the website's lead generation and user engagement strategy. They are designed with clear user feedback mechanisms, including loading states, success messages, and validation errors, and often incorporate animations using framer-motion to enhance the user interface.
Contact Form
The ContactForm component is a comprehensive form used on the /contact page to allow potential clients to book a discovery call. It handles user input, validation, and submission to a backend API.
Sources: components/contact-form.tsx, app/contact/page.tsx
State Management
The form's state is managed using React's useState hook to track form data, validation errors, submission status, and message character count.
formData: An object of typeFormDatathat stores the values of all input fields.errors: An object of typeFormErrorsthat stores validation error messages for each field.isSubmitted: A boolean flag to control the visibility of the success message.isLoading: A boolean flag to show a loading state on the submit button during API calls.charCount: A number to track the length of the user's message.
Sources: components/contact-form.tsx:39-50
Data Structures
The component defines two primary interfaces for managing form state and errors.
FormData Interface
| Field | Type | Description |
|---|---|---|
fullName | string | The user's full name. |
workEmail | string | The user's work email address. |
iAmA | string | User's self-identified role (TMC, Corporate, etc.). |
companyName | string | The user's company name. |
role | string | The user's job title or role. |
message | string | An optional message from the user. |
Sources: components/contact-form.tsx:18-25
FormErrors Interface
This interface mirrors the FormData structure, but all fields are optional strings used to hold validation error messages.
| Field | Type | Description |
|---|---|---|
fullName | string? | Error message for the full name field. |
workEmail | string? | Error message for the work email field. |
iAmA | string? | Error message for the selection field. |
companyName | string? | Error message for the company name field. |
role | string? | Error message for the role field. |
message | string? | Error message for the message field. |
Sources: components/contact-form.tsx:27-35
Validation and Submission Flow
The form submission process involves client-side validation before sending data to the backend.
- The user fills out the form and clicks the "Book discovery call" button.
- The
handleSubmitfunction is triggered, which callsvalidateForm. validateFormchecks for required fields (fullName,workEmail,companyName,iAmA,role) and validates the email format using a regex.- If validation fails, the
errorsstate is updated, and error messages are displayed. - If validation succeeds,
isLoadingis set totrue, and aPOSTrequest is sent to the/api/contactendpoint with theformData. - Upon a successful API response, the form is reset, and
isSubmittedis set totrueto display a success message. - If the API call fails, an alert is shown to the user.
The diagram below illustrates the form submission logic.
Sources: components/contact-form.tsx:58-124
API Interaction
The handleSubmit function orchestrates the API call to the backend.
This sequence diagram shows the interaction between the user, the contact form component, and the API.
Sources: components/contact-form.tsx:94-105
Newsletter Signup
The NewsletterSignup component is a simpler form designed to capture user emails for a mailing list. It is used on pages like /resources.
Sources: components/newsletter-signup.tsx, app/resources/page.tsx:49
State and Submission
This component manages three state variables:
email: Stores the user-entered email address.status: Tracks the submission status ("idle","loading","success","error").message: Stores the feedback message to display to the user.
The handleSubmit function prevents default form submission, sets the status to "loading", and sends a POST request to /api/subscribe. The response from the API dictates the final status and message shown to the user. The privacy policy notes that the third-party service Mailchimp is used for newsletters.
Sources: components/newsletter-signup.tsx:16-22, app/policy/privacy/page.tsx:216-219
API Interaction
The sequence diagram below details the newsletter subscription process.
Features Carousel
The Features component is an interactive element used to display a series of product features. It has distinct behaviors for mobile and desktop views to optimize the user experience.
Sources: components/features.tsx
Interactivity and State
The component's interactivity is driven by several state variables and event handlers:
activeFeatureIndex: A number that determines which feature is currently displayed.isPaused: A boolean to pause the auto-play functionality when the user interacts with the component.isInView: A boolean, updated via anIntersectionObserver, that starts the auto-play only when the component is visible on the screen.- Auto-play: An interval timer automatically cycles through features every 4 seconds (
autoPlayInterval). This is paused for 10 seconds upon user interaction. - Desktop Interaction: On larger screens, users can click on a feature in the list to make it active.
- Mobile Interaction: On smaller screens, the features are displayed in a swipeable carousel. Touch events (
onTouchStart,onTouchMove,onTouchEnd) are used to handle swiping between features.
Sources: components/features.tsx:49-56, 70-84, 110-125
Data Structure
The content for the carousel is passed via the steps prop, which is an array of objects conforming to the FeatureStep interface.
FeatureStep Interface
| Field | Type | Description |
|---|---|---|
title | string | The title of the feature. |
description | string | A brief description of the feature. |
image | string | The path to the feature's image. |
icon | IconName | The name of the Lucide icon to use. |
Sources: components/features.tsx:14-19
Auto-play State Logic
The auto-play functionality is governed by the user's viewport and interactions.
The following state diagram shows the logic for the auto-play timer.
Sources: components/features.tsx:70-98