# RadioGroup

## Description

A group container component for radio button options that manages selection state and provides coordinated behavior between radio button children. Supports both horizontal and vertical layouts, form integration, controlled and uncontrolled modes, and accessibility features for creating option selectors, preference settings, and choice-based inputs.

## Aliases

- RadioGroup
- RadioButtonGroup
- OptionGroup
- ChoiceGroup
- SelectionGroup
- RadioSet

## Props Breakdown

**Extends:** ControlledFormComponentProps<string | number>

| Prop | Type | Default | Required | Description |
|------|------|---------|----------|-------------|
| `children` | `ReactElement<RadioButtonProps> \| ReactElement<RadioButtonProps>[]` | - | Yes | The radio buttons to render in the group |
| `orientation` | `'horizontal' \| 'vertical'` | `'vertical'` | No | Layout orientation of the radio group |
| `value` | `string \| number` | - | No | Current selected value (controlled mode) |
| `onValueChange` | `(value: string \| number) => void` | - | No | Callback when selection changes |
| `disabled` | `boolean` | `false` | No | Whether the entire group is disabled |
| `required` | `boolean` | `false` | No | Whether a selection is required |
| `invalid` | `boolean` | `false` | No | Whether the current selection is invalid |
| `className` | `string` | - | No | Additional CSS class names |

## Examples

### Basic Usage
```tsx
import { RadioGroup, RadioButton } from '@delightui/components';

function BasicExample() {
  const [selectedSize, setSelectedSize] = useState('medium');

  return (
    <div className="size-selector">
      <Text type="Heading6">Select Size</Text>
      
      <RadioGroup 
        value={selectedSize}
        onValueChange={setSelectedSize}
      >
        <RadioButton value="small" label="Small" />
        <RadioButton value="medium" label="Medium" />
        <RadioButton value="large" label="Large" />
        <RadioButton value="xlarge" label="Extra Large" />
      </RadioGroup>
      
      <Text type="BodySmall">
        Selected: {selectedSize}
      </Text>
    </div>
  );
}
```

### Horizontal Layout
```tsx
function HorizontalLayoutExample() {
  const [paymentMethod, setPaymentMethod] = useState('credit');

  return (
    <div className="payment-options">
      <Text type="Heading6">Payment Method</Text>
      
      <RadioGroup 
        value={paymentMethod}
        onValueChange={setPaymentMethod}
        orientation="horizontal"
        className="payment-radio-group"
      >
        <RadioButton 
          value="credit" 
          label="Credit Card"
        />
        <RadioButton 
          value="debit" 
          label="Debit Card"
        />
        <RadioButton 
          value="paypal" 
          label="PayPal"
        />
        <RadioButton 
          value="bank" 
          label="Bank Transfer"
        />
      </RadioGroup>
      
      <div className="payment-info">
        <Text type="BodySmall">
          You selected: {paymentMethod.replace(/^\w/, c => c.toUpperCase())}
        </Text>
      </div>
    </div>
  );
}
```

### Form Integration
```tsx
function FormIntegrationExample() {
  const handleSubmit = (values, setError) => {
    if (!values.priority) {
      setError('priority', 'Please select a priority level');
      return;
    }
    
    console.log('Form submitted:', values);
  };

  return (
    <Form onSubmit={handleSubmit}>
      <FormField 
        name="title" 
        label="Issue Title" 
        required
      >
        <Input placeholder="Describe the issue" />
      </FormField>
      
      <FormField 
        name="priority" 
        label="Priority Level" 
        required
      >
        <RadioGroup>
          <RadioButton 
            value="low" 
            label="Low Priority"
            description="Minor issues, can wait"
          />
          <RadioButton 
            value="medium" 
            label="Medium Priority"
            description="Important but not urgent"
          />
          <RadioButton 
            value="high" 
            label="High Priority"
            description="Needs immediate attention"
          />
          <RadioButton 
            value="critical" 
            label="Critical"
            description="System down or major issue"
          />
        </RadioGroup>
      </FormField>
      
      <FormField name="description" label="Description">
        <TextArea 
          placeholder="Additional details..."
          rows={3}
        />
      </FormField>
      
      <Button actionType="submit">
        Submit Issue
      </Button>
    </Form>
  );
}
```

