Files
sigpro-ui/docs/components_old/radio.md
2026-04-02 19:31:39 +02:00

23 KiB

Radio

Radio button component with label, tooltip support, and reactive group selection. All radios in the same group share a common name attribute for proper HTML semantics.

Tag

Radio

Props

Prop Type Default Description
label string - Label text for the radio button
value string | Signal<string> - Selected value signal for the group
radioValue string - Value of this radio button
name string - Group name (all radios in group should share this)
tooltip string - Tooltip text on hover
disabled boolean | Signal<boolean> false Disabled state
class string '' Additional CSS classes (DaisyUI + Tailwind)
onclick function - Click event handler

Live Examples

Basic Radio Group

Live Demo

const BasicDemo = () => {
  const selected = $('option1');
  
  return Div({ class: 'flex flex-col gap-3' }, [
    Radio({
      label: 'Option 1',
      name: 'basic-group',
      value: selected,
      radioValue: 'option1',
      onclick: () => selected('option1')
    }),
    Radio({
      label: 'Option 2',
      name: 'basic-group',
      value: selected,
      radioValue: 'option2',
      onclick: () => selected('option2')
    }),
    Radio({
      label: 'Option 3',
      name: 'basic-group',
      value: selected,
      radioValue: 'option3',
      onclick: () => selected('option3')
    }),
    Div({ class: 'mt-2 text-sm opacity-70' }, () => `Selected: ${selected()}`)
  ]);
};
$mount(BasicDemo, '#demo-basic');

With Tooltip

Live Demo

const TooltipDemo = () => {
  const selected = $('light');
  
  return Div({ class: 'flex flex-col gap-3' }, [
    Radio({
      label: 'Light mode',
      name: 'theme-group',
      value: selected,
      radioValue: 'light',
      tooltip: 'Light theme with white background',
      onclick: () => selected('light')
    }),
    Radio({
      label: 'Dark mode',
      name: 'theme-group',
      value: selected,
      radioValue: 'dark',
      tooltip: 'Dark theme with black background',
      onclick: () => selected('dark')
    })
  ]);
};
$mount(TooltipDemo, '#demo-tooltip');

Disabled State

Live Demo

const DisabledDemo = () => {
  const selected = $('enabled');
  
  return Div({ class: 'flex flex-col gap-3' }, [
    Radio({
      label: 'Enabled option',
      name: 'disabled-group',
      value: selected,
      radioValue: 'enabled',
      onclick: () => selected('enabled')
    }),
    Radio({
      label: 'Disabled option (cannot select)',
      name: 'disabled-group',
      value: selected,
      radioValue: 'disabled',
      disabled: true,
      onclick: () => selected('disabled')
    })
  ]);
};
$mount(DisabledDemo, '#demo-disabled');

Reactive Preview

Live Demo

const ReactiveDemo = () => {
  const size = $('medium');
  const color = $('blue');
  
  const sizes = [
    { value: 'small', label: 'Small' },
    { value: 'medium', label: 'Medium' },
    { value: 'large', label: 'Large' }
  ];
  
  const colors = [
    { value: 'blue', label: 'Blue' },
    { value: 'green', label: 'Green' },
    { value: 'red', label: 'Red' }
  ];
  
  return Div({ class: 'flex flex-col gap-4' }, [
    Div({ class: 'text-sm font-bold' }, 'Select size'),
    Div({ class: 'flex gap-4' }, sizes.map(s => 
      Radio({
        label: s.label,
        name: 'size-group',
        value: size,
        radioValue: s.value,
        onclick: () => size(s.value)
      })
    )),
    Div({ class: 'text-sm font-bold mt-2' }, 'Select color'),
    Div({ class: 'flex gap-4' }, colors.map(c => 
      Radio({
        label: c.label,
        name: 'color-group',
        value: color,
        radioValue: c.value,
        onclick: () => color(c.value)
      })
    )),
    Div({ 
      class: 'mt-4 p-4 rounded-lg text-center transition-all',
      style: () => {
        const sizeMap = { small: 'text-sm', medium: 'text-base', large: 'text-lg' };
        const colorMap = { blue: '#3b82f6', green: '#10b981', red: '#ef4444' };
        return `background-color: ${colorMap[color()]}; color: white; ${sizeMap[size()]}`;
      }
    }, () => `${size()} ${color()} preview`)
  ]);
};
$mount(ReactiveDemo, '#demo-reactive');

Payment Method Selection

Live Demo

