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.

Source in the MFEs
rate-fe layout.scssadministrator-fe layout.scssAppFormFooter.tsxapp-form-footer.cssReferenceFormAction.tsxreference-fe pages/edit.tsx

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.

Preview
Active
<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.

Preview
.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

NameTypeDefaultDescription
layout'vertical''horizontal'Always vertical. Horizontal is legacy — do not use.
formFormInstanceControlled instance from Form.useForm(); lets the footer call form.submit().
onFinish(values) => voidSubmit handler — async (values) => {...}.
namestringForm field key on each FormItem.
labelstringLabel text with the colon suffix convention — 'Field Label:'.
rulesRule[]Validation per FormItem — [{required: true, message: 'X is required'}].
placeholderstringInput hint text — 'Enter...'.
disabledbooleanField state — read-only/locked (e.g. code field on edit).
valuePropName'checked'For Checkbox — maps the form value to checked, not value.
className / rootClassNamestringOptional label styling — 'text-secondary fw-light' on the FormItem and its wrapper.

Notes

Never layout='horizontal'
Horizontal forms are legacy. Every create/edit and filter form is layout="vertical".
Colon lives in the label text
Write the colon into the label string (label={`${t('reference.label.code')}:`}) — not via Form.Item’s colon prop, which defaults to true and would double it.
required flag alone shows no message
Do not rely on required={true} by itself — always pair it with rules={[{required: true, message: '...'}]} so the user sees a custom error below the input.
Footer margins match the card padding
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.