feat(plugin-form-builder): radio field (#11716)

### What?

A field for input radio

Demo:

<img width="1320" alt="Screenshot 2025-03-15 at 6 54 51 AM"
src="https://github.com/user-attachments/assets/47744e3f-e1ca-4596-bc7c-09f7b2d42c5b"
/>

---

UI code example, using shadcn/ui:

```tsx
import type { SelectField } from '@payloadcms/plugin-form-builder/types'
import type { Control, FieldErrorsImpl } from 'react-hook-form'

import { Label } from '@/components/ui/label'
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'
import React from 'react'
import { Controller } from 'react-hook-form'

import { Error } from '../Error'
import { Width } from '../Width'

export const Radio: React.FC<
  SelectField & {
    control: Control
    errors: Partial<FieldErrorsImpl>
  }
> = ({ name, control, errors, label, options, required, width, defaultValue }) => {
  return (
    <Width width={width}>
      <Label htmlFor={name}>{label}</Label>
      <Controller
        control={control}
        defaultValue={defaultValue}
        name={name}
        render={({ field: { onChange, value } }) => {
          return (
            <RadioGroup onValueChange={(val) => onChange(val)} value={value} className="space-y-2">
              {options.map(({ label, value }) => {
                const id = `${name}-${value}`

                return (
                  <div key={value} className="flex items-center space-x-2">
                    <RadioGroupItem value={value} id={id} />
                    <Label htmlFor={id}>{label}</Label>
                  </div>
                )
              })}
            </RadioGroup>
          )
        }}
        rules={{ required }}
      />
      {required && errors[name] && <Error />}
    </Width>
  )
}

```

UI demo:

<img width="651" alt="Screenshot 2025-03-15 at 7 04 37 AM"
src="https://github.com/user-attachments/assets/f3922489-8e62-4464-b48c-8425735421f5"
/>

Co-authored-by: Pan <kpkong@hk01.com>
This commit is contained in:
AoiYamada
2025-03-15 19:52:05 +08:00
committed by GitHub
parent 9f9db3ff81
commit 427a5f123b
2 changed files with 112 additions and 0 deletions

View File

@@ -28,6 +28,95 @@ const width: Field = {
label: 'Field Width (percentage)', label: 'Field Width (percentage)',
} }
const placeholder: Field = {
name: 'placeholder',
type: 'text',
label: 'Placeholder',
}
const Radio: Block = {
slug: 'radio',
fields: [
{
type: 'row',
fields: [
{
...name,
admin: {
width: '50%',
},
},
{
...label,
admin: {
width: '50%',
},
},
],
},
{
type: 'row',
fields: [
{
...width,
admin: {
width: '50%',
},
},
{
name: 'defaultValue',
type: 'text',
admin: {
width: '50%',
},
label: 'Default Value',
localized: true,
},
],
},
{
name: 'options',
type: 'array',
fields: [
{
type: 'row',
fields: [
{
name: 'label',
type: 'text',
admin: {
width: '50%',
},
label: 'Label',
localized: true,
required: true,
},
{
name: 'value',
type: 'text',
admin: {
width: '50%',
},
label: 'Value',
required: true,
},
],
},
],
label: 'Radio Attribute Options',
labels: {
plural: 'Options',
singular: 'Option',
},
},
required,
],
labels: {
plural: 'Radio Fields',
singular: 'Radio',
},
}
const Select: Block = { const Select: Block = {
slug: 'select', slug: 'select',
fields: [ fields: [
@@ -68,6 +157,14 @@ const Select: Block = {
}, },
], ],
}, },
{
type: 'row',
fields: [
{
...placeholder,
},
],
},
{ {
name: 'options', name: 'options',
type: 'array', type: 'array',
@@ -576,6 +673,7 @@ export const fields = {
message: Message, message: Message,
number: Number, number: Number,
payment: Payment, payment: Payment,
radio: Radio,
select: Select, select: Select,
state: State, state: State,
text: Text, text: Text,

View File

@@ -97,6 +97,19 @@ export interface SelectField {
label?: string label?: string
name: string name: string
options: SelectFieldOption[] options: SelectFieldOption[]
placeholder?: string
required?: boolean
width?: number
}
export interface RadioField {
blockName?: string
blockType: 'radio'
defaultValue?: string
label?: string
name: string
options: SelectFieldOption[]
placeholder?: string
required?: boolean required?: boolean
width?: number width?: number
} }
@@ -175,6 +188,7 @@ export type FormFieldBlock =
| EmailField | EmailField
| MessageField | MessageField
| PaymentField | PaymentField
| RadioField
| SelectField | SelectField
| StateField | StateField
| TextAreaField | TextAreaField