diff --git a/.changeset/hip-parents-fall.md b/.changeset/hip-parents-fall.md
new file mode 100644
index 0000000000..2beddba466
--- /dev/null
+++ b/.changeset/hip-parents-fall.md
@@ -0,0 +1,7 @@
+---
+'@backstage/ui': patch
+---
+
+Added support for disabling pagination in `useTable` complete mode by setting `paginationOptions: { type: 'none' }`. This skips data slicing and produces `pagination: { type: 'none' }` in `tableProps`, removing the need for consumers to manually override the pagination prop on `Table`. Also fixed complete mode not reacting to dynamic changes in `paginationOptions.pageSize`.
+
+**Affected components:** `useTable`
diff --git a/docs-ui/src/app/components/table/page.mdx b/docs-ui/src/app/components/table/page.mdx
index fc43256adb..5323804c88 100644
--- a/docs-ui/src/app/components/table/page.mdx
+++ b/docs-ui/src/app/components/table/page.mdx
@@ -119,7 +119,7 @@ With `mode: 'complete'`, sorting happens client-side. Provide a `sortFn` that re
### Pagination
-Configure page size and available options through `paginationOptions`. The table displays navigation controls automatically.
+Configure page size and available options through `paginationOptions`. The table displays navigation controls automatically. In `complete` mode, set `type: 'none'` to disable pagination and show all rows.
diff --git a/docs-ui/src/app/components/table/props-definition.tsx b/docs-ui/src/app/components/table/props-definition.tsx
index 77254ae0a1..6e5809412e 100644
--- a/docs-ui/src/app/components/table/props-definition.tsx
+++ b/docs-ui/src/app/components/table/props-definition.tsx
@@ -45,15 +45,44 @@ export const useTableOptionsPropDefs: Record = {
'The data for the table. Only applicable for "complete" mode, and either this or `getData` must be provided.',
},
paginationOptions: {
- type: 'enum',
- values: ['object'],
- description: (
- <>
- Pagination configuration including pageSize,{' '}
- pageSizeOptions, initialOffset, and{' '}
- showPaginationLabel.
- >
- ),
+ type: 'complex',
+ description: 'Pagination configuration.',
+ complexType: {
+ name: 'PaginationOptions',
+ properties: {
+ type: {
+ type: "'page' | 'none'",
+ description:
+ "Pagination mode. Set to 'none' to disable pagination and show all rows (complete mode only). Defaults to 'page'.",
+ },
+ pageSize: {
+ type: 'number',
+ description: 'Number of items per page. Defaults to 20.',
+ },
+ pageSizeOptions: {
+ type: 'number[]',
+ description: 'Available page size options for the dropdown.',
+ },
+ initialOffset: {
+ type: 'number',
+ description: 'Starting offset for the first page.',
+ },
+ showPageSizeOptions: {
+ type: 'boolean',
+ description:
+ 'Whether to show the page size dropdown. Defaults to true.',
+ },
+ showPaginationLabel: {
+ type: 'boolean',
+ description:
+ "Whether to display the pagination label (e.g., '1 - 20 of 150').",
+ },
+ getLabel: {
+ type: '(props) => string',
+ description: 'Custom function to generate the pagination label text.',
+ },
+ },
+ },
},
// Uncontrolled state
initialSort: {
diff --git a/packages/ui/report.api.md b/packages/ui/report.api.md
index f8aa8a024f..d19fdc8c56 100644
--- a/packages/ui/report.api.md
+++ b/packages/ui/report.api.md
@@ -906,6 +906,12 @@ export type Columns =
| '12'
| 'auto';
+// @public (undocumented)
+export interface CompletePaginationOptions extends PaginationOptions {
+ // (undocumented)
+ type?: 'page' | 'none';
+}
+
// @public (undocumented)
export const Container: ForwardRefExoticComponent<
ContainerProps & RefAttributes
@@ -3162,7 +3168,17 @@ export const useBreakpoint: () => {
// @public (undocumented)
export function useTable(
- options: UseTableOptions,
+ options: UseTableCompleteOptions,
+): UseTableResult;
+
+// @public (undocumented)
+export function useTable(
+ options: UseTableOffsetOptions,
+): UseTableResult;
+
+// @public (undocumented)
+export function useTable(
+ options: UseTableCursorOptions,
): UseTableResult;
// @public (undocumented)
@@ -3171,7 +3187,7 @@ export type UseTableCompleteOptions<
TFilter = unknown,
> = QueryOptions & {
mode: 'complete';
- paginationOptions?: PaginationOptions;
+ paginationOptions?: CompletePaginationOptions;
sortFn?: (data: T[], sort: SortDescriptor) => T[];
filterFn?: (data: T[], filter: TFilter) => T[];
searchFn?: (data: T[], search: string) => T[];
diff --git a/packages/ui/src/components/Table/hooks/types.ts b/packages/ui/src/components/Table/hooks/types.ts
index 1c69cc7591..06c980efdf 100644
--- a/packages/ui/src/components/Table/hooks/types.ts
+++ b/packages/ui/src/components/Table/hooks/types.ts
@@ -62,6 +62,11 @@ export interface PaginationOptions
initialOffset?: number;
}
+/** @public */
+export interface CompletePaginationOptions extends PaginationOptions {
+ type?: 'page' | 'none';
+}
+
/** @public */
export interface OffsetParams {
offset: number;
@@ -102,7 +107,7 @@ export type UseTableCompleteOptions<
TFilter = unknown,
> = QueryOptions & {
mode: 'complete';
- paginationOptions?: PaginationOptions;
+ paginationOptions?: CompletePaginationOptions;
sortFn?: (data: T[], sort: SortDescriptor) => T[];
filterFn?: (data: T[], filter: TFilter) => T[];
searchFn?: (data: T[], search: string) => T[];
diff --git a/packages/ui/src/components/Table/hooks/useCompletePagination.ts b/packages/ui/src/components/Table/hooks/useCompletePagination.ts
index e382cf6413..f34e2c8c06 100644
--- a/packages/ui/src/components/Table/hooks/useCompletePagination.ts
+++ b/packages/ui/src/components/Table/hooks/useCompletePagination.ts
@@ -38,8 +38,11 @@ export function useCompletePagination(
searchFn,
} = options;
const hasGetData = 'getData' in options;
+ const noPagination = paginationOptions.type === 'none';
const { initialOffset = 0 } = paginationOptions;
- const defaultPageSize = getEffectivePageSize(paginationOptions);
+ const defaultPageSize = noPagination
+ ? Infinity
+ : getEffectivePageSize(paginationOptions);
const getData = useStableCallback(getDataProp);
const { sort, filter, search } = query;
@@ -52,6 +55,12 @@ export function useCompletePagination(
const [offset, setOffset] = useState(initialOffset);
const [pageSize, setPageSize] = useState(defaultPageSize);
+ // Sync pageSize when the caller changes paginationOptions.pageSize
+ useEffect(() => {
+ setPageSize(defaultPageSize);
+ setOffset(0);
+ }, [defaultPageSize]);
+
// Load data on mount and when loadCount changes (reload trigger)
useEffect(() => {
if (data) {
@@ -121,12 +130,15 @@ export function useCompletePagination(
// Paginate the processed data
const paginatedData = useMemo(
- () => processedData?.slice(offset, offset + pageSize),
- [processedData, offset, pageSize],
+ () =>
+ noPagination
+ ? processedData
+ : processedData?.slice(offset, offset + pageSize),
+ [processedData, offset, pageSize, noPagination],
);
- const hasNextPage = offset + pageSize < totalCount;
- const hasPreviousPage = offset > 0;
+ const hasNextPage = !noPagination && offset + pageSize < totalCount;
+ const hasPreviousPage = !noPagination && offset > 0;
const onNextPage = useCallback(() => {
if (offset + pageSize < totalCount) {
diff --git a/packages/ui/src/components/Table/hooks/useTable.ts b/packages/ui/src/components/Table/hooks/useTable.ts
index de70534280..5997416915 100644
--- a/packages/ui/src/components/Table/hooks/useTable.ts
+++ b/packages/ui/src/components/Table/hooks/useTable.ts
@@ -16,8 +16,10 @@
import { useMemo, useRef } from 'react';
import type { SortState, TableItem, TableProps } from '../types';
import type {
- PaginationOptions,
PaginationResult,
+ UseTableCompleteOptions,
+ UseTableCursorOptions,
+ UseTableOffsetOptions,
UseTableOptions,
UseTableResult,
} from './types';
@@ -29,7 +31,7 @@ import { useOffsetPagination } from './useOffsetPagination';
function useTableProps(
paginationResult: PaginationResult,
sortState: SortState,
- paginationOptions: PaginationOptions = {},
+ paginationOptions: UseTableCompleteOptions['paginationOptions'] = {},
): Omit<
TableProps,
'columnConfig' | 'rowConfig' | 'selection' | 'emptyState'
@@ -52,8 +54,11 @@ function useTableProps(
const displayData = paginationResult.data ?? previousDataRef.current;
const isStale = paginationResult.loading && displayData !== undefined;
- const pagination = useMemo(
- () => ({
+ const pagination = useMemo(() => {
+ if (paginationOptions.type === 'none') {
+ return { type: 'none' as const };
+ }
+ return {
type: 'page' as const,
pageSize: paginationResult.pageSize,
pageSizeOptions,
@@ -76,25 +81,25 @@ function useTableProps(
showPageSizeOptions,
getLabel,
showPaginationLabel,
- }),
- [
- paginationResult.pageSize,
- pageSizeOptions,
- paginationResult.offset,
- paginationResult.totalCount,
- paginationResult.hasNextPage,
- paginationResult.hasPreviousPage,
- paginationResult.onNextPage,
- paginationResult.onPreviousPage,
- paginationResult.onPageSizeChange,
- onNextPageCallback,
- onPreviousPageCallback,
- onPageSizeChangeCallback,
- showPageSizeOptions,
- getLabel,
- showPaginationLabel,
- ],
- );
+ };
+ }, [
+ paginationOptions.type,
+ paginationResult.pageSize,
+ pageSizeOptions,
+ paginationResult.offset,
+ paginationResult.totalCount,
+ paginationResult.hasNextPage,
+ paginationResult.hasPreviousPage,
+ paginationResult.onNextPage,
+ paginationResult.onPreviousPage,
+ paginationResult.onPageSizeChange,
+ onNextPageCallback,
+ onPreviousPageCallback,
+ onPageSizeChangeCallback,
+ showPageSizeOptions,
+ getLabel,
+ showPaginationLabel,
+ ]);
return useMemo(
() => ({
@@ -117,6 +122,17 @@ function useTableProps(
}
/** @public */
+export function useTable(
+ options: UseTableCompleteOptions,
+): UseTableResult;
+/** @public */
+export function useTable(
+ options: UseTableOffsetOptions,
+): UseTableResult;
+/** @public */
+export function useTable(
+ options: UseTableCursorOptions,
+): UseTableResult;
export function useTable(
options: UseTableOptions,
): UseTableResult {
diff --git a/packages/ui/src/components/Table/index.ts b/packages/ui/src/components/Table/index.ts
index 033d51cdaa..d2847fae38 100644
--- a/packages/ui/src/components/Table/index.ts
+++ b/packages/ui/src/components/Table/index.ts
@@ -69,6 +69,7 @@ export type {
SearchState,
QueryOptions,
PaginationOptions,
+ CompletePaginationOptions,
} from './hooks/types';
export { TableDefinition } from './definition';