### Product Selection
```tsx
function ProductSelectionExample() {
  const [selectedPlan, setSelectedPlan] = useState('');
  
  const plans = [
    {
      id: 'basic',
      name: 'Basic Plan',
      price: '$9.99/month',
      features: ['5 Projects', '10GB Storage', 'Email Support'],
      recommended: false
    },
    {
      id: 'pro',
      name: 'Pro Plan',
      price: '$19.99/month',
      features: ['Unlimited Projects', '100GB Storage', 'Priority Support', 'Advanced Analytics'],
      recommended: true
    },
    {
      id: 'enterprise',
      name: 'Enterprise Plan',
      price: '$49.99/month',
      features: ['Everything in Pro', 'Custom Integrations', 'Dedicated Manager', 'SLA Guarantee'],
      recommended: false
    }
  ];

  return (
    <div className="plan-selector">
      <Text type="Heading5">Choose Your Plan</Text>
      
      <RadioGroup 
        value={selectedPlan}
        onValueChange={setSelectedPlan}
        className="plan-radio-group"
      >
        <List
          data={plans}
          component={({ id, name, price, features, recommended }) => {
            const FeatureComponent = ({ feature }) => (
              <div className="feature-item">
                <Icon icon="Check" className="feature-icon" />
                <Text type="BodySmall">{feature}</Text>
              </div>
            );

            return (
              <div className="plan-option">
                <div className="plan-header">
                  <RadioButton 
                    value={id}
                    label={
                      <div className="plan-title">
                        <Text type="Heading6">{name}</Text>
                        {recommended && (
                          <Chip size="Small" style="Primary">
                            Recommended
                          </Chip>
                        )}
                      </div>
                    }
                  />
                  <Text type="Heading6" className="plan-price">
                    {price}
                  </Text>
                </div>
                
                <div className="plan-features">
                  <List
                    data={features.map(feature => ({ feature }))}
                    component={FeatureComponent}
                    keyExtractor={(item) => item.feature}
                  />
                </div>
              </div>
            );
          }}
          keyExtractor={(plan) => plan.id}
        />
      </RadioGroup>
      
      <div className="plan-actions">
        <Button 
          disabled={!selectedPlan}
          onClick={() => console.log('Selected plan:', selectedPlan)}
        >
          Continue with {plans.find(p => p.id === selectedPlan)?.name || 'Selected Plan'}
        </Button>
      </div>
    </div>
  );
}
```

### Settings Configuration
```tsx
function SettingsConfigExample() {
  const [settings, setSettings] = useState({
    theme: 'light',
    notifications: 'email',
    privacy: 'friends',
    language: 'en'
  });

  const updateSetting = (key, value) => {
    setSettings(prev => ({ ...prev, [key]: value }));
  };

  return (
    <div className="settings-panel">
      <Text type="Heading5">Preferences</Text>
      
      <div className="settings-section">
        <Text type="Heading6">Theme</Text>
        <RadioGroup 
          value={settings.theme}
          onValueChange={(value) => updateSetting('theme', value)}
          orientation="horizontal"
        >
          <RadioButton 
            value="light" 
            label="Light"
          />
          <RadioButton 
            value="dark" 
            label="Dark"
          />
          <RadioButton 
            value="auto" 
            label="Auto"
          />
        </RadioGroup>
      </div>
      
      <div className="settings-section">
        <Text type="Heading6">Notifications</Text>
        <RadioGroup 
          value={settings.notifications}
          onValueChange={(value) => updateSetting('notifications', value)}
        >
          <RadioButton 
            value="all" 
            label="All Notifications"
            description="Receive all notifications via email and push"
          />
          <RadioButton 
            value="email" 
            label="Email Only"
            description="Only receive email notifications"
          />
          <RadioButton 
            value="push" 
            label="Push Only"
            description="Only receive push notifications"
          />
          <RadioButton 
            value="none" 
            label="None"
            description="Disable all notifications"
          />
        </RadioGroup>
      </div>
      
      <div className="settings-section">
        <Text type="Heading6">Privacy</Text>
        <RadioGroup 
          value={settings.privacy}
          onValueChange={(value) => updateSetting('privacy', value)}
        >
          <RadioButton 
            value="public" 
            label="Public"
            description="Anyone can see your profile"
          />
          <RadioButton 
            value="friends" 
            label="Friends Only"
            description="Only friends can see your profile"
          />
          <RadioButton 
            value="private" 
            label="Private"
            description="Only you can see your profile"
          />
        </RadioGroup>
      </div>
      
      <div className="settings-actions">
        <Button type="Outlined">
          Reset to Defaults
        </Button>
        <Button>
          Save Settings
        </Button>
      </div>
    </div>
  );
}
```

