nyuchimzizi
Mzizi — an open-architecture project of the Bundu Foundation, operated and developed by Nyuchi. Built on the Five African Minerals palette.
Built by Nyuchi Africav4.0.39
Structured address form with street, city, state, postal code, and country fields with African countries prioritized.
No interactive demo is registered for this component yet — the source is shown directly.
"use client"
import * as React from "react"
import { cn } from "@/lib/utils"
import { Input } from "@/components/ui/input"
interface AddressValue {
street: string
city: string
state: string
postalCode: string
country: string
}
interface AddressInputProps {
value?: Partial<AddressValue>
onChange?: (value: AddressValue) => void
className?: string
}
const AFRICAN_COUNTRIES = [
"Zimbabwe",
"South Africa",
"Kenya",
"Nigeria",
"Ghana",
"Tanzania",
"Uganda",
"Ethiopia",
"Rwanda",
"Mozambique",
"Zambia",
"Botswana",
"Namibia",
"Malawi",
"Senegal",
"Cameroon",
"Egypt",
"Morocco",
] as const
const OTHER_COUNTRIES = [
"United Kingdom",
"United States",
"Canada",
"Australia",
"Germany",
"France",
"India",
"Brazil",
"China",
"Japan",
] as const
const DEFAULT_VALUE: AddressValue = {
street: "",
city: "",
state: "",
postalCode: "",
country: "",
}
function AddressInput({ value, onChange, className }: AddressInputProps) {
const address = { ...DEFAULT_VALUE, ...value }
function update(field: keyof AddressValue, v: string) {
onChange?.({ ...address, [field]: v })
}
return (
<div data-slot="address-input" data-portal="https://design.nyuchi.com/components/address-input" className={cn("flex flex-col gap-3", className)}>
<div className="flex flex-col gap-1.5">
<label className="text-sm font-medium">Street address</label>
<Input
value={address.street}
onChange={(e) => update("street", e.target.value)}
placeholder="123 Main Street"
/>
</div>
<div className="grid grid-cols-2 gap-3">
<div className="flex flex-col gap-1.5">
<label className="text-sm font-medium">City</label>
<Input
value={address.city}
onChange={(e) => update("city", e.target.value)}
placeholder="Harare"
/>
</div>
<div className="flex flex-col gap-1.5">
<label className="text-sm font-medium">State / Province</label>
<Input
value={address.state}
onChange={(e) => update("state", e.target.value)}
placeholder="Harare Province"
/>
</div>
</div>
<div className="grid grid-cols-2 gap-3">
<div className="flex flex-col gap-1.5">
<label className="text-sm font-medium">Postal code</label>
<Input
value={address.postalCode}
onChange={(e) => update("postalCode", e.target.value)}
placeholder="00263"
/>
</div>
<div className="flex flex-col gap-1.5">
<label className="text-sm font-medium">Country</label>
<select
value={address.country}
onChange={(e) => update("country", e.target.value)}
aria-label="Country"
className="h-12 w-full rounded-full border border-input bg-input/30 px-3 text-sm transition-colors outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50"
>
<option value="">Select country</option>
<optgroup label="Africa">
{AFRICAN_COUNTRIES.map((c) => (
<option key={c} value={c}>
{c}
</option>
))}
</optgroup>
<optgroup label="Other">
{OTHER_COUNTRIES.map((c) => (
<option key={c} value={c}>
{c}
</option>
))}
</optgroup>
</select>
</div>
</div>
</div>
)
}
export { AddressInput }
export type { AddressInputProps, AddressValue }
The variants, sizes, and props surfaced by the registry. Each is sourced from the Supabase component_docs table.
Hit the registry API live and see the JSON the shadcn CLI consumes when it installs this component.
/api/v1/ui/address-inputnpx shadcn@latest add https://mzizi.dev/api/v1/ui/address-inputcomponents/ui/address-input.tsx