Skip to main content
Glama
contact-split-image-locations.svelte7.24 kB
<!-- Last updated: 2025-11-06T05:40:53.463Z --> <!-- @description: A contact section with a form on one side and office locations with an image on the other. Based on Tailwind UI. @props: title: string - Main title for the contact section. description: string - Introductory paragraph. imageUrl: string - URL for the image displayed above office locations. imageAlt: string - Alt text for the image. offices: Array<{ city: string, addressLines: string[] }> - Array of office location objects. formFields: Array<{ id: string, name: string, label: string, type: string, autocomplete?: string, isTextarea?: boolean, rows?: number, colSpan?: number }> - Configuration for form fields. agreementText: string - Text for the privacy policy agreement, can include HTML for links. submitButtonText: string - Text for the submit button. @theme_vars: --theme-bg-base (bg-white) --theme-bg-alt (bg-gray-50 for image background) --theme-text-base (text-gray-900) --theme-text-muted (text-gray-600) --theme-primary (text-indigo-600, bg-indigo-600) --theme-primary-hover (hover:bg-indigo-500) --theme-input-border (ring-gray-300) --theme-input-focus-ring (focus:ring-indigo-600) --theme-border-radius-md (rounded-md) --theme-switch-bg-enabled (bg-indigo-600) --theme-switch-bg-disabled (bg-gray-200) --theme-switch-thumb-bg (bg-white) --> <script lang="ts"> export let title: string = "Let's work together"; export let description: string = "Proin volutpat consequat porttitor cras nullam gravida at orci molestie a eu arcu sed ut tincidunt magna."; export let imageUrl: string = "https://images.unsplash.com/photo-1559136555-9303baea8ebd?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&crop=focalpoint&fp-x=.4&w=2560&h=3413&&q=80"; export let imageAlt: string = "Office interior"; export let offices = [ { city: "Los Angeles", addressLines: ["4556 Brendan Ferry", "Los Angeles, CA 90210"] }, { city: "New York", addressLines: ["886 Walter Street", "New York, NY 12345"] }, { city: "Toronto", addressLines: ["7363 Cynthia Pass", "Toronto, ON N3Y 4H8"] }, { city: "Chicago", addressLines: ["726 Mavis Island", "Chicago, IL 60601"] }, ]; export let formFields = [ { id: "first-name", name: "first-name", label: "First name", type: "text", autocomplete: "given-name" }, { id: "last-name", name: "last-name", label: "Last name", type: "text", autocomplete: "family-name" }, { id: "email", name: "email", label: "Email", type: "email", autocomplete: "email", colSpan: 2 }, { id: "company", name: "company", label: "Company", type: "text", autocomplete: "organization", colSpan: 2 }, { id: "phone", name: "phone", label: "Phone", type: "tel", autocomplete: "tel", colSpan: 2, optional: true }, { id: "message", name: "message", label: "How can we help you?", type: "text", isTextarea: true, rows: 4, colSpan: 2, maxLength: 500 }, ]; export let agreementText: string = ""; // Not present in this specific Tailwind UI example, but can be added export let submitButtonText: string = "Send message"; let formData: { [key: string]: string } = {}; formFields.forEach(field => formData[field.id] = ""); function handleSubmit() { console.log("Form submitted:", formData); } </script> <div class="relative bg-theme-bg-base"> <div class="lg:absolute lg:inset-0 lg:left-1/2"> <img class="h-64 w-full bg-gray-50 object-cover sm:h-80 lg:absolute lg:h-full" src={imageUrl} alt={imageAlt}> {/* Themeable bg-theme-bg-alt */} </div> <div class="pt-16 pb-24 sm:pt-24 sm:pb-32 lg:mx-auto lg:grid lg:max-w-7xl lg:grid-cols-2 lg:pt-32"> <div class="px-6 lg:px-8"> <div class="mx-auto max-w-xl lg:mx-0 lg:max-w-lg"> <h2 class="text-4xl font-semibold tracking-tight text-pretty text-gray-900 sm:text-5xl">{title}</h2> {/* Themeable text-theme-text-base */} <p class="mt-2 text-lg/8 text-gray-600">{description}</p> {/* Themeable text-theme-text-muted */} <form on:submit|preventDefault={handleSubmit} class="mt-16"> <div class="grid grid-cols-1 gap-x-8 gap-y-6 sm:grid-cols-2"> {#each formFields as field} <div class="{field.colSpan === 2 ? 'sm:col-span-2' : ''}"> <div class="flex justify-between text-sm/6"> <label for={field.id} class="block font-semibold text-gray-900">{field.label}</label> {/* Themeable text-theme-text-base */} {#if field.optional} <p id="{field.id}-description" class="text-gray-400">Optional</p> {/* Themeable text-theme-text-muted */} {/if} {#if field.maxLength} <p id="{field.id}-description" class="text-gray-400">Max {field.maxLength} characters</p> {/* Themeable text-theme-text-muted */} {/if} </div> <div class="mt-2.5"> {#if field.isTextarea} <textarea name={field.name} id={field.id} rows={field.rows || 4} bind:value={formData[field.id]} aria-describedby={field.optional || field.maxLength ? `${field.id}-description` : undefined} class="block w-full rounded-md bg-white px-3.5 py-2 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600" ></textarea> {/* Themeable input styles */} {:else} <input type={field.type} name={field.name} id={field.id} autocomplete={field.autocomplete || ''} bind:value={formData[field.id]} aria-describedby={field.optional || field.maxLength ? `${field.id}-description` : undefined} class="block w-full rounded-md bg-white px-3.5 py-2 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600" > {/* Themeable input styles */} {/if} </div> </div> {/each} {#if agreementText} <fieldset class="sm:col-span-2"> <!-- Agreement switch can be added here if needed, similar to contact-simple-bg-pattern.svelte --> </fieldset> {/if} </div> <div class="mt-10 flex justify-end border-t border-gray-900/10 pt-8"> {/* Themeable border-theme-border-color */} <button type="submit" class="rounded-md bg-indigo-600 px-3.5 py-2.5 text-center text-sm font-semibold text-white shadow-xs hover:bg-indigo-500 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">{submitButtonText}</button> {/* Themeable button */} </div> </form> </div> </div> </div> </div>

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/CaullenOmdahl/Tailwind-Svelte-Assistant'

If you have feedback or need assistance with the MCP directory API, please join our Discord server