templates/basic/.claude/skills/dashboard-form-ui/SKILL.md
Create or modify forms in admin or vendor dashboards in the Mercur basic starter using stable form structure, validation, submission guards, and dashboard UI conventions.
npx skillsauth add mercurjs/mercur dashboard-form-uiInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this skill when:
Applies equally to admin and vendor dashboards.
Prefer the existing Mercur form pattern already present in the screen or package. Do not introduce a parallel form system just because it is locally convenient.
Before introducing custom field wrappers, selectors, overlays, or other interactive form UI, apply medusa-ui-conformance.
Forms use react-hook-form with zod validation and components from @mercurjs/dashboard-shared and @medusajs/ui.
A create/edit form page is a RouteFocusModal drawer route:
// The page default export wraps RouteFocusModal (provides context)
const CreatePage = () => (
<RouteFocusModal>
<CreateForm />
</RouteFocusModal>
);
export default CreatePage;
// The form component uses RouteFocusModal.Form, .Header, .Body, .Footer
const CreateForm = () => {
const { t } = useTranslation();
const { handleSuccess } = useRouteModal();
const form = useForm({ defaultValues: { ... }, resolver: zodResolver(schema) });
const handleSubmit = form.handleSubmit(async (data) => {
await mutateAsync(data, {
onSuccess: () => { toast.success("Created"); handleSuccess("/route"); },
onError: (error) => toast.error(error.message),
});
});
return (
<RouteFocusModal.Form form={form}>
<form onSubmit={handleSubmit} className="flex h-full flex-col overflow-hidden">
<RouteFocusModal.Header />
<RouteFocusModal.Body className="flex size-full flex-col items-center p-16">
<div className="flex w-full max-w-[720px] flex-col gap-y-8">
{/* Heading, fields */}
</div>
</RouteFocusModal.Body>
<RouteFocusModal.Footer>
<RouteFocusModal.Close asChild>
<Button size="small" variant="secondary">{t("actions.cancel")}</Button>
</RouteFocusModal.Close>
<Button size="small" variant="primary" type="submit" isLoading={isPending}>
{t("actions.create")}
</Button>
</RouteFocusModal.Footer>
</form>
</RouteFocusModal.Form>
);
};
Full-screen modal overlay. Used for creating new entities.
RouteFocusModal (provides context), form uses .Form, .Header, .Body, .Footer, .CloseuseRouteModal() must be called inside the providerTabbedForm, do NOT use RouteFocusModal.Form — TabbedForm renders it internally. See dashboard-tab-ui.Side panel from the right. Used for editing existing entities.
RouteDrawer, form uses .Form, .Header, .Title, .Description, .Body, .Footer, .Close@ prefix directory (e.g. [id]/@edit/page.tsx) to create a parallel route. Without @, the detail page unmounts. See dashboard-page-ui for full pattern.RouteFocusModal / RouteDrawer — wraps the page, provides modal provider context.Form — wraps the form, connects react-hook-form.Header — modal/drawer header (RouteFocusModal has close button built in; RouteDrawer uses .Title and .Description).Body — scrollable content area.Footer — sticky footer with actions.Close — closes the modal/drawer (use with asChild on Cancel button)Form.Field / Form.Item / Form.Label / Form.Control / Form.ErrorMessage — form field compositionForm.Label optional — marks a field as optional in the UIuseRouteModal() outside a RouteFocusModal provider.zod + zodResolver) when the form is non-trivial.dashboard-page-ui.dashboard-tab-ui.documentation
Analyze a Mercur 1.x project and guide migration to 2.0. Self-contained — works without access to the mercur monorepo.
documentation
Plan and execute migration from Mercur 1.x to 2.0. Classifies project difficulty, reads relevant migration docs, and follows stop conditions.
development
Review code changes for contract compliance, type safety, and regression risk. Use after completing any non-trivial implementation, before merging PRs, or when asked to review code quality across any mercur package.
tools
Use Mercur CLI commands correctly inside a project created from the Mercur basic starter. Use when choosing between `create`, `init`, `add`, `search`, `view`, and `diff`.