# List

A list is a collection of items or information repeated in a vertical stack. Use lists to make information easy to scan and access.

## Best practices

### Do

- Use a list for independent, vertically stacked, scannable items.
- Keep item structures and line lengths parallel.
- Visually group a list with related content.

### Don't

- Use a list for nested hierarchy; use a tree.
- Use a list for related columns; use a data grid or table.
- Include empty or disabled list items.

## Behavior and states

- For a single action, clicking a list item or pressing Enter or Space while it has focus initiates the action.
- For secondary actions, use the Right Arrow key to navigate into the list item.
- Use the Left Arrow key or Esc to return to the parent container.
- If selection is the only action, clicking the item or pressing Space or Enter triggers selection.
- For multi-select interactions, each list item is accompanied by a checkbox.
- The list of options stays open until someone dismisses it by clicking off the list or pressing Esc.
- If selections exceed the width of the container, the field shows how many options are selected.
- Items in a list are independent of one another.
- If you need a way to display information in columns that relate to each other, try a DataGrid or Table.
- If you need nested hierarchy in your list, try Tree.

## Default

Source: CoreAI.

[Download source](/coreai-design-system/source/examples/components-list--default.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeResetStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { List } from "@coreai-ds/react-components";
import { ListItem } from "@coreai-ds/react-components";
import { Text } from "@coreai-ds/react-components";
import * as React from 'react';

const useTextStyle = makeResetStyles({
    color: tokens.colorNeutralForeground1,
});

export const Default = (): JSXElement => {
    const textStyle = useTextStyle();
    return (<List>
      <ListItem>
        <Text className={textStyle}>Asia</Text>
      </ListItem>
      <ListItem>
        <Text className={textStyle}>Africa</Text>
      </ListItem>
      <ListItem>
        <Text className={textStyle}>Europe</Text>
      </ListItem>
      <ListItem>
        <Text className={textStyle}>North America</Text>
      </ListItem>
      <ListItem>
        <Text className={textStyle}>South America</Text>
      </ListItem>
      <ListItem>
        <Text className={textStyle}>Australia/Oceania</Text>
      </ListItem>
      <ListItem>
        <Text className={textStyle}>Antarctica</Text>
      </ListItem>
    </List>);
};

export default Default;
```

## API

Generated CoreAI prop summaries, not replacement type declarations. Most native DOM/event and ARIA props are omitted. `?` means optional; JSDoc shows defaults, deprecations, and conditional requirements. Defaults assume the standard CoreAI provider.

### List API

```ts
interface ListProps {
  as?: "div" | "ol" | "ul";

  children?: any;

  className?: string;

  defaultSelectedItems?: SelectionItemId[];

  navigationMode?: "items" | "composite";

  onSelectionChange?: EventHandler<OnListSelectionChangeData>;

  ref?: Ref<HTMLDivElement | HTMLUListElement>;

  selectedItems?: SelectionItemId[];

  selectionMode?: "multiselect" | "single";

  style?: CSSProperties;
}
```

## Implementation

CoreAI 0.12.0; Fluent 9.74.9.

[Setup and dependencies](/coreai-design-system/guides/Package.md).

Import components from `@coreai-ds/react-components`. CoreAI guidance above takes precedence over API demonstration examples.

Note: List examples reuse selection values as DOM IDs. Run one example at a time to keep IDs unique.

## List Active Element

Source: Fluent, adapted for CoreAI.

You can use selection and custom styles to show the active element in a different way. This is useful for scenarios where you want to show the details of the selected item, for example.

In this example, we are also demonstrating how the `onFocus` prop can be utilized to change the selected item immediately upon receiving focus. This allows us to show the details of the selected item in the right panel as user navigates through the list with the keyboard.

[Download source](/coreai-design-system/source/examples/components-list--list-active-element.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import * as React from 'react';
import type { SelectionItemId } from "@coreai-ds/react-components";
import { List } from "@coreai-ds/react-components";
import { ListItem } from "@coreai-ds/react-components";
import { mergeClasses } from "@coreai-ds/react-components";
import { Persona } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { Mic16Regular } from "@fluentui/react-icons";
import { Text } from "@coreai-ds/react-components";

const useStyles = makeStyles({
    selectedInfo: {
        marginTop: '16px',
    },
    buttonWrapper: {
        alignSelf: 'center',
    },
    item: {
        cursor: 'pointer',
        padding: '2px 6px',
        justifyContent: 'space-between',
    },
    itemSelected: {
        backgroundColor: tokens.colorSubtleBackgroundSelected,
        '@media (forced-colors:active)': {
            background: 'Highlight',
        },
    },
    personaSelected: {
        '@media (forced-colors:active)': {
            forcedColorAdjust: 'none',
            color: 'HighlightText',
        },
    },
});

type Item = {
    name: string;
    id: string;
    avatar: string;
};

const items: Item[] = [
    'Melda Bevel',
    'Demetra Manwaring',
    'Eusebia Stufflebeam',
    'Israel Rabin',
    'Bart Merrill',
    'Sonya Farner',
    'Kristan Cable',
].map(name => ({
    name,
    id: name,
    avatar: 'https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/office-ui-fabric-react-assets/persona-male.png',
}));

export const ListActiveElement = (): JSXElement => {
    const classes = useStyles();
    const [selectedItems, setSelectedItems] = React.useState<SelectionItemId[]>(['Melda Bevel']);
    const onSelectionChange = React.useCallback((_: React.SyntheticEvent | Event, data: {
        selectedItems: SelectionItemId[];
    }) => {
        setSelectedItems(data.selectedItems);
    }, []);
    const onFocus = React.useCallback((event: React.FocusEvent<HTMLLIElement>) => {
        // Ignore bubbled up events from the children
        if (event.target !== event.currentTarget) {
            return;
        }
        setSelectedItems([event.currentTarget.dataset.value as SelectionItemId]);
    }, []);
    return (<div>
      <List selectionMode="single" navigationMode="composite" selectedItems={selectedItems} onSelectionChange={onSelectionChange}>
        {items.map(({ name, avatar }) => (<ListItem key={name} value={name} className={mergeClasses(classes.item, selectedItems.includes(name) && classes.itemSelected)} data-value={name} aria-label={name} onFocus={onFocus} checkmark={null}>
            <Persona name={name} role="gridcell" secondaryText="Available" presence={{ status: 'available' }} className={mergeClasses(selectedItems.includes(name) && classes.personaSelected)} avatar={{
                image: {
                    src: avatar,
                },
            }}/>
            <div role="gridcell" className={classes.buttonWrapper}>
              <Button aria-label={`Mute ${name}`} size="small" icon={<Mic16Regular />} onClick={e => {
                e.stopPropagation();
                alert(`Muting ${name}`);
            }}/>
            </div>
          </ListItem>))}
      </List>
      <div className={classes.selectedInfo}>
        Currently selected:{' '}
        <Text block weight="bold">
          {selectedItems[0]}
        </Text>
      </div>
    </div>);
};

export default ListActiveElement;
```

## Multiple Actions Different Primary

Source: Fluent, adapted for CoreAI.

Similar to previous example, but this one implements a custom `onAction` prop on the `ListItem`, 
allowing us to trigger a different action than the selection when the user clicks 
on the list item or presses Enter.

The primary action can be triggered by clicking on the list item or pressing `Enter`.

The selection can be toggled by clicking on the checkbox or pressing `Space` when the item is focused.

To focus on the secondary actions, you can navigate between them by using left and right arrows.

[Download source](/coreai-design-system/source/examples/components-list--multiple-actions-different-primary.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import * as React from 'react';
import { List } from "@coreai-ds/react-components";
import { makeResetStyles } from "@coreai-ds/react-components";
import { ListItem } from "@coreai-ds/react-components";
import { mergeClasses } from "@coreai-ds/react-components";
import { Image } from "@coreai-ds/react-components";
import { Text } from "@coreai-ds/react-components";
import { Caption1 } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { MoreHorizontal20Regular } from "@fluentui/react-icons";
import { MenuPopover } from "@coreai-ds/react-components";
import { MenuList } from "@coreai-ds/react-components";
import { MenuItem } from "@coreai-ds/react-components";

const useStyles = makeStyles({
    list: {
        display: 'flex',
        flexDirection: 'column',
        gap: '16px',
        maxWidth: '300px',
    },
    listItem: {
        display: 'grid',
        padding: '8px',
    },
    caption: {
        color: tokens.colorNeutralForeground3,
    },
    image: {
        height: '160px',
        maxWidth: '100%',
        borderRadius: '5px',
    },
    title: {
        color: tokens.colorNeutralForeground1,
        fontWeight: 600,
        display: 'block',
    },
    checkmark: {
        position: 'absolute',
        left: '10px',
        top: '10px',
        zIndex: 1,
    },
    preview: { gridArea: 'preview', overflow: 'hidden' },
    header: { gridArea: 'header' },
    action: { gridArea: 'action' },
    secondaryAction: { gridArea: 'secondary_action' },
});

const useListItemRootStyles = makeResetStyles({
    position: 'relative',
    flexGrow: '1',
    gap: '8px',
    border: '1px solid grey',
    alignItems: 'center',
    borderRadius: '8px',
    gridTemplate: `"preview preview preview" auto
      "header action secondary_action" auto / 1fr auto auto
    `,
});

const CustomListItem = (props: {
    title: string;
    value: string;
}) => {
    const listItemStyles = useListItemRootStyles();
    const styles = useStyles();
    const { value } = props;
    // This will be triggered by user pressing Enter or clicking on the list item
    const onAction = React.useCallback((event: React.SyntheticEvent | Event, { value: val }: {
        value: string | number;
    }) => {
        // This prevents the change in selection on click/Enter
        event.preventDefault();
        alert(`Triggered custom action on ${val}`);
    }, []);
    return (<ListItem value={props.value} className={mergeClasses(listItemStyles, styles.listItem)} checkmark={{ root: { role: 'gridcell' }, className: styles.checkmark, 'aria-label': value }} aria-label={value} onAction={onAction}>
      <div role="gridcell" className={styles.preview}>
        <Image fit="cover" className={styles.image} src="https://fabricweb.azureedge.net/fabric-website/assets/images/wireframe/image.png" alt="Presentation Preview"/>
      </div>
      <div role="gridcell" className={styles.header}>
        <Text className={styles.title}>{props.title}</Text>
        <Caption1 className={styles.caption}>You created 53m ago</Caption1>
      </div>
      <div role="gridcell" className={styles.action}>
        <Button appearance="primary" aria-label="Install" onClick={e => {
            e.preventDefault();
            alert('Installing!');
        }}>
          Install
        </Button>
      </div>
      <div role="gridcell" className={styles.secondaryAction}>
        <Menu>
          <MenuTrigger disableButtonEnhancement>
            <Button onClick={e => {
            e.preventDefault();
        }} appearance="transparent" icon={<MoreHorizontal20Regular />} aria-label="More actions"/>
          </MenuTrigger>

          <MenuPopover>
            <MenuList>
              <MenuItem onClick={e => {
            e.preventDefault();
            alert('Clicked menu item');
        }}>
                About
              </MenuItem>
              <MenuItem onClick={e => {
            e.preventDefault();
            alert('Clicked menu item');
        }}>
                Uninstall
              </MenuItem>
              <MenuItem onClick={e => {
            e.preventDefault();
            alert('Clicked menu item');
        }}>
                Block
              </MenuItem>
            </MenuList>
          </MenuPopover>
        </Menu>
      </div>
    </ListItem>);
};

export const MultipleActionsDifferentPrimary = (): JSXElement => {
    const classes = useStyles();
    const [selectedItems, setSelectedItems] = React.useState<Array<string | number>>([]);
    return (<List className={classes.list} navigationMode="composite" selectionMode="multiselect" selectedItems={selectedItems} onSelectionChange={(e, data) => setSelectedItems(data.selectedItems)}>
      <CustomListItem title="Example List Item" value="card-1"/>
      <CustomListItem title="Example List Item" value="card-2"/>
      <CustomListItem title="Example List Item" value="card-3"/>
      <CustomListItem title="Example List Item" value="card-4"/>
      <CustomListItem title="Example List Item" value="card-5"/>
      <CustomListItem title="Example List Item" value="card-6"/>
      <CustomListItem title="Example List Item" value="card-7"/>
      <CustomListItem title="Example List Item" value="card-8"/>
      <CustomListItem title="Example List Item" value="card-9"/>
    </List>);
};

export default MultipleActionsDifferentPrimary;
```

## Multiple Actions Selection

Source: Fluent, adapted for CoreAI.

Item with multiple actions. It has selection enabled, which is also it's primary action.
The selection can be toggled by clicking on the item or pressing the `Space` key.

Because the selection is the action on the item, to properly narrate the state of selection
we are using the role grid / row / gridcell here to properly announce when the selection on the
item is toggled.

To enable the user to navigate inside of the list items by pressing the `RightArrow` key,
the `navigationMode` prop should be set to `composite`.

[Download source](/coreai-design-system/source/examples/components-list--multiple-actions-selection.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import * as React from 'react';
import { List } from "@coreai-ds/react-components";
import { makeResetStyles } from "@coreai-ds/react-components";
import { ListItem } from "@coreai-ds/react-components";
import { mergeClasses } from "@coreai-ds/react-components";
import { Image } from "@coreai-ds/react-components";
import { Text } from "@coreai-ds/react-components";
import { Caption1 } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { MoreHorizontal20Regular } from "@fluentui/react-icons";
import { MenuPopover } from "@coreai-ds/react-components";
import { MenuList } from "@coreai-ds/react-components";
import { MenuItem } from "@coreai-ds/react-components";

const useStyles = makeStyles({
    list: {
        display: 'flex',
        flexDirection: 'column',
        gap: '16px',
        maxWidth: '300px',
    },
    listItem: {
        display: 'grid',
        padding: '8px',
    },
    caption: {
        color: tokens.colorNeutralForeground3,
    },
    image: {
        height: '160px',
        maxWidth: '100%',
        borderRadius: '5px',
    },
    title: {
        color: tokens.colorNeutralForeground1,
        fontWeight: 600,
        display: 'block',
    },
    checkmark: {
        position: 'absolute',
        left: '10px',
        top: '10px',
        zIndex: 1,
    },
    preview: { gridArea: 'preview', overflow: 'hidden' },
    header: { gridArea: 'header' },
    action: { gridArea: 'action' },
    secondaryAction: { gridArea: 'secondary_action' },
});

const useListItemRootStyles = makeResetStyles({
    position: 'relative',
    flexGrow: '1',
    gap: '8px',
    border: '1px solid grey',
    alignItems: 'center',
    borderRadius: '8px',
    gridTemplate: `"preview preview preview" auto
      "header action secondary_action" auto / 1fr auto auto
    `,
});

const CustomListItem = (props: {
    title: string;
    value: string;
}) => {
    const listItemStyles = useListItemRootStyles();
    const styles = useStyles();
    const { value, title } = props;
    return (<ListItem value={value} className={mergeClasses(listItemStyles, styles.listItem)} checkmark={{ root: { role: 'gridcell' }, className: styles.checkmark, 'aria-label': value }} aria-label={value}>
      <div role="gridcell" className={styles.preview}>
        <Image fit="cover" className={styles.image} src="https://fabricweb.azureedge.net/fabric-website/assets/images/wireframe/image.png" alt="Presentation Preview"/>
      </div>
      <div role="gridcell" className={styles.header}>
        <Text className={styles.title}>{title}</Text>
        <Caption1 className={styles.caption}>You created 53m ago</Caption1>
      </div>
      <div role="gridcell" className={styles.action}>
        <Button appearance="primary" aria-label="Install" onClick={e => {
            e.preventDefault();
            alert('Installing!');
        }}>
          Install
        </Button>
      </div>
      <div role="gridcell" className={styles.secondaryAction}>
        <Menu>
          <MenuTrigger disableButtonEnhancement>
            <Button onClick={e => {
            e.preventDefault();
        }} appearance="transparent" icon={<MoreHorizontal20Regular />} aria-label="More actions"/>
          </MenuTrigger>

          <MenuPopover>
            <MenuList>
              <MenuItem onClick={e => {
            e.preventDefault();
            alert('Clicked menu item');
        }}>
                About
              </MenuItem>
              <MenuItem onClick={e => {
            e.preventDefault();
            alert('Clicked menu item');
        }}>
                Uninstall
              </MenuItem>
              <MenuItem onClick={e => {
            e.preventDefault();
            alert('Clicked menu item');
        }}>
                Block
              </MenuItem>
            </MenuList>
          </MenuPopover>
        </Menu>
      </div>
    </ListItem>);
};

export const MultipleActionsSelection = (): JSXElement => {
    const classes = useStyles();
    const [selectedItems, setSelectedItems] = React.useState<Array<string | number>>([]);
    return (<List className={classes.list} navigationMode="composite" selectionMode="multiselect" selectedItems={selectedItems} onSelectionChange={(e, data) => setSelectedItems(data.selectedItems)}>
      <CustomListItem title="Example List Item" value="card-1"/>
      <CustomListItem title="Example List Item" value="card-2"/>
      <CustomListItem title="Example List Item" value="card-3"/>
      <CustomListItem title="Example List Item" value="card-4"/>
      <CustomListItem title="Example List Item" value="card-5"/>
      <CustomListItem title="Example List Item" value="card-6"/>
      <CustomListItem title="Example List Item" value="card-7"/>
      <CustomListItem title="Example List Item" value="card-8"/>
      <CustomListItem title="Example List Item" value="card-9"/>
    </List>);
};

export default MultipleActionsSelection;
```

## Multiple Actions With Primary

Source: Fluent, adapted for CoreAI.

Base item with multiple actions. Doesn't support selection, but the list items have a primary action 
that can be triggered by clicking on the item or pressing Enter.

__To make the navigation work properly, the `navigationMode` prop should be set to `composite`.__
This will allow the user to navigate inside of the list items by pressing the `Right Arrow` key.
It also sets the `grid` role automatically to the list.

> ⚠️ _In cases where `grid` role is used, it is important that every direct children of `ListItem`_
_has role `gridcell`. Also each focusable item should be in its own "gridcell". This makes sure the _
_screen readers work properly._

[Download source](/coreai-design-system/source/examples/components-list--multiple-actions-with-primary.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { List } from "@coreai-ds/react-components";
import { makeResetStyles } from "@coreai-ds/react-components";
import * as React from 'react';
import { ListItem } from "@coreai-ds/react-components";
import { mergeClasses } from "@coreai-ds/react-components";
import { Image } from "@coreai-ds/react-components";
import { Text } from "@coreai-ds/react-components";
import { Caption1 } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { MoreHorizontal20Regular } from "@fluentui/react-icons";
import { MenuPopover } from "@coreai-ds/react-components";
import { MenuList } from "@coreai-ds/react-components";
import { MenuItem } from "@coreai-ds/react-components";

const useStyles = makeStyles({
    list: {
        display: 'flex',
        flexDirection: 'column',
        gap: '16px',
        maxWidth: '300px',
    },
    listItem: {
        display: 'grid',
        padding: '8px',
    },
    caption: {
        color: tokens.colorNeutralForeground3,
    },
    image: {
        height: '160px',
        maxWidth: '100%',
        borderRadius: '5px',
    },
    title: {
        color: tokens.colorNeutralForeground1,
        fontWeight: 600,
        display: 'block',
    },
    preview: { gridArea: 'preview', overflow: 'hidden' },
    header: { gridArea: 'header' },
    action: { gridArea: 'action' },
    secondaryAction: { gridArea: 'secondary_action' },
});

const useListItemRootStyles = makeResetStyles({
    position: 'relative',
    flexGrow: '1',
    gap: '8px',
    border: '1px solid grey',
    alignItems: 'center',
    borderRadius: '8px',
    gridTemplate: `"preview preview preview" auto
      "header action secondary_action" auto / 1fr auto auto
    `,
});

const CustomListItem = (props: {
    title: string;
    value: string;
}) => {
    const listItemStyles = useListItemRootStyles();
    const styles = useStyles();
    const { value } = props;
    // This will be triggered by user pressing Enter or clicking on the list item
    const onAction = React.useCallback((event: React.SyntheticEvent | Event) => {
        // This prevents the change in selection on click/Enter
        event.preventDefault();
        alert(`Triggered custom action!`);
    }, []);
    return (<ListItem value={props.value} className={mergeClasses(listItemStyles, styles.listItem)} aria-label={value} onAction={onAction}>
      <div role="gridcell" className={styles.preview}>
        <Image fit="cover" className={styles.image} src="https://fabricweb.azureedge.net/fabric-website/assets/images/wireframe/image.png" alt="Presentation Preview"/>
      </div>
      <div role="gridcell" className={styles.header}>
        <Text className={styles.title}>{props.title}</Text>
        <Caption1 className={styles.caption}>You created 53m ago</Caption1>
      </div>
      <div role="gridcell" className={styles.action}>
        <Button appearance="primary" aria-label="Install" onClick={e => {
            e.preventDefault();
            alert('Installing!');
        }}>
          Install
        </Button>
      </div>
      <div role="gridcell" className={styles.secondaryAction}>
        <Menu>
          <MenuTrigger disableButtonEnhancement>
            <Button appearance="transparent" icon={<MoreHorizontal20Regular />} onClick={e => e.preventDefault()} aria-label="More actions"/>
          </MenuTrigger>

          <MenuPopover>
            <MenuList>
              <MenuItem onClick={e => {
            e.preventDefault();
            alert('Clicked menu item');
        }}>
                About
              </MenuItem>
              <MenuItem onClick={e => {
            e.preventDefault();
            alert('Clicked menu item');
        }}>
                Uninstall
              </MenuItem>
              <MenuItem onClick={e => {
            e.preventDefault();
            alert('Clicked menu item');
        }}>
                Block
              </MenuItem>
            </MenuList>
          </MenuPopover>
        </Menu>
      </div>
    </ListItem>);
};

export const MultipleActionsWithPrimary = (): JSXElement => {
    const classes = useStyles();
    return (<List navigationMode="composite" className={classes.list}>
      <CustomListItem title="Example List Item" value="card-1"/>
      <CustomListItem title="Example List Item" value="card-2"/>
      <CustomListItem title="Example List Item" value="card-3"/>
      <CustomListItem title="Example List Item" value="card-4"/>
      <CustomListItem title="Example List Item" value="card-5"/>
      <CustomListItem title="Example List Item" value="card-6"/>
      <CustomListItem title="Example List Item" value="card-7"/>
      <CustomListItem title="Example List Item" value="card-8"/>
      <CustomListItem title="Example List Item" value="card-9"/>
    </List>);
};

export default MultipleActionsWithPrimary;
```

## Single Action

Source: Fluent, adapted for CoreAI.

When the list item should have a custom primary action on it, you can pass the `onAction` prop to the `ListItem` component.
This callback will also be automatically called when the user presses the Enter or Space key on the list item.

To learn more about what event triggered the action, you can check the `event.details.originalEvent`.

To enable keyboard navigation between the list items, the `navigationMode` prop should be set to `items`.

[Download source](/coreai-design-system/source/examples/components-list--single-action.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { List } from "@coreai-ds/react-components";
import { ListItem } from "@coreai-ds/react-components";
import { Persona } from "@coreai-ds/react-components";
import * as React from 'react';

const names = [
    'Melda Bevel',
    'Demetra Manwaring',
    'Eusebia Stufflebeam',
    'Israel Rabin',
    'Bart Merrill',
    'Sonya Farner',
];

export const SingleAction = (): JSXElement => {
    return (<List navigationMode="items">
      {names.map(name => (<ListItem key={name} aria-label={`${name}, available`} onAction={() => alert(`Triggered custom action!`)}>
          <Persona name={name} secondaryText="Available" presence={{ status: 'available' }} avatar={{
                image: {
                    src: 'https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/office-ui-fabric-react-assets/persona-male.png',
                },
            }}/>
        </ListItem>))}
    </List>);
};

export default SingleAction;
```

## Single Action Selection

Source: Fluent, adapted for CoreAI.

Any List can be selectable. You have an option to control the selection state yourself or let the List manage it for you.

You can pass `selectionMode` prop with value "single" or "multiselect" to the List component to get support for selection.
The items can be toggled by clicking on the list item, or pressing `Spacebar` or `Enter` when the item is focused. Keyboard navigation is automatically enabled and `navigationMode` is set to `items`.

Also this example only has one action in the list item, and it's for toggling the selection. The roles for this one are listbox and option.

[Download source](/coreai-design-system/source/examples/components-list--single-action-selection.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { List } from "@coreai-ds/react-components";
import { ListItem } from "@coreai-ds/react-components";
import { Persona } from "@coreai-ds/react-components";
import * as React from 'react';

type Item = {
    name: string;
    id: string;
    avatar: string;
};

const items: Item[] = [
    'Melda Bevel',
    'Demetra Manwaring',
    'Eusebia Stufflebeam',
    'Israel Rabin',
    'Bart Merrill',
    'Sonya Farner',
].map(name => ({
    name,
    id: name,
    avatar: 'https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/office-ui-fabric-react-assets/persona-male.png',
}));

export const SingleActionSelection = (): JSXElement => {
    const defaultSelectedItems = ['Demetra Manwaring', 'Bart Merrill'];
    return (<List selectionMode="multiselect" defaultSelectedItems={defaultSelectedItems} aria-label="People example">
      {items.map(({ name, avatar }, i) => (<ListItem key={name} value={name} aria-label={name} checkmark={{ 'aria-label': name }} disabledSelection={i > 3} // Example of disabling selection for last 2 items
        >
          <Persona name={name} secondaryText="Available" presence={{ status: 'available' }} avatar={{
                image: {
                    src: avatar,
                },
            }}/>
        </ListItem>))}
    </List>);
};

export default SingleActionSelection;
```

## Single Action Selection Controlled

Source: Fluent, adapted for CoreAI.

This example shows how to use the `selectedItems` and `onSelectionChange`
props to control the selection state of the List and keep track of it in the parent component.

This is more in line with how we expect the selection to be used in production environment.

[Download source](/coreai-design-system/source/examples/components-list--single-action-selection-controlled.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import * as React from 'react';
import type { SelectionItemId } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { List } from "@coreai-ds/react-components";
import { ListItem } from "@coreai-ds/react-components";
import { Persona } from "@coreai-ds/react-components";

const useStyles = makeStyles({
    buttonControls: {
        display: 'flex',
        columnGap: '8px',
        marginBottom: '16px',
    },
});

type Item = {
    name: string;
    id: string;
    avatar: string;
};

const items: Item[] = [
    'Melda Bevel',
    'Demetra Manwaring',
    'Eusebia Stufflebeam',
    'Israel Rabin',
    'Bart Merrill',
    'Sonya Farner',
].map(name => ({
    name,
    id: name,
    avatar: 'https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/office-ui-fabric-react-assets/persona-male.png',
}));

export const SingleActionSelectionControlled = (): JSXElement => {
    const classes = useStyles();
    const [selectedItems, setSelectedItems] = React.useState<SelectionItemId[]>(['Demetra Manwaring', 'Bart Merrill']);
    return (<div>
      <div className={classes.buttonControls}>
        <Button onClick={e => setSelectedItems(items.map(({ id }) => id))}>Select all</Button>
      </div>

      <List selectionMode="multiselect" selectedItems={selectedItems} onSelectionChange={(_, data) => setSelectedItems(data.selectedItems)} aria-label="People example">
        {items.map(({ name, avatar }) => (<ListItem key={name} value={name} aria-label={name} checkmark={{ 'aria-label': name }}>
            <Persona name={name} secondaryText="Available" presence={{ status: 'available' }} avatar={{
                image: {
                    src: avatar,
                },
            }}/>
          </ListItem>))}
      </List>
    </div>);
};

export default SingleActionSelectionControlled;
```

## Single Action Selection Different Primary

Source: Fluent, adapted for CoreAI.

This example is similar to the previous one, but it implements a custom primary action on `ListItem`,
allowing us to trigger a
__different action than the selection when the user clicks on the list item or presses Enter__
. This is useful when you want to have a primary action on the list item, but still want 
to allow the user to select it.

To change the default action on the `ListItem` (when user clicks on it or presses Enter), you can use the
`onAction` prop. By calling `event.preventDefault()` in the `onAction` callback, you can prevent the default
action (toggling the selection) from happening. This way, you can perform a completely custom action.
In this example, the custom action is an alert that triggers when the user
clicks on the list item or presses Enter.

__The selection can still be toggled by clicking on the checkbox or pressing `Space` when the item is focused.__

[Download source](/coreai-design-system/source/examples/components-list--single-action-selection-different-primary.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import type { SelectionItemId } from "@coreai-ds/react-components";
import type { ListItemProps } from "@coreai-ds/react-components";
import { List } from "@coreai-ds/react-components";
import { ListItem } from "@coreai-ds/react-components";
import { Persona } from "@coreai-ds/react-components";

type Item = {
    name: string;
    id: string;
    avatar: string;
};

const items: Item[] = [
    'Melda Bevel',
    'Demetra Manwaring',
    'Eusebia Stufflebeam',
    'Israel Rabin',
    'Bart Merrill',
    'Sonya Farner',
].map(name => ({
    name,
    id: name,
    avatar: 'https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/office-ui-fabric-react-assets/persona-male.png',
}));

export const SingleActionSelectionDifferentPrimary = (): JSXElement => {
    const [selectedItems, setSelectedItems] = React.useState<SelectionItemId[]>(['Demetra Manwaring', 'Bart Merrill']);
    // This will be triggered by user pressing Enter or clicking on the list item
    const onAction = React.useCallback((event: React.SyntheticEvent | Event, { value: val }: {
        value: ListItemProps['value'];
    }) => {
        // This prevents the change in selection on click/Enter
        event.preventDefault();
        alert(`Triggered custom action on ${val}`);
    }, []);
    return (<List aria-label="People example" selectionMode="multiselect" selectedItems={selectedItems} onSelectionChange={(_, data) => setSelectedItems(data.selectedItems)}>
      {items.map(({ name, avatar }, index) => (<ListItem key={name} value={name} aria-label={name} onAction={onAction} checkmark={{ 'aria-label': name }} disabledSelection={index === 2}>
          <Persona name={name} secondaryText="Available" presence={{ status: 'available' }} avatar={{
                image: {
                    src: avatar,
                },
            }}/>
        </ListItem>))}
    </List>);
};

export default SingleActionSelectionDifferentPrimary;
```

## Virtualized List

Source: Fluent, adapted for CoreAI.

When creating a list of large size, one way of making sure you are getting the best performance
is to use virtualization. In this example we are leveraging the `react-window` package.

Please note that if the virtualized list contains non-actionable list items, scrolling should be achieved
by using the `tabIndex={0}` property on the List.

> ⚠️ _It is important to manually set `aria-setsize` and `aria-posinset` attributes on the list items, since_
_the virualization will only render the visible items. Relying on the DOM state for these attributes will not work._

[Download source](/coreai-design-system/source/examples/components-list--virtualized-list.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeResetStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { FixedSizeList } from "react-window";
import * as React from 'react';
import { List } from "@coreai-ds/react-components";
import { ListItem } from "@coreai-ds/react-components";
import { Text } from "@coreai-ds/react-components";

const useTextStyle = makeResetStyles({
    color: tokens.colorNeutralForeground1,
});

const countries = [
    'Afghanistan',
    'Albania',
    'Algeria',
    'Andorra',
    'Angola',
    'Antigua & Deps',
    'Argentina',
    'Armenia',
    'Australia',
    'Austria',
    'Azerbaijan',
    'Bahamas',
    'Bahrain',
    'Bangladesh',
    'Barbados',
    'Belarus',
    'Belgium',
    'Belize',
    'Benin',
    'Bhutan',
    'Bolivia',
    'Bosnia Herzegovina',
    'Botswana',
    'Brazil',
    'Brunei',
    'Bulgaria',
    'Burkina',
    'Burundi',
    'Cambodia',
    'Cameroon',
    'Canada',
    'Cape Verde',
    'Central African Rep',
    'Chad',
    'Chile',
    'China',
    'Colombia',
    'Comoros',
    'Congo',
    'Congo {Democratic Rep}',
    'Costa Rica',
    'Croatia',
    'Cuba',
    'Cyprus',
    'Czech Republic',
    'Denmark',
    'Djibouti',
    'Dominica',
    'Dominican Republic',
    'East Timor',
    'Ecuador',
    'Egypt',
    'El Salvador',
    'Equatorial Guinea',
    'Eritrea',
    'Estonia',
    'Ethiopia',
    'Fiji',
    'Finland',
    'France',
    'Gabon',
    'Gambia',
    'Georgia',
    'Germany',
    'Ghana',
    'Greece',
    'Grenada',
    'Guatemala',
    'Guinea',
    'Guinea-Bissau',
    'Guyana',
    'Haiti',
    'Honduras',
    'Hungary',
    'Iceland',
    'India',
    'Indonesia',
    'Iran',
    'Iraq',
    'Ireland {Republic}',
    'Israel',
    'Italy',
    'Ivory Coast',
    'Jamaica',
    'Japan',
    'Jordan',
    'Kazakhstan',
    'Kenya',
    'Kiribati',
    'Korea North',
    'Korea South',
    'Kosovo',
    'Kuwait',
    'Kyrgyzstan',
    'Laos',
    'Latvia',
    'Lebanon',
    'Lesotho',
    'Liberia',
    'Libya',
    'Liechtenstein',
    'Lithuania',
    'Luxembourg',
    'Macedonia',
    'Madagascar',
    'Malawi',
    'Malaysia',
    'Maldives',
    'Mali',
    'Malta',
    'Marshall Islands',
    'Mauritania',
    'Mauritius',
    'Mexico',
    'Micronesia',
    'Moldova',
    'Monaco',
    'Mongolia',
    'Montenegro',
    'Morocco',
    'Mozambique',
    'Myanmar, {Burma}',
    'Namibia',
    'Nauru',
    'Nepal',
    'Netherlands',
    'New Zealand',
    'Nicaragua',
    'Niger',
    'Nigeria',
    'Norway',
    'Oman',
    'Pakistan',
    'Palau',
    'Panama',
    'Papua New Guinea',
    'Paraguay',
    'Peru',
    'Philippines',
    'Poland',
    'Portugal',
    'Qatar',
    'Romania',
    'Russian Federation',
    'Rwanda',
    'St Kitts & Nevis',
    'St Lucia',
    'Saint Vincent & the Grenadines',
    'Samoa',
    'San Marino',
    'Sao Tome & Principe',
    'Saudi Arabia',
    'Senegal',
    'Serbia',
    'Seychelles',
    'Sierra Leone',
    'Singapore',
    'Slovakia',
    'Slovenia',
    'Solomon Islands',
    'Somalia',
    'South Africa',
    'South Sudan',
    'Spain',
    'Sri Lanka',
    'Sudan',
    'Suriname',
    'Swaziland',
    'Sweden',
    'Switzerland',
    'Syria',
    'Taiwan',
    'Tajikistan',
    'Tanzania',
    'Thailand',
    'Togo',
    'Tonga',
    'Trinidad & Tobago',
    'Tunisia',
    'Turkey',
    'Turkmenistan',
    'Tuvalu',
    'Uganda',
    'Ukraine',
    'United Arab Emirates',
    'United Kingdom',
    'United States',
    'Uruguay',
    'Uzbekistan',
    'Vanuatu',
    'Vatican City',
    'Venezuela',
    'Vietnam',
    'Yemen',
    'Zambia',
    'Zimbabwe',
];

const CountriesList = React.forwardRef<HTMLUListElement>((props: React.ComponentProps<typeof List>, ref) => (<List aria-label="Countries" tabIndex={0} {...props} ref={ref}/>));

export const VirtualizedList = (): JSXElement => {
    const textStyle = useTextStyle();
    return (<FixedSizeList height={400} itemCount={countries.length} itemSize={20} width="100%" itemData={countries} outerElementType={CountriesList}>
      {({ index, style, data }) => (<ListItem style={style} aria-setsize={countries.length} aria-posinset={index + 1}>
          <Text className={textStyle}>{data[index]}</Text>
        </ListItem>)}
    </FixedSizeList>);
};

export default VirtualizedList;
```

## Virtualized List With Actionable Items

Source: Fluent, adapted for CoreAI.

Virtualized list can also be used with interactive elements.

[Download source](/coreai-design-system/source/examples/components-list--virtualized-list-with-actionable-items.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeResetStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { FixedSizeList } from "react-window";
import * as React from 'react';
import { List } from "@coreai-ds/react-components";
import { ListItem } from "@coreai-ds/react-components";
import { Text } from "@coreai-ds/react-components";

const useTextStyle = makeResetStyles({
    color: tokens.colorNeutralForeground1,
});

const countries = [
    'Afghanistan',
    'Albania',
    'Algeria',
    'Andorra',
    'Angola',
    'Antigua & Deps',
    'Argentina',
    'Armenia',
    'Australia',
    'Austria',
    'Azerbaijan',
    'Bahamas',
    'Bahrain',
    'Bangladesh',
    'Barbados',
    'Belarus',
    'Belgium',
    'Belize',
    'Benin',
    'Bhutan',
    'Bolivia',
    'Bosnia Herzegovina',
    'Botswana',
    'Brazil',
    'Brunei',
    'Bulgaria',
    'Burkina',
    'Burundi',
    'Cambodia',
    'Cameroon',
    'Canada',
    'Cape Verde',
    'Central African Rep',
    'Chad',
    'Chile',
    'China',
    'Colombia',
    'Comoros',
    'Congo',
    'Congo {Democratic Rep}',
    'Costa Rica',
    'Croatia',
    'Cuba',
    'Cyprus',
    'Czech Republic',
    'Denmark',
    'Djibouti',
    'Dominica',
    'Dominican Republic',
    'East Timor',
    'Ecuador',
    'Egypt',
    'El Salvador',
    'Equatorial Guinea',
    'Eritrea',
    'Estonia',
    'Ethiopia',
    'Fiji',
    'Finland',
    'France',
    'Gabon',
    'Gambia',
    'Georgia',
    'Germany',
    'Ghana',
    'Greece',
    'Grenada',
    'Guatemala',
    'Guinea',
    'Guinea-Bissau',
    'Guyana',
    'Haiti',
    'Honduras',
    'Hungary',
    'Iceland',
    'India',
    'Indonesia',
    'Iran',
    'Iraq',
    'Ireland {Republic}',
    'Israel',
    'Italy',
    'Ivory Coast',
    'Jamaica',
    'Japan',
    'Jordan',
    'Kazakhstan',
    'Kenya',
    'Kiribati',
    'Korea North',
    'Korea South',
    'Kosovo',
    'Kuwait',
    'Kyrgyzstan',
    'Laos',
    'Latvia',
    'Lebanon',
    'Lesotho',
    'Liberia',
    'Libya',
    'Liechtenstein',
    'Lithuania',
    'Luxembourg',
    'Macedonia',
    'Madagascar',
    'Malawi',
    'Malaysia',
    'Maldives',
    'Mali',
    'Malta',
    'Marshall Islands',
    'Mauritania',
    'Mauritius',
    'Mexico',
    'Micronesia',
    'Moldova',
    'Monaco',
    'Mongolia',
    'Montenegro',
    'Morocco',
    'Mozambique',
    'Myanmar, {Burma}',
    'Namibia',
    'Nauru',
    'Nepal',
    'Netherlands',
    'New Zealand',
    'Nicaragua',
    'Niger',
    'Nigeria',
    'Norway',
    'Oman',
    'Pakistan',
    'Palau',
    'Panama',
    'Papua New Guinea',
    'Paraguay',
    'Peru',
    'Philippines',
    'Poland',
    'Portugal',
    'Qatar',
    'Romania',
    'Russian Federation',
    'Rwanda',
    'St Kitts & Nevis',
    'St Lucia',
    'Saint Vincent & the Grenadines',
    'Samoa',
    'San Marino',
    'Sao Tome & Principe',
    'Saudi Arabia',
    'Senegal',
    'Serbia',
    'Seychelles',
    'Sierra Leone',
    'Singapore',
    'Slovakia',
    'Slovenia',
    'Solomon Islands',
    'Somalia',
    'South Africa',
    'South Sudan',
    'Spain',
    'Sri Lanka',
    'Sudan',
    'Suriname',
    'Swaziland',
    'Sweden',
    'Switzerland',
    'Syria',
    'Taiwan',
    'Tajikistan',
    'Tanzania',
    'Thailand',
    'Togo',
    'Tonga',
    'Trinidad & Tobago',
    'Tunisia',
    'Turkey',
    'Turkmenistan',
    'Tuvalu',
    'Uganda',
    'Ukraine',
    'United Arab Emirates',
    'United Kingdom',
    'United States',
    'Uruguay',
    'Uzbekistan',
    'Vanuatu',
    'Vatican City',
    'Venezuela',
    'Vietnam',
    'Yemen',
    'Zambia',
    'Zimbabwe',
];

const CountriesList = React.forwardRef<HTMLUListElement>((props: React.ComponentProps<typeof List>, ref) => (<List navigationMode="items" aria-label="Countries" {...props} ref={ref}/>));

export const VirtualizedListWithActionableItems = (): JSXElement => {
    const textStyle = useTextStyle();
    return (<FixedSizeList height={400} itemCount={countries.length} itemSize={20} width="100%" itemData={countries} outerElementType={CountriesList}>
      {({ index, style, data }) => (<ListItem style={style} aria-setsize={countries.length} aria-posinset={index + 1} onAction={() => alert(data[index])}>
          <Text className={textStyle}>{data[index]}</Text>
        </ListItem>)}
    </FixedSizeList>);
};

export default VirtualizedListWithActionableItems;
```

## Resources

- [Figma component](https://www.figma.com/design/eXfSQrRg3poHRgmr0ivN5V/CoreAI-Figma-Library?node-id=287954-86982)
- [Fluent guidance](https://fluent2.microsoft.design/components/web/react/core/list/usage)