# AppFormFooter

A sticky Save / Cancel action bar pinned to the bottom of the scroll container, so form actions
stay visible without scrolling — on any screen size and when embedded in the appshell.

## Install

```
src/components/common/AppFormFooter.tsx
src/components/common/app-form-footer.css
```

Requires `antd`.

## Usage

```tsx
import AppFormFooter from '@/components/common/AppFormFooter';
import { Button, Form } from 'antd';

<Form layout="vertical" onFinish={handleSubmit}>
  {/* ...fields... */}

  {/* LAST child inside the Form > Card body */}
  <AppFormFooter extra={<Button onClick={changePassword}>Change Password</Button>}>
    <Button type="primary" className="btn-ant-primary" htmlType="submit" loading={saving}>Save</Button>
    <Button className="opacity-8" onClick={handleCancel}>Cancel</Button>
  </AppFormFooter>
</Form>
```

- `children` = primary actions (Save / Cancel), anchored **left**.
- `extra` = secondary actions, pushed **right** (switches the bar to `is-between`).

## Do / Don't

- **Do** render it as the **last child inside the `<Form>`** so `htmlType="submit"` validation fires.
- **Match the negative margin to your card padding** — `-12px` for a 12px `.ant-card-body`, `-16px`
  for 16px. Otherwise the bar floats inside the card with a gap.
- If a `Collapse`/`Tabs` wrapper clips the sticky bar, add `app-sticky-footer-host` to that wrapper.

Part of the **RVN Design Kit** — design-kit.raffles.com.vn
