sections
Gradient Border Contact Form
A dark contact / feedback form card whose border is painted with a vivid diagonal purple-to-cyan gradient using the CSS padding-box + border-box background layering trick — two background declarations share the same rule, the first (padding-box) floods the card with var(--background) while the second (border-box) paints the gradient across the full box so only the exposed 2px border strip shows color. The form contains a labeled email input, a labeled message textarea, and a ghost submit button that transitions to a filled primary state on hover. All interactive states — input focus, button focus, button hover — use Bottega contract tokens; focus-visible rings are delivered via var(--ring). No JavaScript, fully server-renderable, keyboard-operable, and compatible with any shadcn theme.
Ported from gharsh11032000 (MIT)
Get in touch
Install
1. Register the namespace (once per project):
// components.json — register the @bottega namespace once
{
"registries": {
"@bottega": { "url": "https://bottega.ariacode.ca/r/{name}.json" }
}
}2. Add the component:
npx shadcn add @bottega/gradient-border-contact-formUsage
<GradientBorderContactForm />Props
| Prop | Type | Default | Description |
|---|---|---|---|
| heading | string | — | Heading shown above the form. |
| emailLabel | string | Company Email | Label for the email / company-email field. |
| emailPlaceholder | string | — | Placeholder for the email input. |
| messageLabel | string | How Can We Help You? | Label for the message textarea. |
| messagePlaceholder | string | — | Placeholder for the message textarea. |
| submitLabel | string | Submit | Label on the submit button. |
| onSubmit | (data: { email: string; message: string; }) => void | — | Called when the form is submitted with the field values. |
| className | string | Additional class names merged onto the root wrapper. |
Source
import type React from "react";
import styles from "./gradient-border-contact-form.module.css";
export type GradientBorderContactFormProps = {
/** Heading shown above the form. */
heading?: string;
/** Label for the email / company-email field. */
emailLabel?: string;
/** Placeholder for the email input. */
emailPlaceholder?: string;
/** Label for the message textarea. */
messageLabel?: string;
/** Placeholder for the message textarea. */
messagePlaceholder?: string;
/** Label on the submit button. */
submitLabel?: string;
/** Called when the form is submitted with the field values. */
onSubmit?: (data: { email: string; message: string }) => void;
/** Additional class names merged onto the root wrapper. */
className?: string;
};
/**
* Gradient-border contact form.
*
* A dark contact/feedback form whose card container uses the
* CSS `padding-box` + `border-box` background trick to paint a
* vivid diagonal gradient (purple → cyan via `--primary` and `--accent`)
* only on the 2px border while the fill stays `--background`.
* Inputs and textarea use a subtle token-based border that highlights
* with `--primary` on focus-visible. The submit button slides from a
* muted ghost state to a filled `--primary-foreground` / `--primary`
* appearance on hover. All interactive states use `:focus-visible`
* rings via `var(--ring)`. No JS — purely static CSS with a real
* `<form>` and server-renderable markup.
*/
export function GradientBorderContactForm({
heading,
emailLabel = "Company Email",
emailPlaceholder,
messageLabel = "How Can We Help You?",
messagePlaceholder,
submitLabel = "Submit",
onSubmit,
className = "",
}: GradientBorderContactFormProps) {
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
if (!onSubmit) return;
const fd = new FormData(e.currentTarget);
onSubmit({
email: (fd.get("email") as string) ?? "",
message: (fd.get("message") as string) ?? "",
});
}
return (
<div className={[styles.container, className].filter(Boolean).join(" ")}>
{heading && <p className={styles.heading}>{heading}</p>}
<form className={styles.form} onSubmit={handleSubmit} noValidate>
<div className={styles.group}>
<label htmlFor="gbcf-email" className={styles.label}>
{emailLabel}
</label>
<input
type="email"
id="gbcf-email"
name="email"
className={styles.input}
placeholder={emailPlaceholder}
required
autoComplete="email"
/>
</div>
<div className={styles.group}>
<label htmlFor="gbcf-message" className={styles.label}>
{messageLabel}
</label>
<textarea
id="gbcf-message"
name="message"
className={styles.textarea}
placeholder={messagePlaceholder}
required
rows={5}
/>
</div>
<button type="submit" className={styles.submitBtn}>
{submitLabel}
</button>
</form>
</div>
);
}
Dependencies
- @bottega/tokens