@nickle-ai/contact-form-react
v3.0.2
Published
Reusable dark-themed contact form component for n8n + Brevo workflows.
Readme
@nickle-ai/contact-form-react
Reusable contact form package for static/client websites using an n8n webhook + Brevo delivery.
Install
npm install @nickle-ai/contact-form-reactQuick start
import { PremiumContactForm, contactConfig } from "@nickle-ai/contact-form-react";
export function ContactSection() {
return (
<PremiumContactForm
config={contactConfig}
webhookUrl={process.env.NEXT_PUBLIC_CONTACT_WEBHOOK_URL || ""}
clientId={process.env.NEXT_PUBLIC_CONTACT_CLIENT_ID || ""}
/>
);
}Default styles are loaded automatically by the package entrypoint.
If you prefer explicit CSS import control, add:
import "@nickle-ai/contact-form-react/styles.css";What v3 adds
- Dark default design aligned with
@nickle-ai/chatbot-reactvisual values. - Inter-first default typography.
- Canonical theme token API with legacy token aliases preserved.
- Expanded class override hooks.
- n8n email template defaults updated to the same visual language.
Contract (unchanged)
Frontend request payload:
{
"client_id": "client-slug",
"fields": {
"name": "Jane Doe",
"email": "[email protected]",
"message": "Hello"
},
"meta": {
"pageUrl": "https://example.com/contact",
"userAgent": "Mozilla/5.0 ..."
},
"hp": ""
}Webhook responses:
- Success:
{ "ok": true, "client_id": "client-slug" } - Error:
{ "ok": false, "client_id": "client-slug", "error": "..." }
Form success is only set when HTTP is 2xx and response contains ok: true with matching client_id.
PremiumContactForm props
interface PremiumContactFormProps {
config: ContactFormConfig;
webhookUrl: string;
clientId: string;
submitLabel?: string;
successMessage?: string;
unavailableMessage?: string;
networkErrorMessage?: string;
classNames?: PremiumContactFormClassNames;
theme?: Partial<PremiumContactFormTheme>;
tokenBindings?: PremiumContactFormTokenBindings;
renderSubmitButton?: (props: {
isSubmitting: boolean;
submitLabel: string;
disabled: boolean;
}) => ReactNode;
}Notes:
- The snippet above matches all current public props exported from
src/components/contact/PremiumContactForm.tsx. renderSubmitButtonis the button replacement hook for host-site button components.- Keep your custom button as
type="submit"so form submit semantics stay intact.
Submit button override (host-site component)
import { PremiumContactForm, contactConfig } from "@nickle-ai/contact-form-react";
import { Button } from "@/components/ui/button";
export function ContactSection() {
return (
<PremiumContactForm
config={contactConfig}
webhookUrl={process.env.NEXT_PUBLIC_CONTACT_WEBHOOK_URL || ""}
clientId={process.env.NEXT_PUBLIC_CONTACT_CLIENT_ID || ""}
classNames={{
actions: "justify-end", // position (left/center/right) via your CSS utility/classes
}}
renderSubmitButton={({ isSubmitting, submitLabel, disabled }) => (
<Button type="submit" size="lg" disabled={disabled}>
{isSubmitting ? "Sending..." : submitLabel}
</Button>
)}
/>
);
}Size/position options:
- Position: use
classNames.actionsto style the submit button container. - Size: use your custom button component props (
size,className, etc.) or override built-in button tokens. - If you keep the default button, use theme tokens (
buttonPaddingY,buttonPaddingX,buttonRadius, etc.) and/orclassNames.button.
Class overrides
interface PremiumContactFormClassNames {
root?: string;
wrapper?: string;
panel?: string;
form?: string;
fieldWrapper?: string;
label?: string;
checkboxLabel?: string;
requirement?: string;
control?: string;
input?: string;
textarea?: string;
select?: string;
checkboxWrapper?: string;
checkboxRow?: string;
checkbox?: string;
description?: string;
errorText?: string;
button?: string;
submitButton?: string;
submitError?: string;
successMessage?: string;
statusRegion?: string;
statusMessage?: string;
actions?: string;
unavailableMessage?: string;
}Theme tokens
Canonical tokens:
interface PremiumContactFormThemeTokens {
fontFamily: string;
panelBackground: string;
panelBorderColor: string;
panelRadius: string;
panelPadding: string;
panelShadow: string;
fieldGap: string;
fieldInnerGap: string;
requirementGap: string;
labelColor: string;
inputTextColor: string;
inputBackground: string;
inputBorderColor: string;
inputRadius: string;
inputPaddingY: string;
inputPaddingX: string;
textareaMinHeight: string;
selectPaddingRight: string;
inputPlaceholderColor: string;
checkboxGap: string;
checkboxSize: string;
checkboxRadius: string;
descriptionColor: string;
requirementColor: string;
errorColor: string;
successColor: string;
buttonBackground: string;
buttonTextColor: string;
buttonBorderColor: string;
buttonRadius: string;
buttonPaddingY: string;
buttonPaddingX: string;
buttonShadow: string;
focusBorderColor: string;
focusRingColor: string;
selectCaretColor: string;
}Legacy aliases remain supported in both theme and tokenBindings:
wrapperBackground->panelBackgroundwrapperBorderColor->panelBorderColorwrapperRadius->panelRadiuswrapperPadding->panelPaddingcontrolPaddingY->inputPaddingYcontrolPaddingX->inputPaddingX
All other legacy keys with identical names remain valid.
n8n assets
- Workflow JSON:
workflows/n8n/contact-submit.workflow.json - Client config example:
workflows/n8n/client-config.example.json - Setup guide:
docs/n8n-workflow-setup.md - Contract reference:
docs/contracts.md
Email HTML is generated in n8n (Code - Build Email) using merged default + client brandTokens.
Email HTML override surface:
brandTokensoverrides inline style tokens only (colors, spacing, radius, typography, etc.).logoUrl(client registry field) toggles/replaces the header logo image.- To change markup structure, heading copy, subject format, or row ordering, edit
Code - Build Emailin the workflow.
Local QA playground
This repo includes a Next.js playground (src/app) to preview the form defaults and webhook behavior.
npm install
npm run lint
npm run typecheck
npm run build
npm run dev