# ToggleButton

A button component that maintains a pressed/unpressed state, functioning as a toggle between two states. It combines the visual appearance of a button with the state behavior of a toggle, making it perfect for scenarios where you need a button-like interface for binary choices or mode switches.

## Aliases

- ToggleButton
- PressButton
- StateButton

## Props Breakdown

**Extends:** `ButtonProps` (which extends `HTMLAttributes<HTMLButtonElement>` (excluding `style`), excluding `type` and `actionType`) and `ControlledFormComponentProps<boolean>`

| Prop | Type | Default | Required | Description |
|------|------|---------|----------|-------------|
| `defaultChecked` | `boolean` | `undefined` | No | Default value for uncontrolled component |
| `children` | `ReactNode` | `undefined` | No | Content of the button |
| `className` | `string` | `undefined` | No | Additional className for the toggle |
| `initialValue` | `boolean` | `undefined` | No | The initial value for the field |
| `checked` | `boolean` | `undefined` | No | The initial value for the field |
| `value` | `boolean` | `undefined` | No | The current value of the form field |
| `onValueChange` | `(value: boolean) => void` | `undefined` | No | Callback function that is called when the field value changes |
| `disabled` | `boolean` | `false` | No | Whether the form field is disabled and cannot be interacted with |
| `required` | `boolean` | `false` | No | Whether the form field must have a value |
| `invalid` | `boolean` | `false` | No | Whether the form field's current value is invalid |
| `id` | `string` | `undefined` | No | Id for the form field |
| `appearance` | `'Default' \| 'Inverse'` | `'Default'` | No | Appearance of the button |
| `style` | `'Primary' \| 'Secondary' \| 'Destructive'` | `'Primary'` | No | Style of the button |
| `size` | `'Small' \| 'Medium' \| 'Large'` | `'Medium'` | No | Size of the button |
| `loading` | `boolean` | `false` | No | Indicates if the button is in a loading state |
| `leadingIcon` | `ReactNode` | `undefined` | No | Icon to be displayed before the button's content |
| `trailingIcon` | `ReactNode` | `undefined` | No | Icon to be displayed after the button's content |
| `onClick` | `(event?: MouseEvent<HTMLElement>) => void` | `undefined` | No | Click event handler for the button |

Plus all standard HTML button attributes (id, title, aria-*, data-*, etc.).

## Examples

### Basic ToggleButton

```tsx
import { ToggleButton } from '@delightui/components';

function BasicToggleButtonExample() {
  const [isPressed, setIsPressed] = useState(false);

  return (
    <div>
      <p>Button state: {isPressed ? 'Pressed' : 'Not pressed'}</p>
      <ToggleButton
        value={isPressed}
        onValueChange={setIsPressed}
      >
        Toggle Me
      </ToggleButton>
    </div>
  );
}
```

### ToggleButton with Icons

```tsx
import { ToggleButton, Icon } from '@delightui/components';

function IconToggleButtonExample() {
  const [isFavorite, setIsFavorite] = useState(false);
  const [isBookmarked, setIsBookmarked] = useState(false);
  const [isLiked, setIsLiked] = useState(false);

  return (
    <div style={{ display: 'flex', gap: '12px', alignItems: 'center' }}>
      <ToggleButton
        value={isFavorite}
        onValueChange={setIsFavorite}
        leadingIcon={<Icon name={isFavorite ? 'CheckFilled' : 'CheckOutlined'} />}
        style={isFavorite ? 'Primary' : 'Secondary'}
      >
        {isFavorite ? 'Favorited' : 'Favorite'}
      </ToggleButton>

      <ToggleButton
        value={isBookmarked}
        onValueChange={setIsBookmarked}
        leadingIcon={<Icon name={isBookmarked ? 'AddFilled' : 'AddOutlined'} />}
        style={isBookmarked ? 'Primary' : 'Secondary'}
      >
        {isBookmarked ? 'Saved' : 'Save'}
      </ToggleButton>

      <ToggleButton
        value={isLiked}
        onValueChange={setIsLiked}
        leadingIcon={<Icon name={isLiked ? 'CheckFilled' : 'CheckOutlined'} />}
        style={isLiked ? 'Primary' : 'Secondary'}
        size="Small"
      >
        {isLiked ? 'Liked' : 'Like'}
      </ToggleButton>
    </div>
  );
}
```

