GenericForm
A field-config–driven form renderer powered by Formik. You create the formik instance externally (via useFormik or the library's helpers), then pass it along with a fields array — GenericFrom renders every field, handles validation display, and wires up the Formik context automatically.
Preview
Live preview↗ Open in Storybook
Import
import { GenericFrom } from "@xocialive/ui-components";
import type { FormFieldProps } from "@xocialive/ui-components/components";
// Helper hooks / utilities
import {
buildValidationSchema,
buildInitialValues,
buildPayload,
useFormikWithValidation,
useFormikWithPayload,
} from "@xocialive/ui-components/components";
note
The export name is GenericFrom (intentional spelling in the library).
Basic usage
src/modules/items/forms/ItemForm.tsx
import React from "react";
import { useFormik } from "formik";
import * as Yup from "yup";
import { GenericFrom, FormHeader, FormActions } from "@xocialive/ui-components";
import type { FormFieldProps } from "@xocialive/ui-components/components";
import { useNavigate } from "react-router-dom";
interface ItemFormValues {
englishName: string;
arabicName: string;
code: string;
}
const fields: FormFieldProps[] = [
{
type: "text",
name: "englishName",
label: t("items.englishName"),
gridSize: { xs: 12, md: 6 },
maxLength: 100,
},
{
type: "text",
name: "arabicName",
label: t("items.arabicName"),
gridSize: { xs: 12, md: 6 },
maxLength: 100,
},
{
type: "text",
name: "code",
label: t("items.code"),
gridSize: { xs: 12, md: 6 },
maxLength: 50,
},
];
const ItemForm: React.FC = () => {
const navigate = useNavigate();
const formik = useFormik<ItemFormValues>({
initialValues: { englishName: "", arabicName: "", code: "" },
validationSchema: Yup.object({
englishName: Yup.string().required(t("validation.required")),
arabicName: Yup.string().required(t("validation.required")),
code: Yup.string().required(t("validation.required")),
}),
onSubmit: async (values) => {
await createItem(values);
navigate("/items");
},
});
return (
<>
<FormHeader
isDirty={formik.dirty}
isSubmitting={formik.isSubmitting}
onBack={() => navigate("/items")}
textOverrides={{
title: t("items.newItem"),
backButton: t("common.back"),
unsavedChanges: t("common.unsavedChanges"),
}}
/>
<GenericFrom
formik={formik}
fields={fields}
section={{
title: t("items.basicInfo"),
description: t("items.basicInfoDescription"),
}}
/>
<FormActions
isEditing={false}
isSubmitting={formik.isSubmitting}
textOverrides={{
submit: t("common.save"),
cancel: t("common.cancel"),
}}
/>
</>
);
};
export default ItemForm;
Props
| Prop | Type | Description |
|---|---|---|
formik | FormikProps<any> | Required. Formik instance created externally |
fields | FormFieldProps[] | Required. Field definitions |
section | SectionProps | Optional section header (title + description) |
hideSection | boolean | Hides the section header when true |
crossFieldValidations | CrossFieldValidation[] | Cross-field validation rules |
FormFieldProps
interface FormFieldProps {
type:
| "text"
| "textarea"
| "select"
| "async-autocomplete"
| "async-autocomplete-v2"
| "autocomplete"
| "checkbox"
| "switch"
| "tel"
| "date";
name: string;
label: string;
gridSize?: { xs?: number; sm?: number; md?: number; lg?: number };
maxLength?: number;
textFieldType?: string; // e.g. "number", "email", "password"
options?: { label: string; value: any }[]; // for select / autocomplete
disabled?: boolean;
required?: boolean;
placeholder?: string;
}
Supported field types
type | Rendered component |
|---|---|
text | TextField |
textarea | TextField (multiline) |
select | Select |
autocomplete | Autocomplete |
async-autocomplete | AsyncAutoComplete |
async-autocomplete-v2 | AsyncAutoComplete (v2) |
checkbox | Checkbox |
switch | Switch |
tel | MuiTelInput |
date | MUI DatePicker |
Helper utilities
// Build a Yup schema from fields array
const schema = buildValidationSchema(fields);
// Build Formik initialValues from fields array
const initialValues = buildInitialValues(fields);
// Extract only the fields present in the fields array from formik values
const payload = buildPayload(formik.values, fields);
// Combined hook: formik + schema derived from fields
const formik = useFormikWithValidation({ fields, onSubmit, initialValues });
// Combined hook: formik + payload builder
const { formik, payload } = useFormikWithPayload({ fields, onSubmit, initialValues });