# ASChoiceBar

ASChoiceBar is a responsive item selector. It reports an item ID; it does not own routes, URLs, or page content.

## Display modes

- **Desktop:** displays as many items as the available width allows in a horizontal row. Items share spare horizontal space evenly. When their combined width exceeds the available space, the row scrolls horizontally to reach additional items using horizontal gestures or Shift+wheel. Ctrl+wheel and pinch gestures remain available for browser zoom. Clicking an item selects it and smoothly centers it within the scrollable row where the scroll boundaries allow. Reduced-motion preferences disable the animation. Desktop does not open a picker dialog.
- **Mobile:** displays the selected item between previous and next arrows. Activating the selected item opens a modal containing every option in one column. The list scrolls vertically when it exceeds the available viewport height.
- In both modes, arrows select the adjacent item. They stop at the first and last item rather than wrapping.

By default, the viewport breakpoint is 768px. `styleOptions.$displayModeOverride` accepts `DisplayMode.Desktop`, `DisplayMode.Mobile`, or `DisplayMode.None` (automatic). `$disableTransitionsBetweenDisplayModes` freezes the initial viewport-based choice. It does not disable visual animations.

## Usage

```tsx
<ASChoiceBar
  navItems={[
    { itemId: 'overview', displayText: 'Overview' },
    { itemId: 'details', displayText: 'Details' },
  ]}
  selectedItemId={selectedId}
  onItemSelected={setSelectedId}
/>
```

Items have a stable `itemId`, visible `displayText`, and an optional decorative `icon` React node. `size` defaults to `ComponentSize.Medium`; small, medium, and large are supported. Keep IDs unique within an item list.

## Props and defaults

| Prop | Behavior | Default |
| --- | --- | --- |
| `navItems` | Ordered options with unique IDs within this list | `[]` |
| `selectedItemId` | Parent-controlled selection when supplied | Internal selection of the first available option |
| `onItemSelected` | Receives the requested item ID after user activation | No callback |
| `size` | Shared bar and option size | `ComponentSize.Medium` |
| `theme` / `themeOverrides` | Complete replacement or partial inherited theme changes | Inherited theme |
| `id` | ID of the responsive wrapper | Generated unique ID |
| `className` | Class on the active desktop or mobile bar | Empty |
| `styleOptions` | Outer spacing, maximum width, responsive mode, and desktop visibility defaults | Automatic mode; breakpoint `768px` |
| `dwStyleOptions` | Desktop padding/radius and arrow/scrollbar visibility overrides | Arrows visible; scrollbar hidden |
| `mwStyleOptions` | Mobile radius and maximum width overrides | Maximum width `100%` |

The bar supplies one theme and size to all options. Optional `theme` and `size` fields retained on the item type are compatibility metadata; they do not override the containing bar.

## Selection ownership

Supplying `selectedItemId` makes selection controlled: `onItemSelected` requests a new ID, and the displayed selection changes when the parent updates the prop. Without that prop, the component maintains selection internally. Empty lists have no selected item; an unknown or removed ID falls back to the first available item. In uncontrolled mode that fallback becomes the stored selection, so reintroducing a removed ID does not restore the old selection. Initialization and prop synchronization do not emit selection callbacks. Item IDs only need to be unique within their own list; multiple selectors can reuse them.

## Theme and layout

Use `ASThemeProvider` for an inherited theme, `theme` for a complete replacement, or `themeOverrides` for partial changes. Do not pass both theme props together.

`components.choicebar` defines the bar background and shadow, item text and selected appearance, picker appearance, typography, and sizes. Arrow buttons use `components.iconbutton`, scaled to 80% in mobile and 75% in desktop for all sizes. See the [theme property reference](./theme-reference.md#aschoicebar--componentschoicebar) for every choicebar slot and preset default. The mobile overlay uses ASModal for positioning and its backdrop, with the choicebar background applied to the picker surface. The option list remains inside the modal and owns its vertical scrolling. `pickerWidth` controls the modal width and `pickerMaxHeight` limits the list height. Short lists use their natural height. The modal adds no padding because `pickerPadding` supplies the spacing inside the picker.

```tsx
<ASChoiceBar
  navItems={items}
  themeOverrides={{
    components: {
      choicebar: {
        pickerWidth: 'min(560px, calc(100vw - 48px))',
        pickerMaxHeight: '75dvh',
        background: '#102030',
        itemColor: '#dce9f5',
        selectedBackground: '#b7ddff',
        selectedColor: '#102030',
      },
    },
  }}
/>
```

`styleOptions` configures the responsive wrapper; `dwStyleOptions` and `mwStyleOptions` configure the respective mode. Supported layout overrides take precedence over the corresponding theme defaults. Use outer `styleOptions.$margin` and `$padding` for surrounding spacing; mobile keeps its internal arrow gutters reserved. Mobile width accommodates the widest option (including its icon) and stays unchanged when selection changes, capped at the available width. Arrow selection slides the options in the corresponding direction while the arrows remain stationary. Reduced-motion preferences disable the slide. Labels stay on one line and truncate with an ellipsis when space is insufficient; the arrows remain visible. `$hideNavArrowButtonsInDW` and `$hideHorizontalScrollbarInDW` describe desktop-only presentation.

## Accessibility

Give options meaningful text. Icons should not be the only way to distinguish items. Selection does not navigate automatically: consumers decide what content changes when `onItemSelected` runs. Items and arrows support Enter and Space. The selected item exposes aria-current. The mobile picker focuses the selected option, keeps Tab within its controls, and closes with Escape, the backdrop, or a selection. Closing returns focus to the selected mobile item.

Visible scrollbars use `components.choicebar.scrollbarColor` for both standard and WebKit scrollbar styling. Scrollbar hiding remains controlled by the existing display options.
