Components
Input & Form
Vertical AntD forms with colon-suffixed 13px labels, the required asterisk reversed to sit after the label, and Save/Cancel pinned in the sticky AppFormFooter.
Live form
Forms are always layout="vertical". Labels end with a colon in the label text itself (“Code:”), the required asterisk sits after the label, fields sit in Row gutter={[12, 0]} with Col xs={24} md={12} for a responsive two-column layout, and Save/Cancel live in the sticky AppFormFooter. The copy-code below is the real reference-fe create/edit form.
<Form
form={form}
layout="vertical"
className="w-100"
onFinish={handleActionReferenceFinally}
autoComplete="off"
>
<Row gutter={[12, 0]} className="mb-3">
<Col xs={24} sm={24} md={12} lg={12} xl={12}>
<FormItem
name={'code'}
label={`${t('reference.label.code')}:`}
rules={referenceRules.code()}
className="text-secondary fw-light"
rootClassName="text-secondary fw-light"
>
<Input disabled={!!referenceItemDetail?.id} autoComplete="off" placeholder={t('reference.placeholder.code')} />
</FormItem>
</Col>
<Col xs={24} sm={24} md={12} lg={12} xl={12}>
<FormItem
name={'name'}
label={`${t('reference.label.name')}:`}
className="text-secondary fw-light"
rootClassName="text-secondary fw-light"
>
<Input disabled={isReadOnly} autoComplete="off" placeholder={t('reference.placeholder.name')} />
</FormItem>
</Col>
<Col xs={24} sm={24} md={24} lg={24} xl={24}>
<FormItem name={'description'} label={`${t('reference.label.description')}:`} rules={referenceRules.description()}>
<Input disabled={isReadOnly} autoComplete="off" placeholder={t('reference.placeholder.description')} />
</FormItem>
</Col>
<Col xs={24} sm={24} md={24} lg={24} xl={24}>
<FormItem name={'isHierarchy'} label={`${t('reference.label.hierarchy')}:`} valuePropName="checked">
<Checkbox disabled={!!referenceItemDetail?.id || isReadOnly} checked={isHierarchy} onChange={handleCheckboxChange} className="text-primary fw-normal">
{`${t('reference.label.hierarchy')}`}
</Checkbox>
</FormItem>
</Col>
</Row>
</Form>
{/* Sticky action footer */}
<AppFormFooter>
<Button loading={isLoading} htmlType="submit" onClick={() => form.submit()} size="middle" className="btn-ant-primary text-white font-size-13" disabled={isReadOnly}>
{t('reference.actions.save')}
</Button>
<Button size="middle" className="font-size-13 opacity-8" onClick={handleCancel}>
{t('reference.actions.cancel')}
</Button>
</AppFormFooter>Labels and inputs both render at 13px via the module-wide App.css overrides:
/* App.css — 13px type on form labels and inputs */
.ant-form-item .ant-form-item-label > label { font-size: 13px; font-weight: 400; }
.ant-input { font-size: 13px !important; line-height: 1.5714285714285714; }Required mark
AntD renders the required asterisk before the label by default. RVN reverses it in every MFE’s layout.scss (already global in this kit): flex-direction: row-reverse flips the order so the ::before asterisk lands after the label text, margin-left: 4px spaces it from the label, and the ::after colon is collapsed to zero width.
.ant-form-item-required {
flex-direction: row-reverse;
display: inline-flex;
}
.ant-form-item-required::before {
margin-left: 4px;
margin-right: 0;
}
.ant-form-item-required::after {
width: 0;
margin: 0 !important;
}Options
| Name | Type | Default | Description |
|---|---|---|---|
layout | 'vertical' | 'horizontal' | Always vertical. Horizontal is legacy — do not use. |
form | FormInstance | — | Controlled instance from Form.useForm(); lets the footer call form.submit(). |
onFinish | (values) => void | — | Submit handler — async (values) => {...}. |
name | string | — | Form field key on each FormItem. |
label | string | — | Label text with the colon suffix convention — 'Field Label:'. |
rules | Rule[] | — | Validation per FormItem — [{required: true, message: 'X is required'}]. |
placeholder | string | — | Input hint text — 'Enter...'. |
disabled | boolean | — | Field state — read-only/locked (e.g. code field on edit). |
valuePropName | 'checked' | — | For Checkbox — maps the form value to checked, not value. |
className / rootClassName | string | — | Optional label styling — 'text-secondary fw-light' on the FormItem and its wrapper. |
Notes
layout="vertical".label={`${t('reference.label.code')}:`}) — not via Form.Item’s colon prop, which defaults to true and would double it.required={true} by itself — always pair it with rules={[{required: true, message: '...'}]} so the user sees a custom error below the input.AppFormFooter bleeds to the card edges with margin: 16px -12px -12px -12px — that -12px must equal the card’s body padding (.ant-card-body { padding: 12px !important }). Test the footer both standalone and embedded in appshell.