diff --git a/src/components/admin/shared/registry-driven-form.tsx b/src/components/admin/shared/registry-driven-form.tsx index 64bad49d..58c0cdae 100644 --- a/src/components/admin/shared/registry-driven-form.tsx +++ b/src/components/admin/shared/registry-driven-form.tsx @@ -28,6 +28,7 @@ type SettingType = | 'number' | 'boolean' | 'select' + | 'radio' | 'url' | 'email' | 'textarea' @@ -526,6 +527,36 @@ function FieldInput({ /> ); } + if (entry.type === 'radio' && entry.options) { + // Inline radio group — clearer than a dropdown for 2–3 mutually-exclusive + // options where each choice has materially different consequences (e.g. + // auto-vs-manual signing dispatch). Falls through to plain Select when + // the option count grows. + const current = value == null ? null : String(value); + return ( +
+ {entry.options.map((o) => { + const checked = current === o.value; + return ( + + ); + })} +
+ ); + } if (entry.type === 'select' && entry.options) { // Radix Select rejects an empty-string `value` because that's its internal // sentinel for "cleared". Pass `undefined` instead so the placeholder diff --git a/src/lib/settings/registry.ts b/src/lib/settings/registry.ts index aba52898..d5e7f1f4 100644 --- a/src/lib/settings/registry.ts +++ b/src/lib/settings/registry.ts @@ -210,10 +210,10 @@ export const REGISTRY: SettingEntry[] = [ label: 'Initial signing-invitation email behaviour', description: 'Auto = the system sends the branded "please sign" email immediately when an EOI/contract/reservation is generated. Manual = the document is generated and the signing URL appears in the UI; a rep clicks "Send invitation" to dispatch. Applies to all document types, not just EOI.', - type: 'select', + type: 'radio', options: [ - { value: 'manual', label: 'Manual (rep clicks Send after generation)' }, - { value: 'auto', label: 'Auto (send branded email on generate)' }, + { value: 'manual', label: 'Manual — rep clicks Send after generation' }, + { value: 'auto', label: 'Auto — send branded email on generate' }, ], scope: 'port', defaultValue: 'manual', @@ -241,11 +241,11 @@ export const REGISTRY: SettingEntry[] = [ section: 'documenso.behavior', label: 'Signing order', description: - 'PARALLEL = all recipients can sign at once. SEQUENTIAL = each waits for the previous (v2 only - v1 always parallel).', - type: 'select', + 'PARALLEL = all recipients can sign at once. SEQUENTIAL = each waits for the previous (v2 only — v1 always parallel).', + type: 'radio', options: [ - { value: 'PARALLEL', label: 'Parallel - all recipients sign concurrently' }, - { value: 'SEQUENTIAL', label: 'Sequential - order matters (v2 only)' }, + { value: 'PARALLEL', label: 'Parallel — all recipients sign concurrently' }, + { value: 'SEQUENTIAL', label: 'Sequential — order matters (v2 only)' }, ], scope: 'port', defaultValue: 'PARALLEL', diff --git a/src/lib/settings/resolver.ts b/src/lib/settings/resolver.ts index eaf05de4..964ac3b7 100644 --- a/src/lib/settings/resolver.ts +++ b/src/lib/settings/resolver.ts @@ -51,6 +51,7 @@ function defaultValidator(entry: SettingEntry): z.ZodTypeAny { case 'boolean': return z.coerce.boolean(); case 'select': + case 'radio': if (entry.options) { return z.enum(entry.options.map((o) => o.value) as [string, ...string[]]); } diff --git a/src/lib/settings/types.ts b/src/lib/settings/types.ts index c0d1a463..91c0f7b8 100644 --- a/src/lib/settings/types.ts +++ b/src/lib/settings/types.ts @@ -6,6 +6,7 @@ export type SettingType = | 'number' | 'boolean' | 'select' + | 'radio' | 'url' | 'email' | 'textarea'