From 4b082a7daffa295c9fcef370727950cb70f5fedc Mon Sep 17 00:00:00 2001 From: sirily11 <32106111+sirily11@users.noreply.github.com> Date: Tue, 7 Jul 2026 15:17:06 +0800 Subject: [PATCH] fix: add boolean value style and error list --- .../src/components/resource-form.tsx | 30 +++++++- packages/admin-next/src/theme.css | 70 +++++++++++++++++++ 2 files changed, 98 insertions(+), 2 deletions(-) diff --git a/packages/admin-next/src/components/resource-form.tsx b/packages/admin-next/src/components/resource-form.tsx index 556a10e..56b2b05 100644 --- a/packages/admin-next/src/components/resource-form.tsx +++ b/packages/admin-next/src/components/resource-form.tsx @@ -2,7 +2,11 @@ import * as React from "react"; import Form from "@rjsf/core"; -import type { RegistryWidgetsType } from "@rjsf/utils"; +import type { + ErrorListProps, + RegistryWidgetsType, + TemplatesType, +} from "@rjsf/utils"; import validator from "@rjsf/validator-ajv8"; import type { FormSchema } from "../types.js"; import { isDetail } from "../types.js"; @@ -32,6 +36,27 @@ const widgets: RegistryWidgetsType = { ObjectSearch: ForeignKeyWidget, }; +/** Clean, shadcn-styled summary of validation errors shown atop the form. */ +function ErrorListTemplate({ errors }: ErrorListProps): React.JSX.Element { + return ( +
+

+ Please fix the following{" "} + {errors.length === 1 ? "error" : `${errors.length} errors`}: +

+ +
+ ); +} + +const templates: Partial = { + ErrorListTemplate, +}; + export interface ResourceFormProps { resourceId: string; action: "create" | "edit"; @@ -108,11 +133,12 @@ export function ResourceForm({ uiSchema={schema.uiSchema} formData={formData} widgets={widgets} + templates={templates} validator={validator} extraErrors={extraErrors as never} onChange={(e) => setFormData(e.formData as Record)} onSubmit={(e) => submit(e.formData as Record)} - showErrorList={false} + showErrorList="top" > {submitError && (

{submitError}

diff --git a/packages/admin-next/src/theme.css b/packages/admin-next/src/theme.css index f366d07..8a2c00f 100644 --- a/packages/admin-next/src/theme.css +++ b/packages/admin-next/src/theme.css @@ -153,6 +153,76 @@ margin: 0.25rem 0 0; } +/* Field help text: smaller and muted, sitting under the label. */ +.ag-form .field-description { + margin: 0 0 0.375rem; + font-size: 0.8125rem; + line-height: 1.25rem; + color: var(--muted-foreground); +} + +.ag-form .field-description p { + margin: 0; +} + +/* Boolean (checkbox) field: control and label share one aligned row. */ +.ag-form .checkbox label { + display: flex; + align-items: center; + gap: 0.5rem; + margin-bottom: 0; + font-size: 0.875rem; + font-weight: 400; + cursor: pointer; +} + +.ag-form .checkbox input[type="checkbox"] { + width: 1rem; + height: 1rem; + margin: 0; + flex-shrink: 0; + accent-color: var(--primary); + cursor: pointer; +} + +.ag-form .checkbox.disabled label { + cursor: not-allowed; + opacity: 0.6; +} + +.ag-form .checkbox .field-description { + margin-bottom: 0.375rem; +} + +/* Validation error summary at the top of the form. */ +.ag-form .ag-error-list { + margin-bottom: 1rem; + border: 1px solid var(--destructive); + border-radius: 0.5rem; + background: color-mix(in oklab, var(--destructive) 8%, var(--background)); + padding: 0.75rem 0.875rem; +} + +.ag-form .ag-error-list-title { + margin: 0 0 0.375rem; + font-size: 0.8125rem; + font-weight: 600; + color: var(--destructive); +} + +.ag-form .ag-error-list-items { + margin: 0; + padding-left: 1rem; + list-style: disc; +} + +.ag-form .ag-error-list-items li { + margin-top: 0.125rem; + font-size: 0.8125rem; + line-height: 1.35; + color: var(--destructive); +} + .ag-sheet-overlay[data-state="open"] { animation: ag-sheet-overlay-in 160ms ease-out; }