### Different Sizes and Styles

```tsx
import { ToggleButton } from '@delightui/components';

function SizedToggleButtonExample() {
  const [states, setStates] = useState({
    small: false,
    medium: false,
    large: false
  });

  const updateState = (key: string, value: boolean) => {
    setStates(prev => ({ ...prev, [key]: value }));
  };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
      <div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>
        <ToggleButton
          value={states.small}
          onValueChange={(value) => updateState('small', value)}
          size="Small"
        >
          Small
        </ToggleButton>

        <ToggleButton
          value={states.medium}
          onValueChange={(value) => updateState('medium', value)}
          size="Medium"
        >
          Medium
        </ToggleButton>

        <ToggleButton
          value={states.large}
          onValueChange={(value) => updateState('large', value)}
          size="Large"
        >
          Large
        </ToggleButton>
      </div>

      <div style={{ display: 'flex', gap: '8px' }}>
        <ToggleButton
          value={false}
          style="Primary"
        >
          Primary
        </ToggleButton>

        <ToggleButton
          value={false}
          style="Secondary"
        >
          Secondary
        </ToggleButton>

        <ToggleButton
          value={false}
          style="Destructive"
        >
          Destructive
        </ToggleButton>
      </div>
    </div>
  );
}
```

### Toolbar with ToggleButtons

```tsx
import { ToggleButton, Icon } from '@delightui/components';

function ToolbarExample() {
  const [formatting, setFormatting] = useState({
    bold: false,
    italic: false,
    underline: false,
    alignLeft: true,
    alignCenter: false,
    alignRight: false
  });

  const updateFormatting = (key: string, value: boolean) => {
    if (key.startsWith('align')) {
      // Only one alignment can be active
      setFormatting(prev => ({
        ...prev,
        alignLeft: key === 'alignLeft' ? value : false,
        alignCenter: key === 'alignCenter' ? value : false,
        alignRight: key === 'alignRight' ? value : false
      }));
    } else {
      setFormatting(prev => ({ ...prev, [key]: value }));
    }
  };

  return (
    <div style={{ 
      display: 'flex', 
      gap: '4px', 
      padding: '8px',
      border: '1px solid #ccc',
      borderRadius: '8px',
      backgroundColor: '#f8f9fa'
    }}>
      {/* Text formatting */}
      <ToggleButton
        value={formatting.bold}
        onValueChange={(value) => updateFormatting('bold', value)}
        size="Small"
        leadingIcon={<Icon name="AddFilled" />}
        title="Bold"
      />

      <ToggleButton
        value={formatting.italic}
        onValueChange={(value) => updateFormatting('italic', value)}
        size="Small"
        leadingIcon={<Icon name="InfoFilled" />}
        title="Italic"
      />

      <ToggleButton
        value={formatting.underline}
        onValueChange={(value) => updateFormatting('underline', value)}
        size="Small"
        leadingIcon={<Icon name="AddFilled" />}
        title="Underline"
      />

      {/* Separator */}
      <div style={{ width: '1px', backgroundColor: '#ccc', margin: '0 4px' }} />

      {/* Alignment */}
      <ToggleButton
        value={formatting.alignLeft}
        onValueChange={(value) => updateFormatting('alignLeft', value)}
        size="Small"
        leadingIcon={<Icon name="AddFilled" />}
        title="Align Left"
      />

      <ToggleButton
        value={formatting.alignCenter}
        onValueChange={(value) => updateFormatting('alignCenter', value)}
        size="Small"
        leadingIcon={<Icon name="AddFilled" />}
        title="Align Center"
      />

      <ToggleButton
        value={formatting.alignRight}
        onValueChange={(value) => updateFormatting('alignRight', value)}
        size="Small"
        leadingIcon={<Icon name="AddFilled" />}
        title="Align Right"
      />
    </div>
  );
}
```

### Filter Buttons

