From cbe0316284b21c7a83a21d1f33f579200aa855c1 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 22 Apr 2026 17:37:56 +0000 Subject: [PATCH 01/13] Fix pagination layout on small screens Co-authored-by: Nataly Merezhuk --- .../Pagination/Pagination.responsive.test.tsx | 41 +++++++++++++++++++ .../Pagination/Pagination.stories.tsx | 21 ++++++++++ src/components/Pagination/Pagination.tsx | 1 + 3 files changed, 63 insertions(+) create mode 100644 src/components/Pagination/Pagination.responsive.test.tsx diff --git a/src/components/Pagination/Pagination.responsive.test.tsx b/src/components/Pagination/Pagination.responsive.test.tsx new file mode 100644 index 000000000..82082e189 --- /dev/null +++ b/src/components/Pagination/Pagination.responsive.test.tsx @@ -0,0 +1,41 @@ +import type { ReactNode } from 'react'; +import { renderCUI } from '@/utils/test-utils'; +import { Pagination } from '@/components/Pagination'; + +const containerMock = vi.fn(); + +vi.mock('@/components/Container', () => ({ + Container: (props: Record & { children?: ReactNode }) => { + containerMock(props); + return
{props.children}
; + }, +})); + +describe('Pagination responsive behavior', () => { + beforeEach(() => { + containerMock.mockClear(); + }); + + it('renders the outer layout container as non-responsive', () => { + renderCUI( + + ); + + expect( + containerMock.mock.calls.some(([props]) => { + const typedProps = props as { + isResponsive?: boolean; + justifyContent?: string; + }; + return ( + typedProps.isResponsive === false && + typedProps.justifyContent === 'space-between' + ); + }) + ).toBe(true); + }); +}); diff --git a/src/components/Pagination/Pagination.stories.tsx b/src/components/Pagination/Pagination.stories.tsx index 94a9db918..1bca8ef15 100644 --- a/src/components/Pagination/Pagination.stories.tsx +++ b/src/components/Pagination/Pagination.stories.tsx @@ -27,9 +27,30 @@ const PaginationRenderer = () => { ); }; +const PaginationResponsiveLayoutRenderer = () => { + const [currentPage, setCurrentPage] = useState(1); + const [pageSize, setPageSize] = useState(10); + + return ( + + ); +}; + export const Playground: Story = { args: { currentPage: 1, }, render: () => , }; + +export const ResponsiveLayoutPreview: Story = { + render: () => , +}; diff --git a/src/components/Pagination/Pagination.tsx b/src/components/Pagination/Pagination.tsx index 4705e5549..568dc6a25 100644 --- a/src/components/Pagination/Pagination.tsx +++ b/src/components/Pagination/Pagination.tsx @@ -130,6 +130,7 @@ export const Pagination = ({ return ( 0 ? 'space-between' : 'center') From b27349042a8507833d91f856a4e72195cad735b4 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 22 Apr 2026 18:11:15 +0000 Subject: [PATCH 02/13] Keep pagination controls horizontal on small screens Co-authored-by: Nataly Merezhuk --- .../Pagination/Pagination.responsive.test.tsx | 21 +++++++++++++++++++ src/components/Pagination/Pagination.tsx | 2 ++ 2 files changed, 23 insertions(+) diff --git a/src/components/Pagination/Pagination.responsive.test.tsx b/src/components/Pagination/Pagination.responsive.test.tsx index 82082e189..864e8beec 100644 --- a/src/components/Pagination/Pagination.responsive.test.tsx +++ b/src/components/Pagination/Pagination.responsive.test.tsx @@ -38,4 +38,25 @@ describe('Pagination responsive behavior', () => { }) ).toBe(true); }); + + it('renders all pagination layout containers as non-responsive', () => { + renderCUI( + + ); + + const nonResponsiveContainers = containerMock.mock.calls.filter(([props]) => { + const typedProps = props as { + isResponsive?: boolean; + }; + return typedProps.isResponsive === false; + }); + + expect(nonResponsiveContainers.length).toBeGreaterThanOrEqual(3); + }); }); diff --git a/src/components/Pagination/Pagination.tsx b/src/components/Pagination/Pagination.tsx index 568dc6a25..9aa79f66d 100644 --- a/src/components/Pagination/Pagination.tsx +++ b/src/components/Pagination/Pagination.tsx @@ -149,6 +149,7 @@ export const Pagination = ({ )} Date: Wed, 22 Apr 2026 18:11:39 +0000 Subject: [PATCH 03/13] Tune pagination preview story for desktop-like layout Co-authored-by: Nataly Merezhuk --- src/components/Pagination/Pagination.stories.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/Pagination/Pagination.stories.tsx b/src/components/Pagination/Pagination.stories.tsx index 1bca8ef15..6ca2376a6 100644 --- a/src/components/Pagination/Pagination.stories.tsx +++ b/src/components/Pagination/Pagination.stories.tsx @@ -29,7 +29,7 @@ const PaginationRenderer = () => { const PaginationResponsiveLayoutRenderer = () => { const [currentPage, setCurrentPage] = useState(1); - const [pageSize, setPageSize] = useState(10); + const [pageSize, setPageSize] = useState(-1); return ( { onChange={setCurrentPage} onPageSizeChange={setPageSize} pageSize={pageSize} - totalPages={20} - rowCount={1000} + totalPages={2} + rowCount={19} maxRowsPerPageList={[10, 25, 50]} + allowAllRows={false} /> ); }; From a5d4847d2421af1565a7f1ad438f082f2ed0ae5a Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 22 Apr 2026 18:23:36 +0000 Subject: [PATCH 04/13] Prevent total pages label from wrapping in pagination Co-authored-by: Nataly Merezhuk --- .../Pagination/Pagination.responsive.test.tsx | 12 ++++++++++++ src/components/Pagination/Pagination.tsx | 8 ++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/components/Pagination/Pagination.responsive.test.tsx b/src/components/Pagination/Pagination.responsive.test.tsx index 864e8beec..83de26223 100644 --- a/src/components/Pagination/Pagination.responsive.test.tsx +++ b/src/components/Pagination/Pagination.responsive.test.tsx @@ -59,4 +59,16 @@ describe('Pagination responsive behavior', () => { expect(nonResponsiveContainers.length).toBeGreaterThanOrEqual(3); }); + + it('renders total page text as a single inline token', () => { + const { getByText } = renderCUI( + + ); + + expect(getByText('of 2')).toBeInTheDocument(); + }); }); diff --git a/src/components/Pagination/Pagination.tsx b/src/components/Pagination/Pagination.tsx index 9aa79f66d..c99e114a2 100644 --- a/src/components/Pagination/Pagination.tsx +++ b/src/components/Pagination/Pagination.tsx @@ -47,6 +47,10 @@ const CustomSelect = styled.div` width: 150px; `; +const TotalPagesText = styled(Text)` + white-space: nowrap; +`; + export const Pagination = ({ totalPages, currentPage, @@ -179,13 +183,13 @@ export const Pagination = ({ /> {!!totalPages && ( - of {formatNumber(totalPages)} - + )} Date: Wed, 22 Apr 2026 18:26:39 +0000 Subject: [PATCH 05/13] Keep pagination labels on one line on mobile Co-authored-by: Nataly Merezhuk --- .../Pagination/Pagination.responsive.test.tsx | 12 ++++++++++++ src/components/Pagination/Pagination.tsx | 8 ++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/components/Pagination/Pagination.responsive.test.tsx b/src/components/Pagination/Pagination.responsive.test.tsx index 83de26223..5abac6a0e 100644 --- a/src/components/Pagination/Pagination.responsive.test.tsx +++ b/src/components/Pagination/Pagination.responsive.test.tsx @@ -71,4 +71,16 @@ describe('Pagination responsive behavior', () => { expect(getByText('of 2')).toBeInTheDocument(); }); + + it('keeps row count text on one line', () => { + const { getByText } = renderCUI( + + ); + + expect(getByText('19 rows')).toBeInTheDocument(); + }); }); diff --git a/src/components/Pagination/Pagination.tsx b/src/components/Pagination/Pagination.tsx index c99e114a2..cf2ff949d 100644 --- a/src/components/Pagination/Pagination.tsx +++ b/src/components/Pagination/Pagination.tsx @@ -47,6 +47,10 @@ const CustomSelect = styled.div` width: 150px; `; +const RowCountText = styled(Text)` + white-space: nowrap; +`; + const TotalPagesText = styled(Text)` white-space: nowrap; `; @@ -143,13 +147,13 @@ export const Pagination = ({ {...props} > {hasRowCount && ( - {typeof rowCount === 'number' ? formatNumber(rowCount) : rowCount} rows - + )} Date: Wed, 22 Apr 2026 18:37:39 +0000 Subject: [PATCH 06/13] Add responsive pagination story and remove responsive test Co-authored-by: Nataly Merezhuk --- .../Pagination/Pagination.responsive.test.tsx | 86 ------------------- .../Pagination/Pagination.stories.tsx | 20 ++++- 2 files changed, 18 insertions(+), 88 deletions(-) delete mode 100644 src/components/Pagination/Pagination.responsive.test.tsx diff --git a/src/components/Pagination/Pagination.responsive.test.tsx b/src/components/Pagination/Pagination.responsive.test.tsx deleted file mode 100644 index 5abac6a0e..000000000 --- a/src/components/Pagination/Pagination.responsive.test.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import type { ReactNode } from 'react'; -import { renderCUI } from '@/utils/test-utils'; -import { Pagination } from '@/components/Pagination'; - -const containerMock = vi.fn(); - -vi.mock('@/components/Container', () => ({ - Container: (props: Record & { children?: ReactNode }) => { - containerMock(props); - return
{props.children}
; - }, -})); - -describe('Pagination responsive behavior', () => { - beforeEach(() => { - containerMock.mockClear(); - }); - - it('renders the outer layout container as non-responsive', () => { - renderCUI( - - ); - - expect( - containerMock.mock.calls.some(([props]) => { - const typedProps = props as { - isResponsive?: boolean; - justifyContent?: string; - }; - return ( - typedProps.isResponsive === false && - typedProps.justifyContent === 'space-between' - ); - }) - ).toBe(true); - }); - - it('renders all pagination layout containers as non-responsive', () => { - renderCUI( - - ); - - const nonResponsiveContainers = containerMock.mock.calls.filter(([props]) => { - const typedProps = props as { - isResponsive?: boolean; - }; - return typedProps.isResponsive === false; - }); - - expect(nonResponsiveContainers.length).toBeGreaterThanOrEqual(3); - }); - - it('renders total page text as a single inline token', () => { - const { getByText } = renderCUI( - - ); - - expect(getByText('of 2')).toBeInTheDocument(); - }); - - it('keeps row count text on one line', () => { - const { getByText } = renderCUI( - - ); - - expect(getByText('19 rows')).toBeInTheDocument(); - }); -}); diff --git a/src/components/Pagination/Pagination.stories.tsx b/src/components/Pagination/Pagination.stories.tsx index 6ca2376a6..f52de67b3 100644 --- a/src/components/Pagination/Pagination.stories.tsx +++ b/src/components/Pagination/Pagination.stories.tsx @@ -1,5 +1,5 @@ import { Meta, StoryObj } from '@storybook/react-vite'; -import { useState } from 'react'; +import { ReactNode, useState } from 'react'; import { Pagination } from '@/components/Pagination'; const meta: Meta = { @@ -12,6 +12,10 @@ export default meta; type Story = StoryObj; +const MobileViewportFrame = ({ children }: { children: ReactNode }) => ( +
{children}
+); + const PaginationRenderer = () => { const [currentPage, setCurrentPage] = useState(1); @@ -53,5 +57,17 @@ export const Playground: Story = { }; export const ResponsiveLayoutPreview: Story = { - render: () => , + parameters: { + docs: { + description: { + story: + 'Responsive preview constrained to a mobile-width frame. Pagination layout should remain in a single horizontal row just like desktop.', + }, + }, + }, + render: () => ( + + + + ), }; From ded8cc18a622c773383b24a86d8f3a7174622b72 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 22 Apr 2026 18:43:40 +0000 Subject: [PATCH 07/13] Address pagination PR feedback and add changeset Co-authored-by: Nataly Merezhuk --- .changeset/fix-pagination-mobile-layout.md | 5 +++++ .../Pagination/Pagination.stories.tsx | 17 ++++++----------- src/components/Pagination/Pagination.tsx | 14 +++++--------- 3 files changed, 16 insertions(+), 20 deletions(-) create mode 100644 .changeset/fix-pagination-mobile-layout.md diff --git a/.changeset/fix-pagination-mobile-layout.md b/.changeset/fix-pagination-mobile-layout.md new file mode 100644 index 000000000..42f3fa6a1 --- /dev/null +++ b/.changeset/fix-pagination-mobile-layout.md @@ -0,0 +1,5 @@ +--- +"@clickhouse/click-ui": patch +--- + +Fix Pagination layout on small screens so it preserves the desktop horizontal structure without stacking labels or controls into columns. diff --git a/src/components/Pagination/Pagination.stories.tsx b/src/components/Pagination/Pagination.stories.tsx index f52de67b3..d989fe7ec 100644 --- a/src/components/Pagination/Pagination.stories.tsx +++ b/src/components/Pagination/Pagination.stories.tsx @@ -1,5 +1,5 @@ import { Meta, StoryObj } from '@storybook/react-vite'; -import { ReactNode, useState } from 'react'; +import { useState } from 'react'; import { Pagination } from '@/components/Pagination'; const meta: Meta = { @@ -12,10 +12,6 @@ export default meta; type Story = StoryObj; -const MobileViewportFrame = ({ children }: { children: ReactNode }) => ( -
{children}
-); - const PaginationRenderer = () => { const [currentPage, setCurrentPage] = useState(1); @@ -58,16 +54,15 @@ export const Playground: Story = { export const ResponsiveLayoutPreview: Story = { parameters: { + viewport: { + defaultViewport: 'mobile1', + }, docs: { description: { story: - 'Responsive preview constrained to a mobile-width frame. Pagination layout should remain in a single horizontal row just like desktop.', + 'Responsive preview rendered in a mobile viewport. Pagination layout should remain in a single horizontal row just like desktop.', }, }, }, - render: () => ( - - - - ), + render: () => , }; diff --git a/src/components/Pagination/Pagination.tsx b/src/components/Pagination/Pagination.tsx index cf2ff949d..2da1a4a35 100644 --- a/src/components/Pagination/Pagination.tsx +++ b/src/components/Pagination/Pagination.tsx @@ -47,11 +47,7 @@ const CustomSelect = styled.div` width: 150px; `; -const RowCountText = styled(Text)` - white-space: nowrap; -`; - -const TotalPagesText = styled(Text)` +const NoWrapText = styled(Text)` white-space: nowrap; `; @@ -147,13 +143,13 @@ export const Pagination = ({ {...props} > {hasRowCount && ( - {typeof rowCount === 'number' ? formatNumber(rowCount) : rowCount} rows - + )} {!!totalPages && ( - of {formatNumber(totalPages)} - + )} Date: Wed, 22 Apr 2026 18:48:43 +0000 Subject: [PATCH 08/13] Add table-integrated pagination responsive story Co-authored-by: Nataly Merezhuk --- .../Pagination/Pagination.stories.tsx | 216 ++++++++++++++++-- 1 file changed, 203 insertions(+), 13 deletions(-) diff --git a/src/components/Pagination/Pagination.stories.tsx b/src/components/Pagination/Pagination.stories.tsx index d989fe7ec..2c7fb6f0e 100644 --- a/src/components/Pagination/Pagination.stories.tsx +++ b/src/components/Pagination/Pagination.stories.tsx @@ -1,6 +1,11 @@ import { Meta, StoryObj } from '@storybook/react-vite'; -import { useState } from 'react'; +import { useEffect, useMemo, useState } from 'react'; import { Pagination } from '@/components/Pagination'; +import { + Table, + type TableColumnConfigProps, + type TableRowType, +} from '@/components/Table'; const meta: Meta = { component: Pagination, @@ -27,21 +32,206 @@ const PaginationRenderer = () => { ); }; +const tableHeaders: TableColumnConfigProps[] = [ + { label: 'File', width: '170px' }, + { label: 'Table', width: '170px' }, + { label: 'Timestamp', width: '180px' }, +]; + +const tableRows: TableRowType[] = [ + { + id: 'row-1', + items: [ + { label: 'archive-2024-01-15.csv' }, + { label: 'system.query_log' }, + { label: '2024-01-15 14:32:01' }, + ], + }, + { + id: 'row-2', + items: [ + { label: 'export-analytics.parquet' }, + { label: 'default.events' }, + { label: '2024-01-15 14:28:45' }, + ], + }, + { + id: 'row-3', + items: [ + { label: 'user-sessions.csv.gz' }, + { label: 'analytics.sessions' }, + { label: '2024-01-15 14:25:12' }, + ], + }, + { + id: 'row-4', + items: [ + { label: 'page-views.parquet' }, + { label: 'analytics.page_views' }, + { label: '2024-01-15 14:20:00' }, + ], + }, + { + id: 'row-5', + items: [ + { label: 'events-2024-01-14.csv' }, + { label: 'default.events_local' }, + { label: '2024-01-14 18:45:00' }, + ], + }, + { + id: 'row-6', + items: [ + { label: 'orders-jan.parquet' }, + { label: 'sales.orders' }, + { label: '2024-01-14 12:00:00' }, + ], + }, + { + id: 'row-7', + items: [ + { label: 'clickstream.log' }, + { label: 'web.clickstream' }, + { label: '2024-01-14 10:15:20' }, + ], + }, + { + id: 'row-8', + items: [ + { label: 'transactions.csv' }, + { label: 'payments.transactions' }, + { label: '2024-01-14 08:03:11' }, + ], + }, + { + id: 'row-9', + items: [ + { label: 'users-export.csv' }, + { label: 'auth.users' }, + { label: '2024-01-13 22:09:48' }, + ], + }, + { + id: 'row-10', + items: [ + { label: 'errors.ndjson' }, + { label: 'monitoring.errors' }, + { label: '2024-01-13 21:44:01' }, + ], + }, + { + id: 'row-11', + items: [ + { label: 'ad-impressions.csv' }, + { label: 'marketing.impressions' }, + { label: '2024-01-13 20:30:33' }, + ], + }, + { + id: 'row-12', + items: [ + { label: 'subscriptions.parquet' }, + { label: 'billing.subscriptions' }, + { label: '2024-01-13 19:10:07' }, + ], + }, + { + id: 'row-13', + items: [ + { label: 'shipments.csv' }, + { label: 'logistics.shipments' }, + { label: '2024-01-13 17:52:29' }, + ], + }, + { + id: 'row-14', + items: [ + { label: 'inventory-delta.csv' }, + { label: 'warehouse.inventory' }, + { label: '2024-01-13 16:05:44' }, + ], + }, + { + id: 'row-15', + items: [ + { label: 'audit-trail.log' }, + { label: 'security.audit_trail' }, + { label: '2024-01-13 14:11:59' }, + ], + }, + { + id: 'row-16', + items: [ + { label: 'metrics-hourly.csv' }, + { label: 'monitoring.metrics' }, + { label: '2024-01-13 12:26:14' }, + ], + }, + { + id: 'row-17', + items: [ + { label: 'orders-failed.csv' }, + { label: 'sales.orders_failed' }, + { label: '2024-01-13 11:40:23' }, + ], + }, + { + id: 'row-18', + items: [ + { label: 'cart-events.json' }, + { label: 'web.cart_events' }, + { label: '2024-01-13 10:05:51' }, + ], + }, + { + id: 'row-19', + items: [ + { label: 'feature-flags.csv' }, + { label: 'config.feature_flags' }, + { label: '2024-01-13 09:12:18' }, + ], + }, +]; + const PaginationResponsiveLayoutRenderer = () => { const [currentPage, setCurrentPage] = useState(1); - const [pageSize, setPageSize] = useState(-1); + const [pageSize, setPageSize] = useState(10); + + const totalRows = tableRows.length; + const totalPages = Math.max(1, Math.ceil(totalRows / pageSize)); + + useEffect(() => { + if (currentPage > totalPages) { + setCurrentPage(totalPages); + } + }, [currentPage, totalPages]); + + const visibleRows = useMemo(() => { + const start = (currentPage - 1) * pageSize; + return tableRows.slice(start, start + pageSize); + }, [currentPage, pageSize]); return ( - + <> + + { + setPageSize(value); + setCurrentPage(1); + }} + pageSize={pageSize} + totalPages={totalPages} + rowCount={totalRows} + maxRowsPerPageList={[10, 25, 50]} + allowAllRows={false} + /> + ); }; @@ -60,7 +250,7 @@ export const ResponsiveLayoutPreview: Story = { docs: { description: { story: - 'Responsive preview rendered in a mobile viewport. Pagination layout should remain in a single horizontal row just like desktop.', + 'Responsive preview rendered in a mobile viewport with a table and pagination. Pagination layout should remain in a single horizontal row just like desktop.', }, }, }, From dbceeca55474a4c2134a6781ee1253abb411c2c5 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 22 Apr 2026 18:54:58 +0000 Subject: [PATCH 09/13] Remove responsive pagination preview story Co-authored-by: Nataly Merezhuk --- .../Pagination/Pagination.stories.tsx | 225 +----------------- 1 file changed, 1 insertion(+), 224 deletions(-) diff --git a/src/components/Pagination/Pagination.stories.tsx b/src/components/Pagination/Pagination.stories.tsx index 2c7fb6f0e..94a9db918 100644 --- a/src/components/Pagination/Pagination.stories.tsx +++ b/src/components/Pagination/Pagination.stories.tsx @@ -1,11 +1,6 @@ import { Meta, StoryObj } from '@storybook/react-vite'; -import { useEffect, useMemo, useState } from 'react'; +import { useState } from 'react'; import { Pagination } from '@/components/Pagination'; -import { - Table, - type TableColumnConfigProps, - type TableRowType, -} from '@/components/Table'; const meta: Meta = { component: Pagination, @@ -32,227 +27,9 @@ const PaginationRenderer = () => { ); }; -const tableHeaders: TableColumnConfigProps[] = [ - { label: 'File', width: '170px' }, - { label: 'Table', width: '170px' }, - { label: 'Timestamp', width: '180px' }, -]; - -const tableRows: TableRowType[] = [ - { - id: 'row-1', - items: [ - { label: 'archive-2024-01-15.csv' }, - { label: 'system.query_log' }, - { label: '2024-01-15 14:32:01' }, - ], - }, - { - id: 'row-2', - items: [ - { label: 'export-analytics.parquet' }, - { label: 'default.events' }, - { label: '2024-01-15 14:28:45' }, - ], - }, - { - id: 'row-3', - items: [ - { label: 'user-sessions.csv.gz' }, - { label: 'analytics.sessions' }, - { label: '2024-01-15 14:25:12' }, - ], - }, - { - id: 'row-4', - items: [ - { label: 'page-views.parquet' }, - { label: 'analytics.page_views' }, - { label: '2024-01-15 14:20:00' }, - ], - }, - { - id: 'row-5', - items: [ - { label: 'events-2024-01-14.csv' }, - { label: 'default.events_local' }, - { label: '2024-01-14 18:45:00' }, - ], - }, - { - id: 'row-6', - items: [ - { label: 'orders-jan.parquet' }, - { label: 'sales.orders' }, - { label: '2024-01-14 12:00:00' }, - ], - }, - { - id: 'row-7', - items: [ - { label: 'clickstream.log' }, - { label: 'web.clickstream' }, - { label: '2024-01-14 10:15:20' }, - ], - }, - { - id: 'row-8', - items: [ - { label: 'transactions.csv' }, - { label: 'payments.transactions' }, - { label: '2024-01-14 08:03:11' }, - ], - }, - { - id: 'row-9', - items: [ - { label: 'users-export.csv' }, - { label: 'auth.users' }, - { label: '2024-01-13 22:09:48' }, - ], - }, - { - id: 'row-10', - items: [ - { label: 'errors.ndjson' }, - { label: 'monitoring.errors' }, - { label: '2024-01-13 21:44:01' }, - ], - }, - { - id: 'row-11', - items: [ - { label: 'ad-impressions.csv' }, - { label: 'marketing.impressions' }, - { label: '2024-01-13 20:30:33' }, - ], - }, - { - id: 'row-12', - items: [ - { label: 'subscriptions.parquet' }, - { label: 'billing.subscriptions' }, - { label: '2024-01-13 19:10:07' }, - ], - }, - { - id: 'row-13', - items: [ - { label: 'shipments.csv' }, - { label: 'logistics.shipments' }, - { label: '2024-01-13 17:52:29' }, - ], - }, - { - id: 'row-14', - items: [ - { label: 'inventory-delta.csv' }, - { label: 'warehouse.inventory' }, - { label: '2024-01-13 16:05:44' }, - ], - }, - { - id: 'row-15', - items: [ - { label: 'audit-trail.log' }, - { label: 'security.audit_trail' }, - { label: '2024-01-13 14:11:59' }, - ], - }, - { - id: 'row-16', - items: [ - { label: 'metrics-hourly.csv' }, - { label: 'monitoring.metrics' }, - { label: '2024-01-13 12:26:14' }, - ], - }, - { - id: 'row-17', - items: [ - { label: 'orders-failed.csv' }, - { label: 'sales.orders_failed' }, - { label: '2024-01-13 11:40:23' }, - ], - }, - { - id: 'row-18', - items: [ - { label: 'cart-events.json' }, - { label: 'web.cart_events' }, - { label: '2024-01-13 10:05:51' }, - ], - }, - { - id: 'row-19', - items: [ - { label: 'feature-flags.csv' }, - { label: 'config.feature_flags' }, - { label: '2024-01-13 09:12:18' }, - ], - }, -]; - -const PaginationResponsiveLayoutRenderer = () => { - const [currentPage, setCurrentPage] = useState(1); - const [pageSize, setPageSize] = useState(10); - - const totalRows = tableRows.length; - const totalPages = Math.max(1, Math.ceil(totalRows / pageSize)); - - useEffect(() => { - if (currentPage > totalPages) { - setCurrentPage(totalPages); - } - }, [currentPage, totalPages]); - - const visibleRows = useMemo(() => { - const start = (currentPage - 1) * pageSize; - return tableRows.slice(start, start + pageSize); - }, [currentPage, pageSize]); - - return ( - <> -
- { - setPageSize(value); - setCurrentPage(1); - }} - pageSize={pageSize} - totalPages={totalPages} - rowCount={totalRows} - maxRowsPerPageList={[10, 25, 50]} - allowAllRows={false} - /> - - ); -}; - export const Playground: Story = { args: { currentPage: 1, }, render: () => , }; - -export const ResponsiveLayoutPreview: Story = { - parameters: { - viewport: { - defaultViewport: 'mobile1', - }, - docs: { - description: { - story: - 'Responsive preview rendered in a mobile viewport with a table and pagination. Pagination layout should remain in a single horizontal row just like desktop.', - }, - }, - }, - render: () => , -}; From 2ab7d3fc3aa7a2dcaf9a7fdd659f207b1af5219b Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 22 Apr 2026 21:13:21 +0000 Subject: [PATCH 10/13] Lock pagination page input width on small screens Co-authored-by: Nataly Merezhuk --- src/components/Pagination/Pagination.tsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/components/Pagination/Pagination.tsx b/src/components/Pagination/Pagination.tsx index 2da1a4a35..df5b245f3 100644 --- a/src/components/Pagination/Pagination.tsx +++ b/src/components/Pagination/Pagination.tsx @@ -51,6 +51,12 @@ const NoWrapText = styled(Text)` white-space: nowrap; `; +const PageInputWrapper = styled.div` + width: 50px; + min-width: 50px; + max-width: 50px; +`; + export const Pagination = ({ totalPages, currentPage, @@ -163,11 +169,7 @@ export const Pagination = ({ onClick={onPrevClick} data-testid="prev-btn" /> - + - + {!!totalPages && ( Date: Wed, 22 Apr 2026 21:27:03 +0000 Subject: [PATCH 11/13] Prevent pagination page input from shrinking Co-authored-by: Nataly Merezhuk --- src/components/Pagination/Pagination.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Pagination/Pagination.tsx b/src/components/Pagination/Pagination.tsx index df5b245f3..1d78fc572 100644 --- a/src/components/Pagination/Pagination.tsx +++ b/src/components/Pagination/Pagination.tsx @@ -55,6 +55,7 @@ const PageInputWrapper = styled.div` width: 50px; min-width: 50px; max-width: 50px; + flex-shrink: 0; `; export const Pagination = ({ From 277de25750c532af5084454c47fdfc4b6a9ed7e7 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 22 Apr 2026 21:30:44 +0000 Subject: [PATCH 12/13] Make pagination page input width content-aware Co-authored-by: Nataly Merezhuk --- src/components/Pagination/Pagination.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/components/Pagination/Pagination.tsx b/src/components/Pagination/Pagination.tsx index 1d78fc572..710b50903 100644 --- a/src/components/Pagination/Pagination.tsx +++ b/src/components/Pagination/Pagination.tsx @@ -51,11 +51,9 @@ const NoWrapText = styled(Text)` white-space: nowrap; `; -const PageInputWrapper = styled.div` - width: 50px; - min-width: 50px; - max-width: 50px; - flex-shrink: 0; +const PageInputWrapper = styled.div<{ $digitCount: number }>` + flex: 0 0 auto; + width: ${({ $digitCount }) => `calc(${$digitCount}ch + 2.5rem)`}; `; export const Pagination = ({ @@ -79,6 +77,11 @@ export const Pagination = ({ }: PaginationProps): ReactElement => { const hasRowCount = ['number', 'string'].includes(typeof rowCount); const inputRef = useRef(null); + const pageDigits = Math.max( + 2, + currentPage.toString().length, + (totalPages ?? 0).toString().length + ); const formatNumber = (value: number) => { return new Intl.NumberFormat('en').format(value); }; @@ -170,7 +173,7 @@ export const Pagination = ({ onClick={onPrevClick} data-testid="prev-btn" /> - + Date: Wed, 22 Apr 2026 22:43:14 +0000 Subject: [PATCH 13/13] Use clamped adaptive width for pagination page input Co-authored-by: Nataly Merezhuk --- src/components/Pagination/Pagination.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/Pagination/Pagination.tsx b/src/components/Pagination/Pagination.tsx index 710b50903..4a86d9c77 100644 --- a/src/components/Pagination/Pagination.tsx +++ b/src/components/Pagination/Pagination.tsx @@ -49,11 +49,14 @@ const CustomSelect = styled.div` const NoWrapText = styled(Text)` white-space: nowrap; + word-break: normal; + overflow-wrap: normal; + flex-shrink: 0; `; const PageInputWrapper = styled.div<{ $digitCount: number }>` flex: 0 0 auto; - width: ${({ $digitCount }) => `calc(${$digitCount}ch + 2.5rem)`}; + width: ${({ $digitCount }) => `clamp(44px, calc(${$digitCount}ch + 2.5rem), 72px)`}; `; export const Pagination = ({