A client-side React component that renders a list of toggleable push-button options with support for single/multi-select, section grouping, disabled states with tooltips, loading skeletons, and error handling. ## Key Components ### Exported Interfaces | Interface | Purpose | |---|---| | `SelectableOption` | Defines an individual selectable item with `id`, `name`, optional `displayName`, `icon`, `color`, `disabled`, `disabledReason`, and `section` fields | | `SectionDefinition` | Defines a labeled group for organizing options with `id`, `label`, optional `icon`, and `description` | ### Exported Component **`PushButtonSelector`** — Main component accepting `PushButtonSelectorProps`: | Prop | Type | Default | Description | |---|---|---|---| | `options` | `SelectableOption[]` | — | Items to display | | `selectedIds` | `string[]` | — | Currently selected IDs | | `onSelectionChange` | `(ids: string[]) => void` | — | Callback on toggle | | `multiSelect` | `boolean` | `true` | Allow multiple selections | | `sections` | `SectionDefinition[]` | — | Optional grouping definitions | | `selectionSummary` | `boolean` | `false` | Show badge summary of selections | | `optional` | `boolean` | `false` | Suppress empty-selection warning | | `isLoading` | `boolean` | `false` | Show skeleton placeholders | | `error` | `string \| null` | `null` | Show error state | ### Internal Components - **`PushButtonSelectorSkeleton`** — Animated placeholder cards during loading - **`PushButtonSelectorError`** — Error banner using ODS error tokens ## Usage Example ```typescript import { PushButtonSelector, SelectableOption, SectionDefinition } from './push-button-selector'; const platforms: SelectableOption[] = [ { id: 'connectwise', name: 'ConnectWise', displayName: 'ConnectWise Manage', description: 'PSA platform' }, { id: 'halo', name: 'HaloPSA', disabled: true, disabledReason: 'License required' }, ]; const sections: SectionDefinition[] = [ { id: 'psa', label: 'PSA Platforms', description: 'Choose your ticketing system' }, ]; ``` > **Note:** Disabled options that are already selected remain deselectable. A `disabledReason` surfaces via tooltip on hover using the shared `Tooltip` primitive.