Contact section in two intro-column rows: department cards with mailto and tel links, then office cards with street addresses. Built from Section, Card and DescriptionList with Orbcore sample details.
import {
DescriptionList,
DescriptionListDetails,
DescriptionListItem,
DescriptionListTerm,
} from "@/components/editorial/description-list"
import {
Feature,
FeatureGroup,
} from "@/components/editorial/features"
import { Heading } from "@/components/editorial/heading"
import {
Section,
SectionColumns,
SectionContent,
SectionDescription,
SectionHeader,
SectionTitleGroup,
} from "@/components/editorial/section"
import {
Card,
CardContent,
CardHeader,
CardTitle,
} from "@/components/ui/card"
// The copy: change text here, not in the markup.
const COPY = {
title: "Get in touch",
body: "One address per question, so the right people read it first. Replies come within one working day.",
emailTerm: "Email",
phoneTerm: "Phone number",
} as const
const LOCATIONS = {
title: "Locations",
body: "Four studios in four time zones. Visits are by appointment; write to the studio first.",
} as const
const DEPARTMENTS = [
{
name: "Collaborate",
email: "collaborate@orbcore.example",
phone: "+1 (555) 905-2345",
},
{ name: "Press", email: "press@orbcore.example", phone: "+1 (555) 905-3456" },
{
name: "Join our team",
email: "careers@orbcore.example",
phone: "+1 (555) 905-4567",
},
{
name: "Say hello",
email: "hello@orbcore.example",
phone: "+1 (555) 905-5678",
},
] as const
const OFFICES = [
{ name: "Portland", address: ["301 Meridian Way", "Portland, OR 97209"] },
{ name: "Austin", address: ["1450 Halo Street", "Austin, TX 78702"] },
{ name: "Halifax", address: ["62 Eclipse Avenue", "Halifax, NS B3J 1A1"] },
{ name: "Edinburgh", address: ["9 Starling Close", "Edinburgh EH1 2AB"] },
] as const
// A tel: link carries only the digits and the leading plus.
const tel = (phone: string) => `tel:${phone.replace(/[^\d+]/g, "")}`
export default function ContactOffices01() {
return (
<Section>
<SectionContent>
<section>
<SectionColumns variant="intro">
<SectionHeader size="sm">
<SectionTitleGroup>
<Heading>{COPY.title}</Heading>
</SectionTitleGroup>
<SectionDescription>{COPY.body}</SectionDescription>
</SectionHeader>
<FeatureGroup cols={2} gap="sm" className="@sm:grid-cols-2">
{DEPARTMENTS.map((department) => (
<Feature key={department.name}>
<Card>
<CardHeader>
<CardTitle role="heading" aria-level={3}>
{department.name}
</CardTitle>
</CardHeader>
<CardContent>
<DescriptionList className="gap-1">
<DescriptionListItem className="justify-start">
<DescriptionListTerm className="sr-only">
{COPY.emailTerm}
</DescriptionListTerm>
<DescriptionListDetails>
<a
href={`mailto:${department.email}`}
className="font-semibold underline-offset-4 hover:underline"
>
{department.email}
</a>
</DescriptionListDetails>
</DescriptionListItem>
<DescriptionListItem className="justify-start">
<DescriptionListTerm className="sr-only">
{COPY.phoneTerm}
</DescriptionListTerm>
<DescriptionListDetails className="text-muted-foreground">
<a
href={tel(department.phone)}
className="underline-offset-4 hover:underline"
>
{department.phone}
</a>
</DescriptionListDetails>
</DescriptionListItem>
</DescriptionList>
</CardContent>
</Card>
</Feature>
))}
</FeatureGroup>
</SectionColumns>
</section>
<section>
<SectionColumns variant="intro">
<SectionHeader size="sm">
<SectionTitleGroup>
<Heading>{LOCATIONS.title}</Heading>
</SectionTitleGroup>
<SectionDescription>{LOCATIONS.body}</SectionDescription>
</SectionHeader>
<FeatureGroup cols={2} gap="sm" className="@sm:grid-cols-2">
{OFFICES.map((office) => (
<Feature key={office.name}>
<Card>
<CardHeader>
<CardTitle role="heading" aria-level={3}>
{office.name}
</CardTitle>
</CardHeader>
<CardContent>
<address className="grid gap-1 text-sm/6 text-muted-foreground not-italic">
{office.address.map((line) => (
<p key={line}>{line}</p>
))}
</address>
</CardContent>
</Card>
</Feature>
))}
</FeatureGroup>
</SectionColumns>
</section>
</SectionContent>
</Section>
)
}
pnpm dlx shadcn add @01orbital/contact-offices-01npx shadcn add @01orbital/contact-offices-01yarn shadcn add @01orbital/contact-offices-01bunx --bun shadcn add @01orbital/contact-offices-01Free under the MIT license. Add the @01orbital registry to components.json once (install guide), then run the command.
It lands at components/blocks/contact/contact-offices-01/index.tsx, as source you own and edit.
import ContactOffices01 from "@/components/blocks/contact/contact-offices-01"
export default function Example() {
return <ContactOffices01 />
}Registry pieces it installs with it:
Newsletter Card with Lagoon Painting
Newsletter sign-up card with a centered Instrument Serif heading, the Field Notes blurb, an email NewsletterForm, and an italic serif issue number beside a LagoonBackdrop painting.
Contact Sales Form
Contact sales form in one narrow column: first and last name, optional company, email, country select with phone, message and a privacy consent checkbox. Validated with react-hook-form and zod.