```tsx
import { ToggleButton, Text } from '@delightui/components';

function FilterButtonsExample() {
  const [filters, setFilters] = useState({
    all: true,
    active: false,
    completed: false,
    overdue: false
  });

  const [tasks] = useState([
    { id: 1, title: 'Complete project', status: 'active', dueDate: '2024-04-01' },
    { id: 2, title: 'Review documents', status: 'completed', dueDate: '2024-03-28' },
    { id: 3, title: 'Send report', status: 'overdue', dueDate: '2024-03-20' },
    { id: 4, title: 'Team meeting', status: 'active', dueDate: '2024-04-05' }
  ]);

  const updateFilter = (key: string, value: boolean) => {
    if (key === 'all' && value) {
      setFilters({ all: true, active: false, completed: false, overdue: false });
    } else {
      const newFilters = { ...filters, [key]: value, all: false };
      if (!Object.values(newFilters).some(Boolean)) {
        newFilters.all = true;
      }
      setFilters(newFilters);
    }
  };

  const getFilteredTasks = () => {
    if (filters.all) return tasks;
    return tasks.filter(task => {
      if (filters.active && task.status === 'active') return true;
      if (filters.completed && task.status === 'completed') return true;
      if (filters.overdue && task.status === 'overdue') return true;
      return false;
    });
  };

  const filteredTasks = getFilteredTasks();

  return (
    <div>
      <Text weight="bold" style={{ marginBottom: '16px' }}>
        Task Filters
      </Text>

      <div style={{ display: 'flex', gap: '8px', marginBottom: '20px', flexWrap: 'wrap' }}>
        <ToggleButton
          value={filters.all}
          onValueChange={(value) => updateFilter('all', value)}
          size="Small"
        >
          All ({tasks.length})
        </ToggleButton>

        <ToggleButton
          value={filters.active}
          onValueChange={(value) => updateFilter('active', value)}
          size="Small"
          style="Primary"
        >
          Active ({tasks.filter(t => t.status === 'active').length})
        </ToggleButton>

        <ToggleButton
          value={filters.completed}
          onValueChange={(value) => updateFilter('completed', value)}
          size="Small"
          style="Secondary"
        >
          Completed ({tasks.filter(t => t.status === 'completed').length})
        </ToggleButton>

        <ToggleButton
          value={filters.overdue}
          onValueChange={(value) => updateFilter('overdue', value)}
          size="Small"
          style="Destructive"
        >
          Overdue ({tasks.filter(t => t.status === 'overdue').length})
        </ToggleButton>
      </div>

      <div>
        <Text weight="medium" style={{ marginBottom: '12px' }}>
          Showing {filteredTasks.length} tasks
        </Text>
        
        {filteredTasks.map(task => (
          <div key={task.id} style={{ 
            padding: '12px', 
            border: '1px solid #eee', 
            borderRadius: '4px',
            marginBottom: '8px'
          }}>
            <Text weight="medium">{task.title}</Text>
            <Text size="small" color="secondary" style={{ display: 'block', marginTop: '4px' }}>
              Status: {task.status} | Due: {task.dueDate}
            </Text>
          </div>
        ))}
      </div>
    </div>
  );
}
```

### View Mode Switcher