### Survey Question
```tsx
function SurveyQuestionExample() {
  const [answers, setAnswers] = useState({});
  const [currentQuestion, setCurrentQuestion] = useState(0);
  
  const questions = [
    {
      id: 'satisfaction',
      question: 'How satisfied are you with our service?',
      options: [
        { value: 'very-satisfied', label: 'Very Satisfied', emoji: '😍' },
        { value: 'satisfied', label: 'Satisfied', emoji: '😊' },
        { value: 'neutral', label: 'Neutral', emoji: '😐' },
        { value: 'dissatisfied', label: 'Dissatisfied', emoji: '😞' },
        { value: 'very-dissatisfied', label: 'Very Dissatisfied', emoji: '😤' }
      ]
    },
    {
      id: 'recommend',
      question: 'How likely are you to recommend us to others?',
      options: [
        { value: '10', label: 'Extremely Likely (10)' },
        { value: '9', label: 'Very Likely (9)' },
        { value: '8', label: 'Likely (8)' },
        { value: '7', label: 'Somewhat Likely (7)' },
        { value: '6', label: 'Neutral (6)' },
        { value: '5', label: 'Somewhat Unlikely (5)' },
        { value: '4', label: 'Unlikely (4)' },
        { value: '3', label: 'Very Unlikely (3)' },
        { value: '2', label: 'Extremely Unlikely (2)' },
        { value: '1', label: 'Not at All Likely (1)' }
      ]
    }
  ];

  const currentQ = questions[currentQuestion];
  
  const nextQuestion = () => {
    if (currentQuestion < questions.length - 1) {
      setCurrentQuestion(prev => prev + 1);
    }
  };

  const prevQuestion = () => {
    if (currentQuestion > 0) {
      setCurrentQuestion(prev => prev - 1);
    }
  };

  const updateAnswer = (questionId, value) => {
    setAnswers(prev => ({ ...prev, [questionId]: value }));
  };

  return (
    <div className="survey-form">
      <div className="survey-header">
        <Text type="Heading5">Customer Feedback Survey</Text>
        <Text type="BodySmall">
          Question {currentQuestion + 1} of {questions.length}
        </Text>
      </div>
      
      <ProgressBar 
        value={((currentQuestion + 1) / questions.length) * 100}
        showLabel="Text"
        label={`${currentQuestion + 1} of ${questions.length} completed`}
      />
      
      <div className="survey-question">
        <Text type="Heading6">{currentQ.question}</Text>
        
        <RadioGroup 
          value={answers[currentQ.id] || ''}
          onValueChange={(value) => updateAnswer(currentQ.id, value)}
          className="survey-options"
        >
          {currentQ.options.map(option => (
            <RadioButton 
              key={option.value}
              value={option.value}
              label={
                <div className="survey-option">
                  {option.emoji && (
                    <span className="option-emoji">{option.emoji}</span>
                  )}
                  <Text>{option.label}</Text>
                </div>
              }
            />
          ))}
        </RadioGroup>
      </div>
      
      <div className="survey-navigation">
        <Button 
          type="Outlined"
          onClick={prevQuestion}
          disabled={currentQuestion === 0}
        >
          Previous
        </Button>
        
        <div className="survey-progress">
          {questions.map((_, index) => (
            <div 
              key={index}
              className={`progress-dot ${
                index === currentQuestion ? 'current' : 
                answers[questions[index].id] ? 'completed' : 'pending'
              }`}
            />
          ))}
        </div>
        
        <Button 
          onClick={nextQuestion}
          disabled={!answers[currentQ.id] || currentQuestion === questions.length - 1}
        >
          {currentQuestion === questions.length - 1 ? 'Submit' : 'Next'}
        </Button>
      </div>
    </div>
  );
}
```

