Contact 01
block marketingTwo-column contact section. Left column has eyebrow, headline, lede, three icon-prefixed contact rows (email / phone / office), and a map placeholder. Right column is a Card-wrapped form (name / email / company / subject Select / message Textarea) that swaps to a success state after submit. Emits "submit" with the form payload.
Also available for React ->Installation
$ pnpm dlx shadcn-vue@latest add https://uipkge.dev/r/vue/contact-01.json$ npx shadcn-vue@latest add https://uipkge.dev/r/vue/contact-01.json$ yarn dlx shadcn-vue@latest add https://uipkge.dev/r/vue/contact-01.json$ bunx shadcn-vue@latest add https://uipkge.dev/r/vue/contact-01.json
Or with the named registry:
npx shadcn-vue@latest add @uipkge/contact-01
Examples
Theming
CSS custom properties referenced in this item. Override any of them in your :root or per-element to retheme.
--success Files (1)
-
app/components/blocks/Contact01.vue 6 kB
<script setup lang="ts"> import { computed, ref } from 'vue' import { CheckCircle2, Mail, MapPin, Phone, Send } from 'lucide-vue-next' import { Button } from '@/components/ui/button' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' import { Textarea } from '@/components/ui/textarea' const name = ref('') const email = ref('') const company = ref('') const subject = ref('sales') const message = ref('') const sent = ref(false) const canSubmit = computed(() => name.value && email.value && message.value) const emit = defineEmits<{ (e: 'submit', payload: { name: string; email: string; company: string; subject: string; message: string }): void }>() function submit() { if (!canSubmit.value) return emit('submit', { name: name.value, email: email.value, company: company.value, subject: subject.value, message: message.value, }) sent.value = true } </script> <template> <section class="bg-background"> <div class="mx-auto max-w-6xl px-6 py-24"> <div class="grid gap-10 lg:grid-cols-2 lg:items-start"> <div class="space-y-6"> <p class="text-primary text-sm font-medium tracking-widest uppercase">Contact</p> <h2 class="text-3xl font-semibold tracking-tight sm:text-4xl">Talk to a human</h2> <p class="text-muted-foreground text-lg"> Tell us a bit about your team and we'll show you how we'd fit. Average reply: 4 hours. </p> <div class="space-y-3 pt-4"> <div class="flex items-center gap-3"> <div class="bg-primary/10 text-primary rounded-lg p-2"> <Mail class="size-4" /> </div> <div> <p class="text-muted-foreground text-xs uppercase">Email</p> <a href="mailto:[email protected]" class="text-sm font-medium hover:underline"> [email protected] </a> </div> </div> <div class="flex items-center gap-3"> <div class="bg-primary/10 text-primary rounded-lg p-2"> <Phone class="size-4" /> </div> <div> <p class="text-muted-foreground text-xs uppercase">Phone</p> <p class="text-sm font-medium">+1 (415) 555-0142</p> </div> </div> <div class="flex items-center gap-3"> <div class="bg-primary/10 text-primary rounded-lg p-2"> <MapPin class="size-4" /> </div> <div> <p class="text-muted-foreground text-xs uppercase">Office</p> <p class="text-sm font-medium">120 Howard St, San Francisco</p> </div> </div> </div> <div class="bg-muted/40 mt-6 flex h-48 items-center justify-center rounded-lg border border-dashed"> <p class="text-muted-foreground text-sm">Map placeholder</p> </div> </div> <Card> <template v-if="!sent"> <CardHeader> <CardTitle>Send us a message</CardTitle> <CardDescription>We reply during business hours (PT)</CardDescription> </CardHeader> <CardContent> <form class="space-y-4" @submit.prevent="submit"> <div class="grid gap-4 sm:grid-cols-2"> <div class="grid gap-2"> <Label for="contact-name">Name</Label> <Input id="contact-name" v-model="name" required /> </div> <div class="grid gap-2"> <Label for="contact-email">Work email</Label> <Input id="contact-email" v-model="email" type="email" required /> </div> </div> <div class="grid gap-2"> <Label for="contact-company">Company</Label> <Input id="contact-company" v-model="company" /> </div> <div class="grid gap-2"> <Label for="contact-subject">I'm interested in</Label> <Select v-model="subject"> <SelectTrigger id="contact-subject"> <SelectValue /> </SelectTrigger> <SelectContent> <SelectItem value="sales">Talking to sales</SelectItem> <SelectItem value="support">Customer support</SelectItem> <SelectItem value="partnership">Partnerships</SelectItem> <SelectItem value="other">Something else</SelectItem> </SelectContent> </Select> </div> <div class="grid gap-2"> <Label for="contact-message">Message</Label> <Textarea id="contact-message" v-model="message" placeholder="How can we help?" required /> </div> <Button type="submit" class="w-full" :disabled="!canSubmit"> Send message <Send class="ml-2 size-4" /> </Button> </form> </CardContent> </template> <template v-else> <CardContent class="space-y-4 pt-8 text-center"> <div class="mx-auto flex size-12 items-center justify-center rounded-full bg-[var(--success)]/10 text-[var(--success)]" > <CheckCircle2 class="size-6" /> </div> <div class="space-y-1"> <h3 class="text-lg font-semibold">Message sent</h3> <p class="text-muted-foreground text-sm">Thanks {{ name }}, we'll be in touch within a few hours.</p> </div> <Button variant="outline" @click="sent = false">Send another</Button> </CardContent> </template> </Card> </div> </div> </section> </template>
Raw manifest: https://uipkge.dev/r/vue/contact-01.json