```tsx
import { ToggleButton, Icon } from '@delightui/components';

function ViewModeSwitcherExample() {
  const [viewMode, setViewMode] = useState('list');

  const viewModes = [
    { id: 'list', label: 'List View', icon: 'AddFilled' },
    { id: 'grid', label: 'Grid View', icon: 'AddFilled' },
    { id: 'card', label: 'Card View', icon: 'AddFilled' }
  ];

  const sampleData = [
    { id: 1, title: 'Item 1', description: 'Description for item 1' },
    { id: 2, title: 'Item 2', description: 'Description for item 2' },
    { id: 3, title: 'Item 3', description: 'Description for item 3' },
    { id: 4, title: 'Item 4', description: 'Description for item 4' }
  ];

  const renderContent = () => {
    switch (viewMode) {
      case 'list':
        return (
          <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
            {sampleData.map(item => (
              <div key={item.id} style={{ 
                display: 'flex', 
                alignItems: 'center', 
                gap: '12px',
                padding: '12px',
                border: '1px solid #eee',
                borderRadius: '4px'
              }}>
                <Text weight="medium">{item.title}</Text>
                <Text size="small" color="secondary">{item.description}</Text>
              </div>
            ))}
          </div>
        );
      
      case 'grid':
        return (
          <div style={{ 
            display: 'grid', 
            gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', 
            gap: '16px' 
          }}>
            {sampleData.map(item => (
              <div key={item.id} style={{ 
                padding: '16px',
                border: '1px solid #eee',
                borderRadius: '8px',
                textAlign: 'center'
              }}>
                <Text weight="medium" style={{ display: 'block', marginBottom: '8px' }}>
                  {item.title}
                </Text>
                <Text size="small" color="secondary">{item.description}</Text>
              </div>
            ))}
          </div>
        );
      
      case 'card':
        return (
          <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
            {sampleData.map(item => (
              <div key={item.id} style={{ 
                padding: '20px',
                border: '1px solid #eee',
                borderRadius: '12px',
                backgroundColor: '#f8f9fa'
              }}>
                <Text weight="bold" size="large" style={{ display: 'block', marginBottom: '12px' }}>
                  {item.title}
                </Text>
                <Text>{item.description}</Text>
              </div>
            ))}
          </div>
        );
      
      default:
        return null;
    }
  };

  return (
    <div>
      <div style={{ 
        display: 'flex', 
        justifyContent: 'space-between', 
        alignItems: 'center',
        marginBottom: '20px' 
      }}>
        <Text weight="bold">Content View</Text>
        
        <div style={{ display: 'flex', gap: '4px' }}>
          {viewModes.map(mode => (
            <ToggleButton
              key={mode.id}
              value={viewMode === mode.id}
              onValueChange={(value) => value && setViewMode(mode.id)}
              size="Small"
              leadingIcon={<Icon name={mode.icon} />}
              title={mode.label}
            />
          ))}
        </div>
      </div>

      {renderContent()}
    </div>
  );
}
```

### Settings Toggle Buttons

```tsx
import { ToggleButton, Icon, Text } from '@delightui/components';

function SettingsToggleButtonsExample() {
  const [settings, setSettings] = useState({
    notifications: true,
    autoSave: false,
    darkMode: false,
    compactView: false
  });

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

  return (
    <div style={{ maxWidth: '400px' }}>
      <Text weight="bold" size="large" style={{ marginBottom: '20px' }}>
        Quick Settings
      </Text>

      <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <div>
            <Text weight="medium">Notifications</Text>
            <Text size="small" color="secondary" style={{ display: 'block', marginTop: '2px' }}>
              Receive push notifications
            </Text>
          </div>
          <ToggleButton
            value={settings.notifications}
            onValueChange={(value) => updateSetting('notifications', value)}
            size="Small"
            leadingIcon={<Icon name={settings.notifications ? 'InfoFilled' : 'InfoOutlined'} />}
          >
            {settings.notifications ? 'On' : 'Off'}
          </ToggleButton>
        </div>

        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <div>
            <Text weight="medium">Auto Save</Text>
            <Text size="small" color="secondary" style={{ display: 'block', marginTop: '2px' }}>
              Automatically save your work
            </Text>
          </div>
          <ToggleButton
            value={settings.autoSave}
            onValueChange={(value) => updateSetting('autoSave', value)}
            size="Small"
            leadingIcon={<Icon name={settings.autoSave ? 'CheckFilled' : 'CheckOutlined'} />}
          >
            {settings.autoSave ? 'Enabled' : 'Disabled'}
          </ToggleButton>
        </div>

        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <div>
            <Text weight="medium">Dark Mode</Text>
            <Text size="small" color="secondary" style={{ display: 'block', marginTop: '2px' }}>
              Switch to dark theme
            </Text>
          </div>
          <ToggleButton
            value={settings.darkMode}
            onValueChange={(value) => updateSetting('darkMode', value)}
            size="Small"
            style={settings.darkMode ? 'Primary' : 'Secondary'}
          >
            {settings.darkMode ? '🌙 Dark' : '☀️ Light'}
          </ToggleButton>
        </div>

        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <div>
            <Text weight="medium">Compact View</Text>
            <Text size="small" color="secondary" style={{ display: 'block', marginTop: '2px' }}>
              Use smaller spacing
            </Text>
          </div>
          <ToggleButton
            value={settings.compactView}
            onValueChange={(value) => updateSetting('compactView', value)}
            size="Small"
            leadingIcon={<Icon name={settings.compactView ? 'AddFilled' : 'AddOutlined'} />}
          >
            {settings.compactView ? 'Compact' : 'Normal'}
          </ToggleButton>
        </div>
      </div>
    </div>
  );
}
```

