diff --git a/change/@fluentui-react-shared-contexts-c8fe7f5c-9503-41d6-a0d6-dec1071446ac.json b/change/@fluentui-react-shared-contexts-c8fe7f5c-9503-41d6-a0d6-dec1071446ac.json
new file mode 100644
index 0000000000000..a1edf785ce3d5
--- /dev/null
+++ b/change/@fluentui-react-shared-contexts-c8fe7f5c-9503-41d6-a0d6-dec1071446ac.json
@@ -0,0 +1,7 @@
+{
+ "type": "minor",
+ "comment": "deprecate unused ListItemButton exports",
+ "packageName": "@fluentui/react-shared-contexts",
+ "email": "jirivyhnalek@microsoft.com",
+ "dependentChangeType": "patch"
+}
diff --git a/packages/react-components/react-list-preview/config/tests.js b/packages/react-components/react-list-preview/config/tests.js
index 2e211ae9e2142..c6c67de97059e 100644
--- a/packages/react-components/react-list-preview/config/tests.js
+++ b/packages/react-components/react-list-preview/config/tests.js
@@ -1 +1,3 @@
/** Jest test setup file. */
+
+require('@testing-library/jest-dom');
diff --git a/packages/react-components/react-list-preview/cypress.config.ts b/packages/react-components/react-list-preview/cypress.config.ts
new file mode 100644
index 0000000000000..ca52cf041bbf2
--- /dev/null
+++ b/packages/react-components/react-list-preview/cypress.config.ts
@@ -0,0 +1,3 @@
+import { baseConfig } from '@fluentui/scripts-cypress';
+
+export default baseConfig;
diff --git a/packages/react-components/react-list-preview/docs/ListA11y.md b/packages/react-components/react-list-preview/docs/ListA11y.md
new file mode 100644
index 0000000000000..c79b2aac622a8
--- /dev/null
+++ b/packages/react-components/react-list-preview/docs/ListA11y.md
@@ -0,0 +1,243 @@
+# Accessibility of Lists on the web: why we can't have nice things
+
+Rev. 1 - Initial draft
+Rev. 2 - Added examples links, made conclusions in italic, explained bahavior for Space and Enter on lists with a primary action, some wording changed
+
+Accessibility in browsers is hard in general. When it comes to modern web applications with complex UIs, that statement is more true then ever.
+
+And then there are Lists. For some reason, there is not a single aria role that would support proper position narration, selection narration, and complex widget elements with secondary actions.
+
+That is why we need to make compromises, choosing the right tool (a11y role) for each scenario and maybe sometimes hack around a little.
+
+In this document I will go through a different variations and designs of List -- seemingly a simple component, but a nightmare to make accessible properly.
+
+We'll discuss the requirements from the design/functional POV, then proceed with defining accessibility requirement. Having these in mind, we can explore different List use cases and see which aria roles work and which don't, what should we pick and why, and what are the limitations and how we can work around them.
+
+## Functional requirements for List
+
+When I say List, I dont mean a simple `ul`/`li` list. A List component in the world of Fluent UI is a more complex component and supports these features:
+
+- **A simple `ul`/`li`** - base scenario; a simple list with no interactivity at all.
+- **Single action** - Each List Item can have one primary action, this action can be triggered by pressing **Enter** on the focused list item.
+- **Selection** - each List can be set as selectable and List Items need to be toggleable, both single and multiselect are supported. This needs to be properly narrated by screen readers. The selection can be triggered by pressing **Spacebar**.
+- **ListItems with "secondary" action** - each List Item is kind of a widget, in addition to a primary action, can have multiple interactive elements inside. User needs to understand that those options are there and intuitively know how to focus those.
+
+## Accessibility requirements
+
+For the List to be accessible, these requirements are mandatory to work on major screen reading software. I will be focusing on NVDA, Jaws (Windows) and Voice Over (Mac OS).
+
+- **Position** - as user navigates, the current position in the list is announced
+- **Actionable** - as user navigates, it should be obvious that the current item has an action that can be triggered (the action can be selection, but doesn't have to be). This should be implicit (role `button` implies there is an action) or explicit (the screen reader makes it known there is an action)
+- **Selection** - as user changes the selection state on a List Item, it is announced
+
+In the following section, I will go through the each funcional requirement and describe the problems into more detail.
+
+## Analysis
+
+### Single action lists
+
+[example](https://fluentuipr.z22.web.core.windows.net/pull/29760/public-docsite-v9/storybook/iframe.html?viewMode=docs&id=preview-components-list--default#single-action)
+
+List with a single action is a collection of items with common action, specific to each item. One example would be a list of people, where clicking on a person will open a popup with details.
+
+For a List with a single action, there are generally 2 approaches we can take:
+
+a) Put a **Button component inside** of the List Item and navigate directly between them, skipping the List Items
+
+b) Make the **List Items focusable** and attach the action on them
+
+#### Making the Buttons inside focusable
+
+While this is a suggested approach for this case, lets see if it fits all of our a11y requirements:
+
+- Position: ❌
+ - While Voice Over on Mac Works (when using proper VO keys to navigate), screen readers on Windows fail to announce the position inside of the list in Focus mode (preferred mode for comples web Apps).
+- Actionable: ✅
+ - Since it is a button with aria role `button` we are focusing, it's implicitly communicated that the user can trigger action.
+- Selection: N/A
+
+#### Making the List Items Focusable
+
+If we want to put the action directly on the list item, we should choose the proper aria role, which would fill all of our a11y requirement, i.e. **announce position in the list** and **implicitly or explicitly communicate there is action attached to the List Item**.
+
+We have multiple aria roles we can explore and see if any of those fill all of our a11y needs:
+
+##### List/ListItem
+
+- Position: ✅
+ - Focused items of role "listitem" are properly announced with their position
+- Actionable: ✴️
+ - The **action** on the list item is **not announced** in the Focus mode on Windows.
+ - This should be implicitly communicated by context, if that isn't necessary, it can be worked around by using `aria-roledescription` or `aria-label` with proper explanation.
+- Selection: N/A
+
+_`listitem` role on it's own should be used if the fact that it has an action can be understood by the context it exists in. If this is not clear enough, `aria-label` or `aria-roledescription` can be used to further explain this._
+
+##### Menu/Menuitem
+
+- Position: ✅
+ - Focused `menuitem` elements properly announce their position in the `menu`
+- Actionable: ✅
+ - Users implicitly expect an action on a `menuitem`
+- Selection: N/A
+- Other considerations:
+ - While the `menu`/`menuitem` aria roles seem to check our a11y requirement boxes, there are other considerations that need to be taken in:
+ - "Menu" is not semantically correct for our example use case. List is different from a Menu in a way that in a List, each List item is of the same "category" (list of people, emails, conversations, applications) and each list item action triggers the same action, while in a Menu the user expects each option to do something else.
+ - Creates a communication barrier between the sighted user and user relying on a screen reader. If a sighted user instructs visually impaired user to go on "the list of people", they would only be able to find "a menu".
+
+_While the `menuitem` role seems to work, its semantically different from a list enough, that it would add confusion and noise._
+
+#### Outcome
+
+Seems like for our "simple" use case of a single action in a list item, we don't have a perfect solution. Each of the three suggested variants have their cons. While some of the downsides of certain solutions are fundamental (confusion between listitem and menuitem), others can be worked around.
+
+_My suggestion for this usecase would to **make the List Item focusable, use `list` and `listitem` roles and add a translated string of "button" as `aria-roledescription` when an action on the list Item is present**._
+
+This way we make sure that the user knows they are in a List, the position is properly announced and a translated "button" role description is present, making it clear you can press "Enter" to trigger it.
+
+**Examples of narration of the suggested solution:**
+NVDA:
+
+> John Doe button 2 of 13 level 1
+
+JAWS:
+
+> John Doe button 2 of 13
+
+Voice Over (using VO navigation keys):
+
+> John Doe, button, 2 of 13
+
+Voice Over (using just arrow keys):
+
+> John Doe, button
+
+### Single action lists - selection
+
+[Visit example](https://fluentuipr.z22.web.core.windows.net/pull/29760/public-docsite-v9/storybook/iframe.html?viewMode=docs&id=preview-components-list--default#single-action-selection)
+
+List with a single action where the action is toggling the selection. One example would be a list of people to add to a call, where clicking on a row/person will add them to the selection. There is no other action that can be triggered on the list items.
+
+The whole list item can be focused and the selection can be toggled with **spacebar**. Also, the whole item is clickable with a mouse and triggers the same action.
+
+Counter-intuitively, this case is more straightforward to handle than the previous, since this is usually called a **Listbox** and there is an appropriate aria role for this.
+
+#### Listbox/Option
+
+- Position: ✅
+ - The position in the list is properly narrated in all screen readers.
+- Actionable: ✅
+ - The `listbox`/`option` role combination implicitly communicates that user can toggle the selection on an item using spacebar
+- Selection: ✅
+ - The `listbox`/`option` role support `aria-selected` attribute which is properly narrated as it changes.
+
+_This scenario is straightforward, there is an aria role which fits perfectly in our use case. It has one downside, the `option` role is [always presentational](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/option_role#all_descendants_are_presentational), which means that `listbox` with `option` cannot be used in a scenario where there are other actions inside of the list item, but more on that later._
+
+### List with multiple actions - no primary action
+
+[example](https://fluentuipr.z22.web.core.windows.net/pull/29760/public-docsite-v9/storybook/index.html?path=/docs/preview-components-list--default#multiple-actions-no-primary-no-selection)
+
+When multiple actions are available in a list item, things become a bit more complicated, as some aria roles are not equipped to handle that at all (like `option` because of it's inherent property of [all descendants being presentational](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/option_role#all_descendants_are_presentational)).
+
+For the following scenarios we can establish some basic keyboard navigation that should be supported regardless of any a11y role we add.
+
+For simplicity, lets talk about a vertical list in LTR layout. Horizontal lists and lists in RTL layout should swap the arrow keys appropriately.
+
+- **Down/Up arrows** move to the **next, previous list item**
+- **Right arrow enters** the list item and **focuses** on the **first focusable** element
+- Once **in the list item**, **Left** and **Right** arrow keys navigate between **focusable elements inside**, this is **not cyclic** and when **left arrow is pressed on leftmost** element, the **list item itself is selected**
+- Once in the list item, **Up and Down** arrows **focus** the list item **above/below** (if it exists)
+
+In general, we have 2 options for this scenario:
+
+#### List / ListItem
+
+- Position: ✅
+ - as we established earlier, the `listitem` role is properly narrated together with its position
+- Actionable: N/A
+ - in this case, the list items themselves are not actionable
+- Selection: N/A
+ - in this case we don't have selection
+- Other considerations:
+ - Would the user expect to click right arrow key to get inside the list item?
+
+_For this scenario, List/ListItem seems like a good choice, since we don't need support for selection or actionable rows (list items)._
+
+#### Grid / Row / Gridcell
+
+While using Grid role for a list may seem unintuitive and irrelevant, it will come up later when we talk about selection in a complex list like this.
+
+I'm writing about it here for completion and to contrast it with the listitem role.
+
+In grid, each list item is of role `row` and each actionable element inside should be in its own `cell` role element.
+
+- Position: ❌
+ - The position is not properly narrated, we get `row` but not `row x of y`
+- Actionable: N/A
+- Selection: N/A
+- Other considerations: ⚠️
+ - The nature of `grid`/`row`/`gridcell` roles forces the developers to actually stick to this strict HTML layout. A cell should be wrapping actionable element, but it should be a direct child of the `row`, preventing users from building more complex widgets with custom HTML structure.
+
+### List with multiple actions - with selection
+
+[example](https://fluentuipr.z22.web.core.windows.net/pull/29760/public-docsite-v9/storybook/index.html?path=/docs/preview-components-list--default#multiple-actions-primary-selection)
+
+Things become a bit more complicated when selection is involved, as we need the proper a11y announcements when the selection state is changed. This is not supported for the `listitem` role, which we deemed perfect for complex list without selection. Even if `aria-selected` is added to a `listitem`, the screen readers just ignore that property (since it's not valid for `listitem` role).
+
+When the list supports selection, the main action of the list item is **to toggle the selection** by default.
+
+**Left mouse button** always triggers _onClick_, which toggles the selection, if enabled. A custom action can be triggered on click instead, by passing a custom `onClick` handler to the `ListItem` component and calling `preventDefault()` on the event. See how this works [here](https://fluentuipr.z22.web.core.windows.net/pull/29760/public-docsite-v9/storybook/index.html?path=/docs/preview-components-list--default#multiple-actions-different-primary).
+
+**Spacebar** on the `ListItem` always toggles the selection.
+
+**Enter** on the `ListItem` triggers the main action, which can be changed by passing the `onClick` handler, i.e. by default it triggers selection, but this behavior can be overriden (by changing the onClick handler).
+
+Both keys behavior can be changed by passing the `onKeyDown` handler and preventing teh default by calling `preventDefault()` on the event. Please note that the uncontrolled selection can no longer be utilized in this case and you have to take control.
+
+#### Listbox / option
+
+Since [all descendats of option are presentational](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/option_role#all_descendants_are_presentational), this role is not viable for this case, since we need to allow the screen reader to go inside of the list item to focus on the secondary actions.
+
+While this role technically works on Windows using the screen reader Focus mode, it actually **completely breaks Voice Over navigation on Mac OS** and therefore is unusable.
+
+#### Grid / Row / Gridcell
+
+- Position: ✴️
+ - While we get announcement for `row` as "row", we don't get the row number `row x of y` in any of the screen readers tested. This is a big limitation of this role, could be a chromium bug.
+ - This _can_ be worked around from the user world by passing the order as part of the `aria-label`. This is not without it's downsides though.
+- Actionable: ✅
+ - Since the rows can be selected, it is reasonable to expect that the users understand that they can trigger the action on the list item (row).
+- Selection: ✅
+ - Rows can be selected, and the selection is properly announced when it changes.
+- Other considerations: ⚠️
+ - As mentioned previously, when using this role, it is importand that the HTML structure is precisely `grid > row > gridcell > actionable element`. For some complex layouts, this may not be always easy / possible to do.
+
+_While grid role puts some constrain on the DOM structure to work properly, it is the only accessibility role I found that supports `aria-selected` and allows complex widgets inside._
+
+### List with multiple actions, without selection
+
+[example](https://fluentuipr.z22.web.core.windows.net/pull/29760/public-docsite-v9/storybook/index.html?path=/docs/preview-components-list--default#multiple-actions-no-selection-with-primary)
+
+When no selection is involved in the equation, we don't have to limit ourselves to using a11y roles that support `aria-selected`, which makes things a bit easier.
+
+#### Grid / Row / Gridcell
+
+- Position: ✴️
+ - dtto, `row` is announced, but no order
+- Actionable: ✴️
+ - While actions can be attached to the whole row, this is not a common pattern and it could lead to discoverability issue. When explicitely communicated in `aria-roledescription` or in `aria-label`, this could be solved.
+ - On the other hand, grid allows for better discoverability of secondary inside actions.
+- Selection: N/A
+- Other considerations: ⚠️
+ - Again, the combination of these roles requires developers to strictly adhere to the required DOM layout.
+
+#### List / Listitem
+
+- Position: ✅
+ - As established earlier, list has a great support for announcing list position
+- Actionable: ✅
+ - Action can be put directly on the List Item. Discoverability might be a small issue again, but a context, updated label or supporting aria attributes like `aria-roledescription` can easily solve that
+ - **It might be difficult to communicate that there are secondary actions that the user can navigate to.**
+- Selection: N/A
+
+_Both `grid` and `list` could be used in this scenario, both have downsides. List gives us better position narration, but doesn't implicitely communicate that there actions that can be focused by moving right. Grid solves this issue, but it's row positions aren't properly narrated (this has been brought up with NVDA/Jaws teams)._
diff --git a/packages/react-components/react-list-preview/docs/MIGRATION.md b/packages/react-components/react-list-preview/docs/MIGRATION.md
new file mode 100644
index 0000000000000..c82899517708e
--- /dev/null
+++ b/packages/react-components/react-list-preview/docs/MIGRATION.md
@@ -0,0 +1,203 @@
+# List migration
+
+## Migration from v8
+
+### Composition over configuration
+
+Compared to its v8 counterpart, the v9 `List` uses composition over configuration when it comes to rendering items, same as other components in Fluent UI React v9. This means that instead of passing an array of items to the `List` component, it's up to you to render `ListItem` components with appropriate content.
+
+Take this example in v8:
+
+```js
+const items = [{ name: 'John' }, { name: 'Alice' }];
+
+const MyList = () => {
+ return ;
+};
+```
+
+becomes this in v9:
+
+```js
+const items = [{ name: 'John' }, { name: 'Alice' }];
+
+const MyList = () => {
+ return (
+
+ {items.map(item => {
+ {item};
+ })}
+
+ );
+};
+```
+
+### Virtualization approach
+
+Virtualization is **not part** of `List` in Fluent UI React v9. We don't want to force any particular solution for virtualization, but we provide [examples](https://react.fluentui.dev/?path=/story/preview-components-list--virtualized-list-with-actionable-items) how to use `List` with a popular library `react-window` to get the desired effect.
+
+This makes the API of `List` much simpler.
+
+### v8 Property mapping
+
+Most of the v8 props are for it's virtualization functionality. Since the v9 `List` takes a different approach, most of the props cannot be directly migrated.
+
+| v8 List | v9 List |
+| ------------------------- | -------------------------------- |
+| `className` | `className` |
+| `componentRef` | `componentRef` |
+| `getItemCountForPage` | N/A |
+| `getKey` | N/A as you control the ListItems |
+| `getPageHeight` | N/A |
+| `getPageSpecification` | N/A |
+| `getPageStyle` | N/A |
+| `ignoreScrollingState` | N/A |
+| `items` | render `` instead |
+| `onPageAdded` | N/A |
+| `onPagesUpdated` | N/A |
+| `onRenderCell` | N/A |
+| `onRenderCellConditional` | N/A |
+| `onRenderPage` | N/A |
+| `onRenderRoot` | N/A |
+| `onRenderSurface` | N/A |
+| `onShouldVirtualize` | N/A |
+| `renderCount` | N/A |
+| `renderEarly` | N/A |
+| `renderedWindowsAhead` | N/A |
+| `renderedWindowsBehind` | N/A |
+| `role` | `role` |
+| `startIndex` | N/A |
+| `usePageCache` | N/A |
+| `version` | N/A |
+| - | `defaultSelectedItems` |
+| - | `onSelectionChange` |
+| - | `selectionMode` |
+
+## Migration from v0
+
+### Composition, also known as "Children API"
+
+In Fluent UI React v9 we prefer to use composition over configuration where possible. List is no exception. the v0 list also supports composition API under a name of "Children API".
+
+#### Children API component mapping
+
+Migrating from a v9 Children API to v9 composition API is quite straighforward. You can replace the components like this:
+
+- Use v9 `List` instead of v0 `List`
+- Use v9 `ListItem` instead of v0 `List.Item`
+
+For props please refer to [Property mapping](#v0-property-mapping) section.
+
+#### Shorthand API
+
+For Shorthand API things are a bit more complicated, as your code needs to me updated to use composition.
+
+Take this example in v0:
+
+```js
+const items = [
+ {
+ key: 'robert',
+ header: 'Robert Tolbert',
+ content: 'Program the sensor to the SAS alarm through the haptic SQL card!',
+ },
+ {
+ key: 'celeste',
+ header: 'Celeste Burton',
+ content: 'Use the online FTP application to input the multi-byte application!',
+ },
+];
+
+const MyList = () => {
+ return ;
+};
+```
+
+becomes this in v9:
+
+```js
+const items = [
+ {
+ key: 'robert',
+ header: 'Robert Tolbert',
+ content: 'Program the sensor to the SAS alarm through the haptic SQL card!',
+ },
+ {
+ key: 'celeste',
+ header: 'Celeste Burton',
+ content: 'Use the online FTP application to input the multi-byte application!',
+ },
+];
+
+const MyList = () => {
+ return (
+
+ {items.map(item => {
+
+
{item.header}
+
{item.content}>
+ ;
+ })}
+
+ );
+};
+```
+
+### v0 Property mapping
+
+Compared to its v0 counterpart, the v9 List implementation is much more generic and it **doesn't have any opinion** on how it's content should look like. This means that you will **not** find layout specific props like `header`, `headerMedia`, `content` or layout specific components. This allows for much more flexible use of the component.
+
+We recommend using a component like `Persona` where possible, or creating a custom layout component where necessary.
+
+#### List
+
+| v0 List | v9 List |
+| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `accessibility` | built in, customize with `useArrowNavigationGroup` from `tabster` |
+| `as` | `as` |
+| `className` | `className` |
+| `debug` | N/A |
+| `defaultSelectedIndex` | `defaultSelectedItems` |
+| `design` | N/A |
+| `horizontal` | N/A - will be added in the future |
+| `items` | N/A - use `ListItem` components as Children |
+| `navigable` | `navigable` |
+| `onSelectedIndexChange` | `onSelectionChange` |
+| `ref` | `ref` |
+| `selectable` | use `selectionMode` of value `single` or `multiselect` |
+| `selectedIndex` | only in controlled mode, use `selection` state; see [example](https://react.fluentui.dev/?path=/story/preview-components-list--list-selection-controlled). |
+| `styles` | use slots in combination with `className` |
+| `truncateContent` | N/A - the `List` is not concerned about it's content |
+| `truncateHeader` | N/A - the `List` is not concerned about it's content |
+| `variables` | N/A - use slots in combination with `className` |
+| `wrap` | N/A - the `List` is not concerned about it's content |
+
+#### ListItem
+
+| v0 ListItem | v9 ListItem |
+| ----------------- | ------------------------------------------------------------------------------------- |
+| `accessibility` | N/A |
+| `as` | `as` |
+| `className` | `className` |
+| `content` | N/A - use children |
+| `contentMedia` | N/A - use children |
+| `debug` | N/A |
+| `design` | N/A |
+| `endMedia` | N/A - use children |
+| `header` | N/A - use children |
+| `headerMedia` | N/A - use children |
+| `important` | N/A |
+| `index` | N/A |
+| `media` | N/A - use children |
+| `navigable` | N/A - use `tabIndex={0}` or `navigable` on the `List` |
+| `onClick` | `onAction` |
+| `ref` | ref |
+| `selectable` | N/A - use `List` props like `selectionMode`, `selectedItems` and `onSelectionChange` |
+| `selected` | N/A - use `selectedItems` (or tracked internally when `defaultSelectedItems` is used) |
+| `styles` | N/A - use `className` for any slot |
+| `truncateContent` | N/A - the `List` is not concerned about it's content |
+| `truncateHeader` | N/A - the `List` is not concerned about it's content |
+
+#### Other
+
+Other components like `ListItemContent`, `ListItemContentMedia`, `ListItemEndMedia`, `ListItemHeader`,`ListItemHeaderMedia` and `ListItemMedia` are _not_ currently present in v9 `List` implementation for the reasons mentioned above.
diff --git a/packages/react-components/react-list-preview/docs/Spec.md b/packages/react-components/react-list-preview/docs/Spec.md
index a3a755a6aa0de..cbf05e0b2ea7a 100644
--- a/packages/react-components/react-list-preview/docs/Spec.md
+++ b/packages/react-components/react-list-preview/docs/Spec.md
@@ -2,15 +2,19 @@
## Background
-_Description and use cases of this component_
+A List is a component that displays a set of vertically stacked components.
-## Prior Art
+If you are displaying more than one dimension of the data, the List probably isn't the proper component to use, instead, consider using Table or DataGrid.
+
+The List supports plain list items, interactive list items with one action or multiple actions. It also has support for single and multi selection built in. This can be utilized in either uncontrolled or controlled way.
-_Include background research done for this component_
+All of the List scenarios are also accessible, as the whole component was built with accessibility in mind. It is easily navigable with a keyboard and supports different screen reader applications.
+
+## Prior Art
-- _Link to Open UI research_
-- _Link to comparison of v7 and v0_
-- _Link to GitHub epic issue for the converged component_
+- [Fluent UI v0 docs](https://fluentsite.z22.web.core.windows.net/components/list/definition)
+- [Fluent UI v8 docs](https://developer.microsoft.com/en-us/fluentui#/controls/web/list)
+- [Open UI research](https://open-ui.org/components/list.research/)
## Sample Code
diff --git a/packages/react-components/react-list-preview/etc/react-list-preview.api.md b/packages/react-components/react-list-preview/etc/react-list-preview.api.md
index b065e9f82f8d8..e6d8e41b06262 100644
--- a/packages/react-components/react-list-preview/etc/react-list-preview.api.md
+++ b/packages/react-components/react-list-preview/etc/react-list-preview.api.md
@@ -4,84 +4,78 @@
```ts
+///
+
+import { Checkbox } from '@fluentui/react-checkbox';
import type { ComponentProps } from '@fluentui/react-utilities';
import type { ComponentState } from '@fluentui/react-utilities';
+import type { EventData } from '@fluentui/react-utilities';
+import type { EventHandler } from '@fluentui/react-utilities';
import type { ForwardRefComponent } from '@fluentui/react-utilities';
import * as React_2 from 'react';
+import { SelectionItemId } from '@fluentui/react-utilities';
+import type { SelectionMode as SelectionMode_2 } from '@fluentui/react-utilities';
import type { Slot } from '@fluentui/react-utilities';
import type { SlotClassNames } from '@fluentui/react-utilities';
-// @public
+// @public (undocumented)
export const List: ForwardRefComponent;
// @public (undocumented)
export const listClassNames: SlotClassNames;
-// @public
-export const ListItem: ForwardRefComponent;
-
-// @public
-export const ListItemButton: ForwardRefComponent;
-
-// @public (undocumented)
-export const listItemButtonClassNames: SlotClassNames;
-
-// @public
-export type ListItemButtonProps = ComponentProps & {};
-
// @public (undocumented)
-export type ListItemButtonSlots = {
- root: Slot<'div'>;
-};
-
-// @public
-export type ListItemButtonState = ComponentState;
+export const ListItem: ForwardRefComponent;
// @public (undocumented)
export const listItemClassNames: SlotClassNames;
// @public
-export type ListItemProps = ComponentProps & {};
+export type ListItemProps = ComponentProps & {
+ value?: string | number;
+ onAction?: (e: ListItemActionEvent) => void;
+};
// @public (undocumented)
export type ListItemSlots = {
- root: Slot<'div'>;
+ root: NonNullable>;
+ checkmark?: Slot;
};
// @public
-export type ListItemState = ComponentState;
+export type ListItemState = ComponentState & {
+ selectable: boolean;
+ navigable: boolean;
+};
// @public
-export type ListProps = ComponentProps & {};
+export type ListProps = ComponentProps & {
+ navigationMode?: ListNavigationMode;
+ selectionMode?: SelectionMode_2;
+ selectedItems?: SelectionItemId[];
+ defaultSelectedItems?: SelectionItemId[];
+ onSelectionChange?: EventHandler;
+};
// @public (undocumented)
export type ListSlots = {
- root: Slot<'div'>;
+ root: NonNullable>;
};
// @public
-export type ListState = ComponentState;
+export type ListState = ComponentState & ListContextValue;
// @public
-export const renderList_unstable: (state: ListState) => JSX.Element;
+export const renderList_unstable: (state: ListState, contextValues: ListContextValues) => JSX.Element;
// @public
export const renderListItem_unstable: (state: ListItemState) => JSX.Element;
// @public
-export const renderListItemButton_unstable: (state: ListItemButtonState) => JSX.Element;
-
-// @public
-export const useList_unstable: (props: ListProps, ref: React_2.Ref) => ListState;
-
-// @public
-export const useListItem_unstable: (props: ListItemProps, ref: React_2.Ref) => ListItemState;
-
-// @public
-export const useListItemButton_unstable: (props: ListItemButtonProps, ref: React_2.Ref) => ListItemButtonState;
+export const useList_unstable: (props: ListProps, ref: React_2.Ref) => ListState;
// @public
-export const useListItemButtonStyles_unstable: (state: ListItemButtonState) => ListItemButtonState;
+export const useListItem_unstable: (props: ListItemProps, ref: React_2.Ref) => ListItemState;
// @public
export const useListItemStyles_unstable: (state: ListItemState) => ListItemState;
diff --git a/packages/react-components/react-list-preview/package.json b/packages/react-components/react-list-preview/package.json
index 2deb5a999ed1d..b78e1d5aa3568 100644
--- a/packages/react-components/react-list-preview/package.json
+++ b/packages/react-components/react-list-preview/package.json
@@ -2,7 +2,7 @@
"name": "@fluentui/react-list-preview",
"version": "0.0.0",
"private": true,
- "description": "New fluentui react package",
+ "description": "React List v9",
"main": "lib-commonjs/index.js",
"module": "lib/index.js",
"typings": "./dist/index.d.ts",
@@ -27,7 +27,9 @@
"storybook": "start-storybook",
"test": "jest --passWithNoTests",
"test-ssr": "test-ssr \"./stories/**/*.stories.tsx\"",
- "type-check": "tsc -b tsconfig.json"
+ "type-check": "tsc -b tsconfig.json",
+ "e2e": "cypress run --component",
+ "e2e:local": "cypress open --component"
},
"devDependencies": {
"@fluentui/eslint-plugin": "*",
@@ -37,7 +39,11 @@
"@fluentui/scripts-tasks": "*"
},
"dependencies": {
+ "@fluentui/react-checkbox": "^9.2.18",
+ "@fluentui/react-context-selector": "^9.1.56",
"@fluentui/react-jsx-runtime": "^9.0.34",
+ "@fluentui/keyboard-keys": "^9.0.7",
+ "@fluentui/react-tabster": "^9.19.5",
"@fluentui/react-theme": "^9.1.19",
"@fluentui/react-utilities": "^9.18.5",
"@fluentui/react-shared-contexts": "^9.15.2",
diff --git a/packages/react-components/react-list-preview/src/ListItemButton.ts b/packages/react-components/react-list-preview/src/ListItemButton.ts
deleted file mode 100644
index 3737c764d3713..0000000000000
--- a/packages/react-components/react-list-preview/src/ListItemButton.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './components/ListItemButton/index';
diff --git a/packages/react-components/react-list-preview/src/components/List/List.cy.tsx b/packages/react-components/react-list-preview/src/components/List/List.cy.tsx
new file mode 100644
index 0000000000000..f850e8173e5a5
--- /dev/null
+++ b/packages/react-components/react-list-preview/src/components/List/List.cy.tsx
@@ -0,0 +1,450 @@
+import * as React from 'react';
+import { mount as mountBase } from '@cypress/react';
+import { FluentProvider } from '@fluentui/react-provider';
+import { teamsLightTheme } from '@fluentui/react-theme';
+
+import { List } from './List';
+import { ListItem } from '../ListItem';
+import { SelectionItemId } from '@fluentui/react-utilities';
+
+const mount = (element: JSX.Element) => {
+ mountBase({element});
+};
+
+/**
+ * Validates focus movement based on the sequence of keybaord commands
+ * Use focused: to validate the focused element after a given step
+ * @param sequence - Array of commands to execute
+ * @example
+ * testSequence([
+ * 'focused:list-item-1',
+ * 'DownArrow',
+ * 'focused:list-item-2',
+ * ])
+ */
+const testSequence = (sequence: Array) => {
+ cy.get('li:first-of-type').focus();
+ for (const command of sequence) {
+ if (command.startsWith('focused:')) {
+ const tid = command.split(':')[1];
+ cy.focused().should('have.attr', 'data-test', tid);
+ } else {
+ cy.focused().type(`{${command}}`);
+ }
+ }
+};
+
+const mountSimpleList = () => {
+ mount(
+
+ List Item 1
+ List Item 2
+ List Item 3
+ ,
+ );
+};
+
+const mountListWithSecondaryActions = () => {
+ mount(
+
+
+ List Item 1
+
+
+
+ List Item 2
+
+
+
+ List Item 3
+
+
+ ,
+ );
+};
+
+type SelectionTestListProps = {
+ selectionMode: React.ComponentProps['selectionMode'];
+ defaultSelectedItems?: React.ComponentProps['defaultSelectedItems'];
+ controlled?: boolean;
+};
+
+const SelectionTestList = ({ selectionMode, defaultSelectedItems, controlled }: SelectionTestListProps) => {
+ const [selectedItems, setSelectedItems] = React.useState(defaultSelectedItems || []);
+
+ const onChange = React.useCallback((_, { selectedItems: selected }) => {
+ setSelectedItems(selected);
+ }, []);
+
+ const onSelectLastClick = React.useCallback(_ => {
+ setSelectedItems(['list-item-3']);
+ }, []);
+
+ return (
+ <>
+
+
+ List Item 1
+
+
+ List Item 2
+
+
+ List Item 3
+
+
+
+