### Shipping Options
```tsx
function ShippingOptionsExample() {
  const [selectedShipping, setSelectedShipping] = useState('');
  
  const shippingOptions = [
    {
      id: 'standard',
      name: 'Standard Shipping',
      price: 'Free',
      duration: '5-7 business days',
      description: 'Free standard delivery'
    },
    {
      id: 'express',
      name: 'Express Shipping',
      price: '$9.99',
      duration: '2-3 business days',
      description: 'Faster delivery for urgent orders'
    },
    {
      id: 'overnight',
      name: 'Overnight Delivery',
      price: '$24.99',
      duration: '1 business day',
      description: 'Next business day delivery'
    },
    {
      id: 'weekend',
      name: 'Weekend Delivery',
      price: '$19.99',
      duration: 'Saturday delivery',
      description: 'Delivered on Saturday'
    }
  ];

  const selectedOption = shippingOptions.find(opt => opt.id === selectedShipping);

  return (
    <div className="shipping-selector">
      <Text type="Heading6">Choose Shipping Method</Text>
      
      <RadioGroup 
        value={selectedShipping}
        onValueChange={setSelectedShipping}
        required
        className="shipping-options"
      >
        {shippingOptions.map(option => (
          <div key={option.id} className="shipping-option">
            <RadioButton 
              value={option.id}
              label={
                <div className="shipping-details">
                  <div className="shipping-header">
                    <Text type="BodyMedium">{option.name}</Text>
                    <Text type="BodyMedium" className="shipping-price">
                      {option.price}
                    </Text>
                  </div>
                  
                  <div className="shipping-info">
                    <Text type="BodySmall" className="delivery-time">
                      <Icon icon="Clock" size="Small" />
                      {option.duration}
                    </Text>
                    <Text type="BodySmall" className="shipping-desc">
                      {option.description}
                    </Text>
                  </div>
                </div>
              }
            />
          </div>
        ))}
      </RadioGroup>
      
      {selectedOption && (
        <div className="shipping-summary">
          <Text type="BodySmall">
            Selected: {selectedOption.name} - {selectedOption.price}
          </Text>
          <Text type="BodySmall">
            Estimated delivery: {selectedOption.duration}
          </Text>
        </div>
      )}
    </div>
  );
}
```

### Quiz Question
```tsx
function QuizQuestionExample() {
  const [selectedAnswer, setSelectedAnswer] = useState('');
  const [showResult, setShowResult] = useState(false);
  
  const question = {
    question: 'What is the capital of France?',
    options: [
      { id: 'a', text: 'London', correct: false },
      { id: 'b', text: 'Berlin', correct: false },
      { id: 'c', text: 'Paris', correct: true },
      { id: 'd', text: 'Madrid', correct: false }
    ]
  };

  const submitAnswer = () => {
    setShowResult(true);
  };

  const resetQuestion = () => {
    setSelectedAnswer('');
    setShowResult(false);
  };

  const correctAnswer = question.options.find(opt => opt.correct);
  const selectedOption = question.options.find(opt => opt.id === selectedAnswer);
  const isCorrect = selectedOption?.correct || false;

  return (
    <div className="quiz-question">
      <Text type="Heading6">Quiz Question</Text>
      
      <div className="question-text">
        <Text type="BodyMedium">{question.question}</Text>
      </div>
      
      <RadioGroup 
        value={selectedAnswer}
        onValueChange={setSelectedAnswer}
        disabled={showResult}
        className="quiz-options"
      >
        {question.options.map(option => (
          <div 
            key={option.id}
            className={`quiz-option ${
              showResult ? (
                option.correct ? 'correct' : 
                option.id === selectedAnswer && !option.correct ? 'incorrect' : 
                'neutral'
              ) : ''
            }`}
          >
            <RadioButton 
              value={option.id}
              label={
                <div className="option-content">
                  <Text>{option.id.toUpperCase()}. {option.text}</Text>
                  {showResult && option.correct && (
                    <Icon icon="CheckCircle" className="correct-icon" />
                  )}
                  {showResult && option.id === selectedAnswer && !option.correct && (
                    <Icon icon="XCircle" className="incorrect-icon" />
                  )}
                </div>
              }
            />
          </div>
        ))}
      </RadioGroup>
      
      {!showResult ? (
        <Button 
          onClick={submitAnswer}
          disabled={!selectedAnswer}
        >
          Submit Answer
        </Button>
      ) : (
        <div className="quiz-result">
          <div className={`result-message ${isCorrect ? 'correct' : 'incorrect'}`}>
            <Icon 
              icon={isCorrect ? 'CheckCircle' : 'XCircle'} 
              className="result-icon"
            />
            <Text type="BodyMedium">
              {isCorrect ? 'Correct!' : 'Incorrect'}
            </Text>
          </div>
          
          {!isCorrect && (
            <Text type="BodySmall">
              The correct answer is: {correctAnswer.text}
            </Text>
          )}
          
          <Button type="Outlined" onClick={resetQuestion}>
            Try Again
          </Button>
        </div>
      )}
    </div>
  );
}
```