### Form Integration

```tsx
import { Form, FormField, ToggleButton, Button, Text } from '@delightui/components';

function FormToggleButtonExample() {
  const handleSubmit = (data: any) => {
    console.log('Form submitted:', data);
  };

  return (
    <Form onSubmit={handleSubmit}>
      <Text weight="bold" style={{ marginBottom: '16px' }}>
        Subscription Preferences
      </Text>

      <FormField
        name="newsletter"
        label="Newsletter Subscription"
      >
        <ToggleButton
          initialValue={true}
          size="Small"
        >
          Subscribe to Newsletter
        </ToggleButton>
      </FormField>

      <FormField
        name="marketing"
        label="Marketing Emails"
      >
        <ToggleButton
          initialValue={false}
          size="Small"
        >
          Receive Marketing Emails
        </ToggleButton>
      </FormField>

      <FormField
        name="urgent"
        label="Urgent Notifications"
        required
      >
        <ToggleButton
          initialValue={true}
          size="Small"
          style="Primary"
        >
          Enable Urgent Notifications
        </ToggleButton>
      </FormField>

      <Button type="submit">
        Save Preferences
      </Button>
    </Form>
  );
}
```

### Disabled States

```tsx
import { ToggleButton, Icon } from '@delightui/components';

function DisabledToggleButtonExample() {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
      <div style={{ display: 'flex', gap: '8px' }}>
        <ToggleButton value={false}>
          Normal (Off)
        </ToggleButton>
        
        <ToggleButton value={true}>
          Normal (On)
        </ToggleButton>
      </div>

      <div style={{ display: 'flex', gap: '8px' }}>
        <ToggleButton value={false} disabled>
          Disabled (Off)
        </ToggleButton>
        
        <ToggleButton value={true} disabled>
          Disabled (On)
        </ToggleButton>
      </div>

      <div style={{ display: 'flex', gap: '8px' }}>
        <ToggleButton 
          value={false} 
          disabled
          leadingIcon={<Icon name="ErrorOutlined" />}
        >
          Disabled with Icon
        </ToggleButton>
        
        <ToggleButton 
          value={true} 
          disabled
          leadingIcon={<Icon name="CheckFilled" />}
        >
          Disabled Active
        </ToggleButton>
      </div>
    </div>
  );
}
```

### Loading State

```tsx
import { ToggleButton, Spinner, Button } from '@delightui/components';

function LoadingToggleButtonExample() {
  const [isLoading, setIsLoading] = useState(false);
  const [isToggled, setIsToggled] = useState(false);

  const handleToggle = async (value: boolean) => {
    setIsLoading(true);
    // Simulate API call
    await new Promise(resolve => setTimeout(resolve, 2000));
    setIsToggled(value);
    setIsLoading(false);
  };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
      <ToggleButton
        value={isToggled}
        onValueChange={handleToggle}
        loading={isLoading}
        disabled={isLoading}
        leadingIcon={isLoading ? <Spinner /> : undefined}
      >
        {isLoading ? 'Saving...' : isToggled ? 'Feature Enabled' : 'Enable Feature'}
      </ToggleButton>

      <Button 
        size="Small" 
        type="Outlined"
        onClick={() => handleToggle(!isToggled)}
        disabled={isLoading}
      >
        Toggle Programmatically
      </Button>
    </div>
  );
}
```