diff --git a/.changeset/heavy-regions-camp.md b/.changeset/heavy-regions-camp.md new file mode 100644 index 0000000000..624758548d --- /dev/null +++ b/.changeset/heavy-regions-camp.md @@ -0,0 +1,7 @@ +--- +'@backstage/ui': patch +--- + +Added support for column width configuration in Table component. Columns now accept `width`, `defaultWidth`, `minWidth`, and `maxWidth` props for responsive layout control. + +Affected components: Table, Column diff --git a/packages/ui/report.api.md b/packages/ui/report.api.md index 295d5e8d4f..7643469bdc 100644 --- a/packages/ui/report.api.md +++ b/packages/ui/report.api.md @@ -7,6 +7,8 @@ import { ButtonProps as ButtonProps_2 } from 'react-aria-components'; import { CellProps as CellProps_2 } from 'react-aria-components'; import { CheckboxProps as CheckboxProps_2 } from 'react-aria-components'; import { ColumnProps as ColumnProps_2 } from 'react-aria-components'; +import type { ColumnSize } from '@react-types/table'; +import type { ColumnStaticSize } from '@react-types/table'; import { ComponentProps } from 'react'; import type { ComponentPropsWithRef } from 'react'; import { DetailedHTMLProps } from 'react'; @@ -478,6 +480,8 @@ export interface ColumnConfig { // (undocumented) cell: (item: T) => ReactNode; // (undocumented) + defaultWidth?: ColumnSize | null; + // (undocumented) header?: () => ReactNode; // (undocumented) id: string; @@ -490,7 +494,11 @@ export interface ColumnConfig { // (undocumented) label: string; // (undocumented) - width?: number | string; + maxWidth?: ColumnStaticSize | null; + // (undocumented) + minWidth?: ColumnStaticSize | null; + // (undocumented) + width?: ColumnSize | null; } // @public (undocumented) diff --git a/packages/ui/src/components/Table/components/Table.tsx b/packages/ui/src/components/Table/components/Table.tsx index 84211901a6..103a1aece9 100644 --- a/packages/ui/src/components/Table/components/Table.tsx +++ b/packages/ui/src/components/Table/components/Table.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { Key } from 'react-aria-components'; +import { type Key, ResizableTableContainer } from 'react-aria-components'; import { TableRoot } from './TableRoot'; import { TableHeader } from './TableHeader'; import { TableBody } from './TableBody'; @@ -132,67 +132,73 @@ export function Table({ {liveRegionLabel} - - - {column => - column.header ? ( - <>{column.header()} - ) : ( - - {column.label} - - ) - } - - {emptyState} : undefined - } + + - {item => { - const itemIndex = data?.indexOf(item) ?? -1; - - if (isRowRenderFn(rowConfig)) { - return rowConfig({ - item, - index: itemIndex, - }); + + {column => + column.header ? ( + <>{column.header()} + ) : ( + + {column.label} + + ) } + + {emptyState} : undefined + } + > + {item => { + const itemIndex = data?.indexOf(item) ?? -1; - return ( - rowConfig?.onClick?.(item) - : undefined - } - > - {column => ( - {column.cell(item)} - )} - - ); - }} - - + if (isRowRenderFn(rowConfig)) { + return rowConfig({ + item, + index: itemIndex, + }); + } + + return ( + rowConfig?.onClick?.(item) + : undefined + } + > + {column => ( + {column.cell(item)} + )} + + ); + }} + + + {pagination.type === 'page' && ( ( ), @@ -61,16 +62,19 @@ export const BasicLocalData: Story = { { id: 'owner', label: 'Owner', + defaultWidth: '1fr', cell: item => , }, { id: 'type', label: 'Type', + defaultWidth: '1fr', cell: item => , }, { id: 'lifecycle', label: 'Lifecycle', + defaultWidth: '1fr', cell: item => , }, ]; diff --git a/packages/ui/src/components/Table/stories/Table.docs.stories.tsx b/packages/ui/src/components/Table/stories/Table.docs.stories.tsx index 49e0b44885..aff656b083 100644 --- a/packages/ui/src/components/Table/stories/Table.docs.stories.tsx +++ b/packages/ui/src/components/Table/stories/Table.docs.stories.tsx @@ -40,6 +40,7 @@ export const TableRockBand: Story = { id: 'name', label: 'Band name', isRowHeader: true, + defaultWidth: '4fr', cell: item => ( ), @@ -47,16 +48,19 @@ export const TableRockBand: Story = { { id: 'genre', label: 'Genre', + defaultWidth: '4fr', cell: item => , }, { id: 'yearFormed', label: 'Year formed', + defaultWidth: '1fr', cell: item => , }, { id: 'albums', label: 'Albums', + defaultWidth: '1fr', cell: item => , }, ]; diff --git a/packages/ui/src/components/Table/types.ts b/packages/ui/src/components/Table/types.ts index 5fec5355e5..380be8817c 100644 --- a/packages/ui/src/components/Table/types.ts +++ b/packages/ui/src/components/Table/types.ts @@ -21,6 +21,7 @@ import { } from 'react-aria-components'; import type { ReactNode } from 'react'; import type { SortDescriptor as ReactStatelySortDescriptor } from 'react-stately'; +import type { ColumnSize, ColumnStaticSize } from '@react-types/table'; import type { TextColors } from '../../types'; import { TablePaginationProps } from '../TablePagination'; @@ -92,7 +93,10 @@ export interface ColumnConfig { header?: () => ReactNode; isSortable?: boolean; isHidden?: boolean; - width?: number | string; + width?: ColumnSize | null; + defaultWidth?: ColumnSize | null; + minWidth?: ColumnStaticSize | null; + maxWidth?: ColumnStaticSize | null; isRowHeader?: boolean; }