Repository: aws-amplify/amplify-ui (2025-08-12T14:07:16Z)

Issue:
Table support missing in Collection Primitive
### Before creating a new issue, please confirm:


- [X] I have [searched for duplicate or closed issues](https://github.com/aws-amplify/amplify-ui/issues?q=is%3Aissue+) and [discussions](https://github.com/aws-amplify/amplify-ui/discussions).
- [X] I have tried disabling all browser extensions or using a different browser
- [X] I have tried deleting the node_modules folder and reinstalling my dependencies
- [X] I have read the guide for [submitting bug reports](https://github.com/aws-amplify/amplify-ui/blob/main/CONTRIBUTING.md#bug-reports).

### On which framework/platform are you having an issue?

React

### Which UI component?

Other

### How is your app built?

NA

### What browsers are you seeing the problem on?

_No response_

### Please describe your bug.

The Collection component exports `table` type which is currently not implemented.

https://github.com/aws-amplify/amplify-ui/blob/main/packages/react/src/primitives/types/collection.ts#L6
https://github.com/aws-amplify/amplify-ui/blob/81903d1ee63832b995df80e918c32b1b25783f0a/packages/react/src/primitives/Collection/Collection.tsx#L101-L114

### What's the expected behaviour?

type="table" should render a TableRow

### Help us reproduce the bug!

This will render null even if users is populated with an array.

```jsx
<Table highlightOnHover={true} size="small" variation="striped">
      <TableHead>
        <TableCell as="th">Id</TableCell>
        <TableCell as="th">First Name</TableCell>
        <TableCell as="th">Last Name</TableCell>
        <TableCell as="th">Team</TableCell>
      </TableHead>
      <TableBody>
        <Collection items={users} type="table">
          {(item, index) => (
            <TableRow>
              <TableCell>{item.id}</TableCell>
              <TableCell>{item.firstName}</TableCell>
              <TableCell>{item.lastName}</TableCell>
              <TableCell>{item.teamId}</TableCell>
            </TableRow>
          )}
        </Collection>
      </TableBody>
    </Table>
 ```

### Code Snippet

```typescript
// Put your code below this line.

```


### Additional information and screenshots

_No response_


Discussion:
its literally in the documentation as implemented, but it's not. when can this be expected? 



Patch:
diff --git a/.changeset/unlucky-otters-dress.md b/.changeset/unlucky-otters-dress.md
new file mode 100644
index 00000000000..6945ff68c0a
--- /dev/null
+++ b/.changeset/unlucky-otters-dress.md
@@ -0,0 +1,5 @@
+---
+"@aws-amplify/ui-react": minor
+---
+
+feat(collection): Add `table` type to `Collection` UI primitive
diff --git a/packages/react/src/primitives/Collection/Collection.tsx b/packages/react/src/primitives/Collection/Collection.tsx
index c77c2177908..321ea3d49d5 100644
--- a/packages/react/src/primitives/Collection/Collection.tsx
+++ b/packages/react/src/primitives/Collection/Collection.tsx
@@ -16,8 +16,10 @@ import type {
   ElementType,
   GridCollectionProps,
   ListCollectionProps,
+  TableCollectionProps,
 } from '../types';
 import { getItemsAtPage, itemHasText, getPageCount } from './utils';
+import { Table, TableBody } from '../Table';
 
 const DEFAULT_PAGE_SIZE = 10;
 const TYPEAHEAD_DELAY_MS = 300;
@@ -41,6 +43,18 @@ const GridCollection = <Item,>({
   <Grid {...rest}>{Array.isArray(items) ? items.map(children) : null}</Grid>
 );
 
+const TableCollection = <Item,>({
+  children,
+  items,
+  tableHeader: TableHeader,
+  ...rest
+}: TableCollectionProps<Item>) => (
+  <Table {...rest}>
+    <TableHeader />
+    <TableBody>{Array.isArray(items) ? items.map(children) : null}</TableBody>
+  </Table>
+);
+
 const renderCollectionOrNoResultsFound = <Item,>(
   collection: React.JSX.Element | null,
   items: Item[],
@@ -114,6 +128,13 @@ export const Collection = <Item, Element extends ElementType>({
         items={items}
         {...rest}
       />
+    ) : type === 'table' ? (
+      <TableCollection
+        className={ComponentClassName.CollectionItems}
+        items={items}
+        tableHeader={(rest as Partial<TableCollectionProps<Item>>).tableHeader!}
+        {...rest}
+      />
     ) : null;
 
   return (
diff --git a/packages/react/src/primitives/types/collection.ts b/packages/react/src/primitives/types/collection.ts
index e22f4704822..e5a18879283 100644
--- a/packages/react/src/primitives/types/collection.ts
+++ b/packages/react/src/primitives/types/collection.ts
@@ -81,6 +81,14 @@ export type ListCollectionProps<Item> = Omit<BaseFlexProps, 'children'> &
   CollectionBaseProps<Item>;
 export type GridCollectionProps<Item> = Omit<BaseGridProps, 'children'> &
   CollectionBaseProps<Item>;
+export type TableCollectionProps<Item> = Omit<BaseGridProps, 'children'> &
+  CollectionBaseProps<Item> & {
+    /**
+     * @description
+     * Custom table header component to be rendered at the top of the table
+     */
+    tableHeader: () => React.ReactNode;
+  };
 
 /**
  * Omits `React.ReactNode` as children to prevent intersection type for `children` of
@@ -98,6 +106,7 @@ export type BaseCollectionProps<
   (
     | ReplaceChildren<{ type: 'list' } & ListCollectionProps<Item>, Item>
     | ReplaceChildren<{ type: 'grid' } & GridCollectionProps<Item>, Item>
+    | ReplaceChildren<{ type: 'table' } & TableCollectionProps<Item>, Item>
   );
 
 export type CollectionProps<


Test patch:
diff --git a/packages/react/src/primitives/Collection/__tests__/Collection.test.tsx b/packages/react/src/primitives/Collection/__tests__/Collection.test.tsx
index a7eaa2fa630..c5ba19d7f89 100644
--- a/packages/react/src/primitives/Collection/__tests__/Collection.test.tsx
+++ b/packages/react/src/primitives/Collection/__tests__/Collection.test.tsx
@@ -10,6 +10,7 @@ import { Flex } from '../../Flex';
 import { Text } from '../../Text';
 import { ComponentText } from '../../shared/constants';
 import { ComponentPropsToStylePropsMap } from '../../types';
+import { TableCell, TableHead, TableRow } from '../../Table';
 
 const emojis = [
   {
@@ -282,4 +283,45 @@ describe('Collection component', () => {
     const noResults = await screen.findByText(customText);
     expect(noResults).toBeDefined();
   });
+
+  it('should render table with table header when type is table', async () => {
+    const borderStyle = '1px solid red';
+    render(
+      <Collection
+        testId={testList}
+        type="table"
+        items={emojis}
+        border={borderStyle}
+        tableHeader={() => (
+          <TableRow>
+            <TableHead>Title</TableHead>
+            <TableHead>Emoji</TableHead>
+          </TableRow>
+        )}
+      >
+        {(item, _index) => (
+          <TableRow>
+            <TableCell>{item.title}</TableCell>
+            <TableCell>{item.emoji}</TableCell>
+          </TableRow>
+        )}
+      </Collection>
+    );
+
+    const collection = await screen.findByTestId(testList);
+    const items = getElementByClassName<HTMLDivElement>(
+      collection,
+      ComponentClassName.CollectionItems
+    );
+
+    expect(
+      items?.style.getPropertyValue(
+        kebabCase(ComponentPropsToStylePropsMap.border)
+      )
+    ).toBe(borderStyle);
+
+    const tdNode = items?.children[1].children[0].children[0];
+    expect(tdNode?.nodeName).toBe('TD');
+    expect(tdNode?.innerHTML).toBe('LOL');
+  });
 });