Skip to content

feat(view-pager): add PageIndicator - #1929

Open
bataevvlad wants to merge 2 commits into
masterfrom
feat/page-indicator
Open

bataevvlad wants to merge 2 commits into
masterfrom
feat/page-indicator

Conversation

@bataevvlad

@bataevvlad bataevvlad commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

ViewPager gives no indication of how many pages there are or which one is visible; apps that move from tabs to a pager lose that cue (#1355). onOffsetChange reports raw pixels and the consumer onLayout was dropped, so even a hand-rolled indicator could not follow the swipe.

Fix

  • New PageIndicator (src/components/ui/viewPager/pageIndicator.component.tsx, exported from the ui barrel): one dot per pageCount, the selected dot wider and coloured by status (default primary). Props: selectedIndex, progress (fractional page position; the dots grow / shrink between pages), onSelect (dot press), dotStyle, dotAccessibilityLabel, appearance. Dots are Pressables with role='button' and aria-selected; test ids @<testID>/dot-<i>.
  • Eva and Material mappings: a PageIndicator block (paddingHorizontal / paddingVertical 8, dotWidth / dotHeight 8, dotBorderRadius 4, dotMarginHorizontal 4, dotBackgroundColor background-basic-color-4, selectedDotWidth 16) with a status variant group for selectedDotBackgroundColor (primary default, basic = text-basic-color, control = color-control-default). Inserted before Popover in both files.
  • ViewPager now forwards a consumer onLayout (it was swallowed by the internal one). The laid-out view is the content strip, pages x page width wide, so pageWidth = layout.width / pageCount; documented on onLayout and onOffsetChange. Arrows stay app-side (onSelect(index ± 1)).
  • Showcase ViewPagerIndicator (end of SHOWCASES): a 4-page pager with a progress-driven indicator (labelled dots) and a danger one; Storybook viewPager.stories.tsx (WithPageIndicator, IndicatorStatuses); a PageIndicator section with the props table in view-pager.mdx.

Verification

  • Specs: pageIndicator.spec.tsx (7): one dot per page with the mapped size; selected dot width / status colour / aria-selected; primary and first page by default; progress interpolation between two pages; onSelect with the pressed index via the dot test id; dotAccessibilityLabel; dotStyle merge. viewPager.spec.tsx: consumer onLayout forwarded (fails on master).
  • Android emulator (Pixel 7, Eva light, section-ViewPagerIndicator): dots exposed as "Page 1 of 4" ... buttons; pressing dot 3 shows "Page: 3" and TRANSACTIONS; pressing dot 4 shows "Page: 4", "Progress: 3.00", and both indicators highlight the fourth dot (the progress-driven one only after the onLayout fix, which is how the dropped callback was found).
  • iOS simulator and yarn e2e:ios: see "iOS verification (2026-09-28)" below.
  • Gates: yarn turbo run build --filter=@ui-kitten/components, yarn typecheck:all, yarn lint (0 errors, 50 pre-existing warnings), yarn test --runInBand (75 suites, 1894 tests) pass.

Changeset: @ui-kitten/components minor, @ui-kitten/eva minor, @ui-kitten/material minor.

Closes #1355

iOS verification (2026-09-28)

iPhone 17 simulator (iOS 26.2), debug build on Metro from a clean worktree of this branch, driven with agent-device.

  • section-ViewPagerIndicator: swipe left -> Page: 2, Progress: 1.00, both indicators move to the second dot; dot 4 press -> Page: 4, Progress: 3.00; dot 3 press -> Page: 3, Progress: 2.00. Eva/Dark and Material/Dark: dots visible on the level-1 background, selected dot in primary / danger.
  • Old ViewPager section: swipe -> Page: 2, ORDERS.
  • yarn e2e:ios against a Metro serving this branch (the flags injected into a scratch copy of the scripts; without them agent-device test loads the bundle from :8081): smoke.ad and icon-touchable.ad pass; modal-nested.ad (step 51) and autocomplete.ad fail exactly as on master (both fixed in test(e2e): keep modals inside the snapshot budget #1918). An earlier run reported here had loaded another checkout's bundle from :8081 and did not test this branch.

Android verification (2026-09-28, second pass)

Pixel 7 emulator (API 34), debug build on Metro from a clean worktree of this branch, driven with agent-device.

  • section-ViewPagerIndicator: swipe -> Page: 2, Progress: 1.00; dot 4 -> Page: 4, Progress: 3.00; dot 3 -> Page: 3.
  • Found while testing: unselected dots used background-basic-color-4, 1.2-1.6:1 against the page in all four theme/mapping combos, nearly invisible in the dark themes. Fixed in 057384a: text-hint-color (2.8-5.0:1), with a spec over the four combinations (fails on the old token). Checked on device in all four combos.
  • Old ViewPager: swipe -> Page: 2.
  • popover-android.ad is stale on master (its fixed scroll count stops at the List section) and was not a branch check; test(e2e): reach showcase sections through a deep link #1932 replaces the scrolls with a section deep link. The Android replay line previously reported here had also loaded another checkout's bundle from :8081.

ViewPager gave no cue of how many pages there are or which one is
visible. PageIndicator renders one dot per page, the selected one wider
and coloured by status, and can follow the swipe through `progress`.
ViewPager now forwards a consumer onLayout instead of dropping it, which
the progress computation needs. Closes #1355.
The unselected dots used background-basic-color-4, which sits at
1.2-1.6:1 against the page background in the Eva and Material light
and dark themes, so the dots nearly vanished (dark themes worst).
Use text-hint-color (2.8-5.0:1) and check all four combinations.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Indicating the next and previous pages of a ViewPager

1 participant