{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"contact-03","type":"registry:component","title":"Contact 03","description":"A comprehensive team-focused contact component with contact methods, team member showcases, testimonial, and detailed form. Features contact method cards with icons, team member profiles with avatars and roles, customer testimonial with rating, sticky form layout, and project budget selection. Perfect for service-based businesses, agencies, and companies requiring personal connection with potential clients through team visibility.","dependencies":["lucide-react","react-hook-form","@hookform/resolvers","zod"],"registryDependencies":["avatar","badge","button","card","input","textarea","form"],"files":[{"path":"src/registry/blocks/marketing/landing-pages/contact/contact-03.tsx","content":"\"use client\";\n\nimport { zodResolver } from \"@hookform/resolvers/zod\";\nimport {\n  Clock,\n  type LucideIcon,\n  Mail,\n  MapPin,\n  Phone,\n  Quote,\n  Star,\n} from \"lucide-react\";\nimport { useForm } from \"react-hook-form\";\nimport { z } from \"zod\";\nimport { cn } from \"@/registry/lib/utils\";\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/registry/ui/avatar\";\nimport { Badge } from \"@/registry/ui/badge\";\nimport { Button } from \"@/registry/ui/button\";\nimport { Card, CardContent } from \"@/registry/ui/card\";\nimport {\n  Form,\n  FormControl,\n  FormField,\n  FormItem,\n  FormLabel,\n  FormMessage,\n} from \"@/registry/ui/form\";\nimport { Input } from \"@/registry/ui/input\";\nimport { Textarea } from \"@/registry/ui/textarea\";\n\ninterface ContactMethod {\n  id: string;\n  icon: LucideIcon;\n  title: string;\n  subtitle: string;\n  value: string;\n  color: \"blue\" | \"green\" | \"purple\" | \"orange\";\n}\n\ninterface TeamMember {\n  id: string;\n  name: string;\n  role: string;\n  description: string;\n  avatar: string;\n  fallback: string;\n}\n\ninterface Testimonial {\n  quote: string;\n  author: {\n    name: string;\n    avatar: string;\n    fallback: string;\n  };\n  rating: number;\n}\n\ninterface BudgetOption {\n  value: string;\n  label: string;\n}\n\nconst formSchema = z.object({\n  firstName: z.string().min(2, \"First name must be at least 2 characters\"),\n  lastName: z.string().min(2, \"Last name must be at least 2 characters\"),\n  email: z.string().email(\"Please enter a valid email address\"),\n  company: z.string().optional(),\n  budget: z.string().optional(),\n  message: z.string().min(10, \"Message must be at least 10 characters\"),\n});\n\ntype FormValues = z.infer<typeof formSchema>;\n\nexport interface Contact03Props {\n  className?: string;\n}\n\nconst content: {\n  header: {\n    badge: {\n      text: string;\n      variant: \"outline\";\n      className: string;\n    };\n    title: string;\n    description: string;\n  };\n  maxWidth: string;\n  sectionPadding: string;\n  contactMethods: ContactMethod[];\n  teamSection: {\n    title: string;\n    members: TeamMember[];\n  };\n  testimonial: Testimonial;\n  form: {\n    title: string;\n    description: string;\n    buttonText: string;\n    disclaimer: string;\n    showCompanyField: boolean;\n    showBudgetField: boolean;\n    budgetOptions: BudgetOption[];\n  };\n} = {\n  header: {\n    badge: {\n      text: \"Let's Connect\",\n      variant: \"outline\",\n      className: \"bg-primary/5 text-primary border-primary/20\",\n    },\n    title: \"Get in Touch with Our Team\",\n    description:\n      \"We're here to help you succeed. Reach out to our friendly team and we'll get back to you as soon as possible.\",\n  },\n  maxWidth: \"max-w-7xl\",\n  sectionPadding: \"py-16 px-4\",\n  contactMethods: [\n    {\n      id: \"phone\",\n      icon: Phone,\n      title: \"Call Us\",\n      subtitle: \"Mon-Fri 9am-6pm\",\n      value: \"+1 (555) 123-4567\",\n      color: \"blue\",\n    },\n    {\n      id: \"email\",\n      icon: Mail,\n      title: \"Email Us\",\n      subtitle: \"We'll respond quickly\",\n      value: \"hello@company.com\",\n      color: \"green\",\n    },\n    {\n      id: \"location\",\n      icon: MapPin,\n      title: \"Visit Us\",\n      subtitle: \"Our office location\",\n      value: \"San Francisco, CA\",\n      color: \"purple\",\n    },\n    {\n      id: \"response-time\",\n      icon: Clock,\n      title: \"Response Time\",\n      subtitle: \"Average response\",\n      value: \"< 2 hours\",\n      color: \"orange\",\n    },\n  ],\n  teamSection: {\n    title: \"Meet Our Team\",\n    members: [\n      {\n        id: \"sarah-johnson\",\n        name: \"Sarah Johnson\",\n        role: \"Customer Success\",\n        description: \"Specializes in onboarding and customer support\",\n        avatar: \"https://randomuser.me/api/portraits/women/1.jpg\",\n        fallback: \"SJ\",\n      },\n      {\n        id: \"mike-kim\",\n        name: \"Mike Kim\",\n        role: \"Technical Lead\",\n        description: \"Handles technical questions and integrations\",\n        avatar: \"https://randomuser.me/api/portraits/men/1.jpg\",\n        fallback: \"MK\",\n      },\n    ],\n  },\n  testimonial: {\n    quote:\n      \"The support team is incredibly responsive and helpful. They went above and beyond to help us solve our integration challenges.\",\n    author: {\n      name: \"Alex Lee\",\n      avatar: \"https://randomuser.me/api/portraits/men/2.jpg\",\n      fallback: \"AL\",\n    },\n    rating: 5,\n  },\n  form: {\n    title: \"Send us a Message\",\n    description: \"We'll get back to you within 24 hours\",\n    buttonText: \"Send Message\",\n    disclaimer:\n      \"We respect your privacy and will never share your information.\",\n    showCompanyField: true,\n    showBudgetField: true,\n    budgetOptions: [\n      { value: \"\", label: \"Select budget range\" },\n      { value: \"under-10k\", label: \"Under $10,000\" },\n      { value: \"10k-25k\", label: \"$10,000 - $25,000\" },\n      { value: \"25k-50k\", label: \"$25,000 - $50,000\" },\n      { value: \"50k-100k\", label: \"$50,000 - $100,000\" },\n      { value: \"over-100k\", label: \"Over $100,000\" },\n    ],\n  },\n};\n\nexport function Contact03({ className }: Contact03Props) {\n  const form = useForm<FormValues>({\n    resolver: zodResolver(formSchema),\n    defaultValues: {\n      firstName: \"\",\n      lastName: \"\",\n      email: \"\",\n      company: \"\",\n      budget: \"\",\n      message: \"\",\n    },\n  });\n\n  const onSubmit = (values: FormValues) => {\n    console.log(\"Form submitted:\", values);\n    // Handle form submission here\n    form.reset();\n  };\n\n  const getIconBackground = (color: ContactMethod[\"color\"]) => {\n    const backgrounds = {\n      blue: \"bg-blue-100 dark:bg-blue-900/30\",\n      green: \"bg-green-100 dark:bg-green-900/30\",\n      purple: \"bg-purple-100 dark:bg-purple-900/30\",\n      orange: \"bg-orange-100 dark:bg-orange-900/30\",\n    };\n    return backgrounds[color];\n  };\n\n  const getIconColor = (color: ContactMethod[\"color\"]) => {\n    const colors = {\n      blue: \"text-blue-600 dark:text-blue-400\",\n      green: \"text-green-600 dark:text-green-400\",\n      purple: \"text-purple-600 dark:text-purple-400\",\n      orange: \"text-orange-600 dark:text-orange-400\",\n    };\n    return colors[color];\n  };\n\n  return (\n    <section\n      className={cn(content.sectionPadding, className)}\n      data-testid=\"contact-03\"\n    >\n      <div className={cn(content.maxWidth, \"mx-auto\")}>\n        <div\n          className=\"grid lg:grid-cols-2 gap-12 items-start md:gap-16 lg:gap-24\"\n          data-testid=\"contact-grid\"\n        >\n          {/* Left Side - Contact Info & Team */}\n          <div className=\"space-y-8\" data-testid=\"contact-info-side\">\n            {/* Header */}\n            <div className=\"space-y-4\" data-testid=\"header-section\">\n              <Badge\n                variant={content.header.badge.variant}\n                className={content.header.badge.className}\n                data-testid=\"header-badge\"\n              >\n                {content.header.badge.text}\n              </Badge>\n              <h2\n                className=\"text-3xl md:text-4xl font-bold\"\n                data-testid=\"header-title\"\n              >\n                {content.header.title}\n              </h2>\n              <p\n                className=\"text-lg text-muted-foreground\"\n                data-testid=\"header-description\"\n              >\n                {content.header.description}\n              </p>\n            </div>\n\n            {/* Contact Methods */}\n            <div\n              className=\"grid sm:grid-cols-2 gap-4\"\n              data-testid=\"contact-methods-grid\"\n            >\n              {content.contactMethods.map((method) => {\n                const IconComponent = method.icon;\n                return (\n                  <Card\n                    key={method.id}\n                    className=\"bg-card border-border\"\n                    data-testid={`contact-method-${method.id}`}\n                  >\n                    <CardContent>\n                      <div className=\"flex items-center gap-3 mb-3\">\n                        <div\n                          className={cn(\n                            \"w-10 h-10 rounded-lg flex items-center justify-center\",\n                            getIconBackground(method.color),\n                          )}\n                          data-testid={`contact-method-icon-${method.id}`}\n                        >\n                          <IconComponent\n                            className={cn(\n                              \"h-5 w-5\",\n                              getIconColor(method.color),\n                            )}\n                          />\n                        </div>\n                        <div>\n                          <p\n                            className=\"font-medium\"\n                            data-testid={`contact-method-title-${method.id}`}\n                          >\n                            {method.title}\n                          </p>\n                          <p\n                            className=\"text-sm text-muted-foreground\"\n                            data-testid={`contact-method-subtitle-${method.id}`}\n                          >\n                            {method.subtitle}\n                          </p>\n                        </div>\n                      </div>\n                      <p\n                        className=\"text-sm font-medium\"\n                        data-testid={`contact-method-value-${method.id}`}\n                      >\n                        {method.value}\n                      </p>\n                    </CardContent>\n                  </Card>\n                );\n              })}\n            </div>\n\n            {/* Team Members */}\n            <div className=\"space-y-4\" data-testid=\"team-section\">\n              <h3 className=\"text-xl font-semibold\" data-testid=\"team-title\">\n                {content.teamSection.title}\n              </h3>\n              <div className=\"space-y-4\" data-testid=\"team-members-list\">\n                {content.teamSection.members.map((member) => (\n                  <Card\n                    key={member.id}\n                    className=\"bg-card border-border\"\n                    data-testid={`team-member-${member.id}`}\n                  >\n                    <CardContent>\n                      <div className=\"flex items-center gap-4\">\n                        <Avatar\n                          className=\"h-12 w-12\"\n                          data-testid={`team-member-avatar-${member.id}`}\n                        >\n                          <AvatarImage src={member.avatar} />\n                          <AvatarFallback>{member.fallback}</AvatarFallback>\n                        </Avatar>\n                        <div className=\"flex-1\">\n                          <div className=\"flex items-center gap-2 mb-1\">\n                            <p\n                              className=\"font-medium\"\n                              data-testid={`team-member-name-${member.id}`}\n                            >\n                              {member.name}\n                            </p>\n                            <Badge\n                              variant=\"secondary\"\n                              className=\"text-xs\"\n                              data-testid={`team-member-role-${member.id}`}\n                            >\n                              {member.role}\n                            </Badge>\n                          </div>\n                          <p\n                            className=\"text-sm text-muted-foreground\"\n                            data-testid={`team-member-description-${member.id}`}\n                          >\n                            {member.description}\n                          </p>\n                        </div>\n                      </div>\n                    </CardContent>\n                  </Card>\n                ))}\n              </div>\n            </div>\n\n            {/* Testimonial */}\n            <Card\n              className=\"bg-primary text-primary-foreground\"\n              data-testid=\"testimonial-section\"\n            >\n              <CardContent>\n                <Quote\n                  className=\"h-8 w-8 text-primary-foreground/30 mb-3\"\n                  data-testid=\"testimonial-quote-icon\"\n                />\n                <p className=\"text-sm mb-4\" data-testid=\"testimonial-quote\">\n                  {content.testimonial.quote}\n                </p>\n                <div\n                  className=\"flex items-center gap-3\"\n                  data-testid=\"testimonial-author\"\n                >\n                  <Avatar\n                    className=\"h-8 w-8\"\n                    data-testid=\"testimonial-author-avatar\"\n                  >\n                    <AvatarImage src={content.testimonial.author.avatar} />\n                    <AvatarFallback>\n                      {content.testimonial.author.fallback}\n                    </AvatarFallback>\n                  </Avatar>\n                  <div>\n                    <p\n                      className=\"text-sm font-medium\"\n                      data-testid=\"testimonial-author-name\"\n                    >\n                      {content.testimonial.author.name}\n                    </p>\n                    <div\n                      className=\"flex items-center gap-1\"\n                      data-testid=\"testimonial-rating\"\n                    >\n                      {Array.from({ length: content.testimonial.rating }).map(\n                        (_, i) => (\n                          <Star\n                            key={i}\n                            className=\"h-3 w-3 fill-current\"\n                            data-testid={`testimonial-star-${i + 1}`}\n                          />\n                        ),\n                      )}\n                    </div>\n                  </div>\n                </div>\n              </CardContent>\n            </Card>\n          </div>\n\n          {/* Right Side - Contact Form */}\n          <div className=\"lg:sticky lg:top-8\" data-testid=\"contact-form-side\">\n            <Card\n              className=\"bg-card border-border shadow-xl\"\n              data-testid=\"contact-form-card\"\n            >\n              <CardContent className=\"p-8\">\n                <div className=\"space-y-6\">\n                  <div\n                    className=\"text-center space-y-2\"\n                    data-testid=\"form-header\"\n                  >\n                    <h3 className=\"text-2xl font-bold\" data-testid=\"form-title\">\n                      {content.form.title}\n                    </h3>\n                    <p\n                      className=\"text-muted-foreground\"\n                      data-testid=\"form-description\"\n                    >\n                      {content.form.description}\n                    </p>\n                  </div>\n\n                  <Form {...form}>\n                    <form\n                      onSubmit={form.handleSubmit(onSubmit)}\n                      className=\"space-y-4\"\n                      data-testid=\"contact-form\"\n                    >\n                      <div\n                        className=\"grid grid-cols-2 gap-4\"\n                        data-testid=\"form-grid-fields\"\n                      >\n                        <FormField\n                          control={form.control}\n                          name=\"firstName\"\n                          render={({ field }) => (\n                            <FormItem data-testid=\"form-field-firstName\">\n                              <FormLabel data-testid=\"label-firstName\">\n                                First Name *\n                              </FormLabel>\n                              <FormControl>\n                                <Input\n                                  placeholder=\"John\"\n                                  className=\"bg-background border-border\"\n                                  data-testid=\"input-firstName\"\n                                  {...field}\n                                />\n                              </FormControl>\n                              <FormMessage />\n                            </FormItem>\n                          )}\n                        />\n                        <FormField\n                          control={form.control}\n                          name=\"lastName\"\n                          render={({ field }) => (\n                            <FormItem data-testid=\"form-field-lastName\">\n                              <FormLabel data-testid=\"label-lastName\">\n                                Last Name *\n                              </FormLabel>\n                              <FormControl>\n                                <Input\n                                  placeholder=\"Doe\"\n                                  className=\"bg-background border-border\"\n                                  data-testid=\"input-lastName\"\n                                  {...field}\n                                />\n                              </FormControl>\n                              <FormMessage />\n                            </FormItem>\n                          )}\n                        />\n                      </div>\n\n                      <FormField\n                        control={form.control}\n                        name=\"email\"\n                        render={({ field }) => (\n                          <FormItem data-testid=\"form-field-email\">\n                            <FormLabel data-testid=\"label-email\">\n                              Email Address *\n                            </FormLabel>\n                            <FormControl>\n                              <Input\n                                type=\"email\"\n                                placeholder=\"john@example.com\"\n                                className=\"bg-background border-border\"\n                                data-testid=\"input-email\"\n                                {...field}\n                              />\n                            </FormControl>\n                            <FormMessage />\n                          </FormItem>\n                        )}\n                      />\n\n                      {content.form.showCompanyField && (\n                        <FormField\n                          control={form.control}\n                          name=\"company\"\n                          render={({ field }) => (\n                            <FormItem data-testid=\"form-field-company\">\n                              <FormLabel data-testid=\"label-company\">\n                                Company\n                              </FormLabel>\n                              <FormControl>\n                                <Input\n                                  placeholder=\"Your company name\"\n                                  className=\"bg-background border-border\"\n                                  data-testid=\"input-company\"\n                                  {...field}\n                                />\n                              </FormControl>\n                              <FormMessage />\n                            </FormItem>\n                          )}\n                        />\n                      )}\n\n                      {content.form.showBudgetField && (\n                        <FormField\n                          control={form.control}\n                          name=\"budget\"\n                          render={({ field }) => (\n                            <FormItem data-testid=\"form-field-budget\">\n                              <FormLabel data-testid=\"label-budget\">\n                                Project Budget\n                              </FormLabel>\n                              <FormControl>\n                                <select\n                                  className=\"w-full h-10 px-3 bg-background border border-border rounded-md text-sm\"\n                                  data-testid=\"select-budget\"\n                                  {...field}\n                                >\n                                  {content.form.budgetOptions.map((option) => (\n                                    <option\n                                      key={option.value}\n                                      value={option.value}\n                                    >\n                                      {option.label}\n                                    </option>\n                                  ))}\n                                </select>\n                              </FormControl>\n                              <FormMessage />\n                            </FormItem>\n                          )}\n                        />\n                      )}\n\n                      <FormField\n                        control={form.control}\n                        name=\"message\"\n                        render={({ field }) => (\n                          <FormItem data-testid=\"form-field-message\">\n                            <FormLabel data-testid=\"label-message\">\n                              Project Details *\n                            </FormLabel>\n                            <FormControl>\n                              <Textarea\n                                placeholder=\"Tell us about your project, timeline, and any specific requirements...\"\n                                className=\"bg-background border-border min-h-[100px]\"\n                                data-testid=\"textarea-message\"\n                                {...field}\n                              />\n                            </FormControl>\n                            <FormMessage />\n                          </FormItem>\n                        )}\n                      />\n\n                      <Button\n                        type=\"submit\"\n                        className=\"w-full\"\n                        size=\"lg\"\n                        disabled={form.formState.isSubmitting}\n                        data-testid=\"form-submit-button\"\n                      >\n                        {form.formState.isSubmitting\n                          ? \"Submitting...\"\n                          : content.form.buttonText}\n                      </Button>\n\n                      <p\n                        className=\"text-xs text-muted-foreground text-center\"\n                        data-testid=\"form-disclaimer\"\n                      >\n                        {content.form.disclaimer}\n                      </p>\n                    </form>\n                  </Form>\n                </div>\n              </CardContent>\n            </Card>\n          </div>\n        </div>\n      </div>\n    </section>\n  );\n}\n","type":"registry:component"},{"path":"src/registry/lib/utils.ts","content":"import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}\n","type":"registry:lib"}]}