const PaymentDemo = () => {
  const method = $('credit');
  
  return Div({ class: 'flex flex-col gap-4' }, [
    Div({ class: 'text-sm font-bold' }, 'Payment method'),
    Div({ class: 'flex flex-col gap-3' }, [
      Radio({
        label: '💳 Credit Card',
        name: 'payment-group',
        value: method,
        radioValue: 'credit',
        onclick: () => method('credit')
      }),
      Radio({
        label: '🏦 Bank Transfer',
        name: 'payment-group',
        value: method,
        radioValue: 'bank',
        onclick: () => method('bank')
      }),
      Radio({
        label: '📱 Digital Wallet',
        name: 'payment-group',
        value: method,
        radioValue: 'wallet',
        onclick: () => method('wallet')
      })
    ]),
    Div({ class: 'alert alert-info mt-2' }, () => {
      const messages = {
        credit: 'You selected Credit Card. Enter your card details.',
        bank: 'You selected Bank Transfer. Use the provided account number.',
        wallet: 'You selected Digital Wallet. Scan the QR code to pay.'
      };
      return messages[method()];
    })
  ]);
};
$mount(PaymentDemo, '#demo-payment');

All Variants

Live Demo

const VariantsDemo = () => {
  const primary = $('primary1');
  const secondary = $('secondary1');
  const accent = $('accent1');
  
  return Div({ class: 'flex flex-col gap-4' }, [
    Div({ class: 'card bg-base-200 p-4' }, [
      Div({ class: 'text-sm font-bold mb-2' }, 'Primary variant'),
      Div({ class: 'flex gap-4' }, [
        Radio({
          label: 'Option A',
          name: 'primary-group',
          value: primary,
          radioValue: 'primary1',
          class: 'radio-primary',
          onclick: () => primary('primary1')
        }),
        Radio({
          label: 'Option B',
          name: 'primary-group',
          value: primary,
          radioValue: 'primary2',
          class: 'radio-primary',
          onclick: () => primary('primary2')
        })
      ])
    ]),
    Div({ class: 'card bg-base-200 p-4' }, [
      Div({ class: 'text-sm font-bold mb-2' }, 'Secondary variant'),
      Div({ class: 'flex gap-4' }, [
        Radio({
          label: 'Option A',
          name: 'secondary-group',
          value: secondary,
          radioValue: 'secondary1',
          class: 'radio-secondary',
          onclick: () => secondary('secondary1')
        }),
        Radio({
          label: 'Option B',
          name: 'secondary-group',
          value: secondary,
          radioValue: 'secondary2',
          class: 'radio-secondary',
          onclick: () => secondary('secondary2')
        })
      ])
    ]),
    Div({ class: 'card bg-base-200 p-4' }, [
      Div({ class: 'text-sm font-bold mb-2' }, 'Accent variant'),
      Div({ class: 'flex gap-4' }, [
        Radio({
          label: 'Option A',
          name: 'accent-group',
          value: accent,
          radioValue: 'accent1',
          class: 'radio-accent',
          onclick: () => accent('accent1')
        }),
        Radio({
          label: 'Option B',
          name: 'accent-group',
          value: accent,
          radioValue: 'accent2',
          class: 'radio-accent',
          onclick: () => accent('accent2')
        })
      ])
    ])
  ]);
};
$mount(VariantsDemo, '#demo-variants');

Dynamic Options

Live Demo