### Accessibility Enhanced RadioGroup
```tsx
function AccessibilityExample() {
  const [accessibility, setAccessibility] = useState({
    fontSize: 'medium',
    contrast: 'normal',
    motionPreference: 'normal'
  });

  const updateAccessibility = (key, value) => {
    setAccessibility(prev => ({ ...prev, [key]: value }));
  };

  return (
    <div className="accessibility-settings">
      <Text type="Heading5">Accessibility Preferences</Text>
      
      <div className="accessibility-section">
        <Text type="Heading6">Font Size</Text>
        <Text type="BodySmall">
          Choose a comfortable reading size
        </Text>
        
        <RadioGroup 
          value={accessibility.fontSize}
          onValueChange={(value) => updateAccessibility('fontSize', value)}
          orientation="horizontal"
          className="font-size-options"
        >
          <RadioButton 
            value="small" 
            label="Small"
            aria-describedby="font-small-desc"
          />
          <RadioButton 
            value="medium" 
            label="Medium"
            aria-describedby="font-medium-desc"
          />
          <RadioButton 
            value="large" 
            label="Large"
            aria-describedby="font-large-desc"
          />
          <RadioButton 
            value="xlarge" 
            label="Extra Large"
            aria-describedby="font-xlarge-desc"
          />
        </RadioGroup>
      </div>
      
      <div className="accessibility-section">
        <Text type="Heading6">Color Contrast</Text>
        <Text type="BodySmall">
          Adjust contrast for better visibility
        </Text>
        
        <RadioGroup 
          value={accessibility.contrast}
          onValueChange={(value) => updateAccessibility('contrast', value)}
        >
          <RadioButton 
            value="normal" 
            label="Normal Contrast"
            description="Standard color scheme"
          />
          <RadioButton 
            value="high" 
            label="High Contrast"
            description="Enhanced contrast for better readability"
          />
          <RadioButton 
            value="dark" 
            label="Dark Mode"
            description="Dark background with light text"
          />
        </RadioGroup>
      </div>
      
      <div className="accessibility-section">
        <Text type="Heading6">Motion Preference</Text>
        <Text type="BodySmall">
          Control animations and transitions
        </Text>
        
        <RadioGroup 
          value={accessibility.motionPreference}
          onValueChange={(value) => updateAccessibility('motionPreference', value)}
        >
          <RadioButton 
            value="normal" 
            label="Normal Motion"
            description="Standard animations and transitions"
          />
          <RadioButton 
            value="reduced" 
            label="Reduced Motion"
            description="Minimal animations for sensitivity"
          />
          <RadioButton 
            value="none" 
            label="No Motion"
            description="Disable all animations"
          />
        </RadioGroup>
      </div>
      
      <div className="preview-section">
        <Text type="Heading6">Preview</Text>
        <div 
          className={`preview-area 
            font-${accessibility.fontSize} 
            contrast-${accessibility.contrast} 
            motion-${accessibility.motionPreference}`}
        >
          <Text>This is how your settings will look.</Text>
          <Button size="Small">Sample Button</Button>
        </div>
      </div>
      
      <div className="accessibility-actions">
        <Button type="Outlined">
          Reset Defaults
        </Button>
        <Button>
          Apply Settings
        </Button>
      </div>
    </div>
  );
}
```