const DynamicDemo = () => {
  const category = $('cars');
  const selected = $('');
  
  const options = {
    cars: [
      { value: 'sedan', label: 'Sedan' },
      { value: 'suv', label: 'SUV' },
      { value: 'sports', label: 'Sports' }
    ],
    colors: [
      { value: 'red', label: 'Red' },
      { value: 'blue', label: 'Blue' },
      { value: 'black', label: 'Black' }
    ]
  };
  
  return Div({ class: 'flex flex-col gap-4' }, [
    Div({ class: 'flex gap-4' }, [
      Radio({
        label: 'Cars',
        name: 'category-group',
        value: category,
        radioValue: 'cars',
        onclick: () => {
          category('cars');
          selected('');
        }
      }),
      Radio({
        label: 'Colors',
        name: 'category-group',
        value: category,
        radioValue: 'colors',
        onclick: () => {
          category('colors');
          selected('');
        }
      })
    ]),
    Div({ class: 'divider my-1' }),
    Div({ class: 'text-sm font-bold' }, () => `Select ${category()}`),
    Div({ class: 'flex flex-col gap-2' }, () => 
      options[category()].map(opt => 
        Radio({
          label: opt.label,
          name: 'dynamic-option-group',
          value: selected,
          radioValue: opt.value,
          onclick: () => selected(opt.value)
        })
      )
    ),
    () => selected() 
      ? Div({ class: 'alert alert-success mt-2' }, () => `Selected ${category()}: ${selected()}`)
      : null
  ]);
};
$mount(DynamicDemo, '#demo-dynamic');
<script> (function() { const initRadioExamples = () => { // 1. Basic Radio Group const basicTarget = document.querySelector('#demo-basic'); if (basicTarget && !basicTarget.hasChildNodes()) { const BasicDemo = () => { const selected = $('option1'); return Div({ class: 'flex flex-col gap-3' }, [ Radio({ label: 'Option 1', name: 'basic-group', value: selected, radioValue: 'option1', onclick: () => selected('option1') }), Radio({ label: 'Option 2', name: 'basic-group', value: selected, radioValue: 'option2', onclick: () => selected('option2') }), Radio({ label: 'Option 3', name: 'basic-group', value: selected, radioValue: 'option3', onclick: () => selected('option3') }), Div({ class: 'mt-2 text-sm opacity-70' }, () => `Selected: ${selected()}`) ]); }; $mount(BasicDemo, basicTarget); } // 2. With Tooltip const tooltipTarget = document.querySelector('#demo-tooltip'); if (tooltipTarget && !tooltipTarget.hasChildNodes()) { const TooltipDemo = () => { const selected = $('light'); return Div({ class: 'flex flex-col gap-3' }, [ Radio({ label: 'Light mode', name: 'theme-group', value: selected, radioValue: 'light', tooltip: 'Light theme with white background', onclick: () => selected('light') }), Radio({ label: 'Dark mode', name: 'theme-group', value: selected, radioValue: 'dark', tooltip: 'Dark theme with black background', onclick: () => selected('dark') }) ]); }; $mount(TooltipDemo, tooltipTarget); } // 3. Disabled State const disabledTarget = document.querySelector('#demo-disabled'); if (disabledTarget && !disabledTarget.hasChildNodes()) { const DisabledDemo = () => { const selected = $('enabled'); return Div({ class: 'flex flex-col gap-3' }, [ Radio({ label: 'Enabled option', name: 'disabled-group', value: selected, radioValue: 'enabled', onclick: () => selected('enabled') }), Radio({ label: 'Disabled option (cannot select)', name: 'disabled-group', value: selected, radioValue: 'disabled', disabled: true, onclick: () => selected('disabled') }) ]); }; $mount(DisabledDemo, disabledTarget); } // 4. Reactive Preview const reactiveTarget = document.querySelector('#demo-reactive'); if (reactiveTarget && !reactiveTarget.hasChildNodes()) { const ReactiveDemo = () => { const size = $('medium'); const color = $('blue'); const sizes = [ { value: 'small', label: 'Small' }, { value: 'medium', label: 'Medium' }, { value: 'large', label: 'Large' } ]; const colors = [ { value: 'blue', label: 'Blue' }, { value: 'green', label: 'Green' }, { value: 'red', label: 'Red' } ]; return Div({ class: 'flex flex-col gap-4' }, [ Div({ class: 'text-sm font-bold' }, 'Select size'), Div({ class: 'flex gap-4' }, sizes.map(s => Radio({ label: s.label, name: 'size-group', value: size, radioValue: s.value, onclick: () => size(s.value) }) )), Div({ class: 'text-sm font-bold mt-2' }, 'Select color'), Div({ class: 'flex gap-4' }, colors.map(c => Radio({ label: c.label, name: 'color-group', value: color, radioValue: c.value, onclick: () => color(c.value) }) )), Div({ class: 'mt-4 p-4 rounded-lg text-center transition-all', style: () => { const sizeMap = { small: 'text-sm', medium: 'text-base', large: 'text-lg' }; const colorMap = { blue: '#3b82f6', green: '#10b981', red: '#ef4444' }; return `background-color: ${colorMap[color()]}; color: white; ${sizeMap[size()]}`; } }, () => `${size()} ${color()} preview`) ]); }; $mount(ReactiveDemo, reactiveTarget); } // 5. Payment Method Selection const paymentTarget = document.querySelector('#demo-payment'); if (paymentTarget && !paymentTarget.hasChildNodes()) { const PaymentDemo = () => { const method = $('credit'); return Div({ class: 'flex flex-col gap-4' }, [ Div({ class: 'text-sm font-bold' }, 'Payment method'), Div({ class: 'flex flex-col gap-3' }, [ Radio({ label: '💳 Credit Card', name: 'payment-group', value: method, radioValue: 'credit', onclick: () => method('credit') }), Radio({ label: '🏦 Bank Transfer', name: 'payment-group', value: method, radioValue: 'bank', onclick: () => method('bank') }), Radio({ label: '📱 Digital Wallet', name: 'payment-group', value: method, radioValue: 'wallet', onclick: () => method('wallet') }) ]), Div({ class: 'alert alert-info mt-2' }, () => { const messages = { credit: 'You selected Credit Card. Enter your card details.', bank: 'You selected Bank Transfer. Use the provided account number.', wallet: 'You selected Digital Wallet. Scan the QR code to pay.' }; return messages[method()]; }) ]); }; $mount(PaymentDemo, paymentTarget); } // 6. All Variants const variantsTarget = document.querySelector('#demo-variants'); if (variantsTarget && !variantsTarget.hasChildNodes()) { const VariantsDemo = () => { const primary = $('primary1'); const secondary = $('secondary1'); const accent = $('accent1'); return Div({ class: 'flex flex-col gap-4' }, [ Div({ class: 'card bg-base-200 p-4' }, [ Div({ class: 'text-sm font-bold mb-2' }, 'Primary variant'), Div({ class: 'flex gap-4' }, [ Radio({ label: 'Option A', name: 'primary-group', value: primary, radioValue: 'primary1', class: 'radio-primary', onclick: () => primary('primary1') }), Radio({ label: 'Option B', name: 'primary-group', value: primary, radioValue: 'primary2', class: 'radio-primary', onclick: () => primary('primary2') }) ]) ]), Div({ class: 'card bg-base-200 p-4' }, [ Div({ class: 'text-sm font-bold mb-2' }, 'Secondary variant'), Div({ class: 'flex gap-4' }, [ Radio({ label: 'Option A', name: 'secondary-group', value: secondary, radioValue: 'secondary1', class: 'radio-secondary', onclick: () => secondary('secondary1') }), Radio({ label: 'Option B', name: 'secondary-group', value: secondary, radioValue: 'secondary2', class: 'radio-secondary', onclick: () => secondary('secondary2') }) ]) ]), Div({ class: 'card bg-base-200 p-4' }, [ Div({ class: 'text-sm font-bold mb-2' }, 'Accent variant'), Div({ class: 'flex gap-4' }, [ Radio({ label: 'Option A', name: 'accent-group', value: accent, radioValue: 'accent1', class: 'radio-accent', onclick: () => accent('accent1') }), Radio({ label: 'Option B', name: 'accent-group', value: accent, radioValue: 'accent2', class: 'radio-accent', onclick: () => accent('accent2') }) ]) ]) ]); }; $mount(VariantsDemo, variantsTarget); } // 7. Dynamic Options const dynamicTarget = document.querySelector('#demo-dynamic'); if (dynamicTarget && !dynamicTarget.hasChildNodes()) { const DynamicDemo = () => { const category = $('cars'); const selected = $(''); const options = { cars: [ { value: 'sedan', label: 'Sedan' }, { value: 'suv', label: 'SUV' }, { value: 'sports', label: 'Sports' } ], colors: [ { value: 'red', label: 'Red' }, { value: 'blue', label: 'Blue' }, { value: 'black', label: 'Black' } ] }; return Div({ class: 'flex flex-col gap-4' }, [ Div({ class: 'flex gap-4' }, [ Radio({ label: 'Cars', name: 'category-group', value: category, radioValue: 'cars', onclick: () => { category('cars'); selected(''); } }), Radio({ label: 'Colors', name: 'category-group', value: category, radioValue: 'colors', onclick: () => { category('colors'); selected(''); } }) ]), Div({ class: 'divider my-1' }), Div({ class: 'text-sm font-bold' }, () => `Select ${category()}`), Div({ class: 'flex flex-col gap-2' }, () => options[category()].map(opt => Radio({ label: opt.label, name: 'dynamic-option-group', value: selected, radioValue: opt.value, onclick: () => selected(opt.value) }) ) ), () => selected() ? Div({ class: 'alert alert-success mt-2' }, () => `Selected ${category()}: ${selected()}`) : null ]); }; $mount(DynamicDemo, dynamicTarget); } }; initRadioExamples(); if (window.$docsify) { window.$docsify.plugins = [].concat(window.$docsify.plugins || [], (hook) => { hook.doneEach(initRadioExamples); }); } })(); </script>