Skip to content

fix(pagination): replace onchange with onsubmit#2846

Closed
zeroedin wants to merge 13 commits intostaging/eeveefrom
fix/pagination/onsubmit
Closed

fix(pagination): replace onchange with onsubmit#2846
zeroedin wants to merge 13 commits intostaging/eeveefrom
fix/pagination/onsubmit

Conversation

@zeroedin
Copy link
Collaborator

@zeroedin zeroedin commented Feb 26, 2026

What I did

  1. Wrapped numeric input in a <form> for mobile submit support
  2. Added enterkeyhint="go" attribute replacing inputmode="numeric" giving the mobile keyboard a enter key the represents a navigation action.

TODO

  • Write tests

Testing Instructions

  1. View demo Changing the value of the input will no longer update the URL onChange, now requires a enter keypress. On mobile the enterkeyhint="go" should display a navigation style enter key.

Notes to Reviewers

Please look at mobile browser if you have android phone I do not so I can't test the enterkeyhint there.

This change does change the user expectation that the input field change auto submits via onChange -> onSubmit which needs the user to press enter or hit the "go" button? Does we think this constitute enough for a major change? Feel it maybe in a grey area.

@changeset-bot
Copy link

changeset-bot bot commented Feb 26, 2026

🦋 Changeset detected

Latest commit: bea8787

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@rhds/elements Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@netlify
Copy link

netlify bot commented Feb 26, 2026

Deploy Preview for red-hat-design-system ready!

Name Link
🔨 Latest commit bea8787
🔍 Latest deploy log https://app.netlify.com/projects/red-hat-design-system/deploys/69a5cc57cd877f0008d6481b
😎 Deploy Preview https://deploy-preview-2846--red-hat-design-system.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@zeroedin zeroedin changed the base branch from main to staging/eevee February 26, 2026 18:06
@zeroedin zeroedin self-assigned this Feb 26, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Feb 26, 2026

Size Change: +76 B (+0.03%)

Total Size: 261 kB

Filename Size Change
./elements/rh-pagination/rh-pagination.js 5.9 kB +76 B (+1.3%)
ℹ️ View Unchanged
Filename Size
./elements.js 640 B
./elements/rh-accordion/context.js 162 B
./elements/rh-accordion/rh-accordion-header.js 2.71 kB
./elements/rh-accordion/rh-accordion-panel.js 1.27 kB
./elements/rh-accordion/rh-accordion.js 3.35 kB
./elements/rh-alert/rh-alert.js 5.09 kB
./elements/rh-announcement/rh-announcement.js 2.18 kB
./elements/rh-audio-player/rh-audio-player-about.js 1.83 kB
./elements/rh-audio-player/rh-audio-player-rate-stepper.js 1.76 kB
./elements/rh-audio-player/rh-audio-player-scrolling-text-overflow.js 1.47 kB
./elements/rh-audio-player/rh-audio-player-subscribe.js 1.41 kB
./elements/rh-audio-player/rh-audio-player.js 12.4 kB
./elements/rh-audio-player/rh-cue.js 1.95 kB
./elements/rh-audio-player/rh-transcript.js 2.68 kB
./elements/rh-avatar/random-pattern-controller.js 2.72 kB
./elements/rh-avatar/rh-avatar.js 3.01 kB
./elements/rh-back-to-top/rh-back-to-top.js 1.98 kB
./elements/rh-badge/rh-badge.js 1.62 kB
./elements/rh-blockquote/rh-blockquote.js 1.38 kB
./elements/rh-breadcrumb/rh-breadcrumb.js 1.67 kB
./elements/rh-button-group/rh-button-group.js 679 B
./elements/rh-button/rh-button.js 3.36 kB
./elements/rh-card/rh-card.js 3.13 kB
./elements/rh-chip/context.js 165 B
./elements/rh-chip/rh-chip-group.js 1.58 kB
./elements/rh-chip/rh-chip.js 2.06 kB
./elements/rh-code-block/prism.css.js 667 B
./elements/rh-code-block/prism.js 572 B
./elements/rh-code-block/rh-code-block.js 8.71 kB
./elements/rh-cta/rh-cta.js 3.72 kB
./elements/rh-dialog/rh-dialog.js 4.72 kB
./elements/rh-dialog/yt-api.js 617 B
./elements/rh-disclosure/rh-disclosure.js 2.53 kB
./elements/rh-footer/rh-footer-block.js 714 B
./elements/rh-footer/rh-footer-copyright.js 357 B
./elements/rh-footer/rh-footer-links.js 1.1 kB
./elements/rh-footer/rh-footer-social-link.js 1.03 kB
./elements/rh-footer/rh-footer-universal.js 3.99 kB
./elements/rh-footer/rh-footer.js 4.67 kB
./elements/rh-health-index/rh-health-index.js 2.11 kB
./elements/rh-icon/rh-icon.js 2.52 kB
./elements/rh-icon/ssr.js 181 B
./elements/rh-jump-links/context.js 179 B
./elements/rh-jump-links/rh-jump-link.js 1.48 kB
./elements/rh-jump-links/rh-jump-links-list.js 1.17 kB
./elements/rh-jump-links/rh-jump-links.js 2.38 kB
./elements/rh-menu-dropdown/rh-menu-dropdown.js 4.12 kB
./elements/rh-menu/rh-menu-item-group.js 614 B
./elements/rh-menu/rh-menu-item.js 2.21 kB
./elements/rh-menu/rh-menu.js 1.6 kB
./elements/rh-navigation-link/rh-navigation-link.js 1.87 kB
./elements/rh-navigation-primary/context.js 176 B
./elements/rh-navigation-primary/rh-navigation-primary-item-menu.js 1.03 kB
./elements/rh-navigation-primary/rh-navigation-primary-item.js 3.46 kB
./elements/rh-navigation-primary/rh-navigation-primary-overlay.js 534 B
./elements/rh-navigation-primary/rh-navigation-primary.js 7.67 kB
./elements/rh-navigation-secondary/rh-navigation-secondary-dropdown.js 2.57 kB
./elements/rh-navigation-secondary/rh-navigation-secondary-menu-section.js 1.31 kB
./elements/rh-navigation-secondary/rh-navigation-secondary-menu.js 1.68 kB
./elements/rh-navigation-secondary/rh-navigation-secondary-overlay.js 562 B
./elements/rh-navigation-secondary/rh-navigation-secondary.js 5.23 kB
./elements/rh-navigation-secondary/test/fixtures.js 769 B
./elements/rh-navigation-vertical/rh-navigation-vertical-list.js 2.24 kB
./elements/rh-navigation-vertical/rh-navigation-vertical.js 1.54 kB
./elements/rh-progress-stepper/context.js 187 B
./elements/rh-progress-stepper/rh-progress-step.js 3.02 kB
./elements/rh-progress-stepper/rh-progress-stepper.js 4.78 kB
./elements/rh-scheme-toggle/rh-scheme-toggle.js 1.91 kB
./elements/rh-site-status/rh-site-status.js 2.44 kB
./elements/rh-skeleton/rh-skeleton.js 677 B
./elements/rh-skip-link/rh-skip-link.js 1.33 kB
./elements/rh-spinner/rh-spinner.js 1.31 kB
./elements/rh-stat/rh-stat.js 2.05 kB
./elements/rh-subnav/rh-subnav.js 2.98 kB
./elements/rh-surface/rh-surface.js 911 B
./elements/rh-surface/test/elements.js 763 B
./elements/rh-switch/rh-switch.js 2.83 kB
./elements/rh-table/rh-sort-button.js 1.39 kB
./elements/rh-table/rh-table.js 2.81 kB
./elements/rh-tabs/context.js 226 B
./elements/rh-tabs/rh-tab-panel.js 1 kB
./elements/rh-tabs/rh-tab.js 3.01 kB
./elements/rh-tabs/rh-tabs.js 3.65 kB
./elements/rh-tag/rh-tag.js 2.96 kB
./elements/rh-tile/rh-tile-group.js 1.78 kB
./elements/rh-tile/rh-tile.js 4.71 kB
./elements/rh-timestamp/rh-timestamp.js 991 B
./elements/rh-tooltip/rh-tooltip.js 3.18 kB
./elements/rh-video-embed/rh-video-embed.js 4.64 kB
./lib/color-palettes.js 851 B
./lib/context/headings/consumer.js 591 B
./lib/context/headings/provider.js 1.2 kB
./lib/elements/rh-context-demo/rh-context-demo.js 1.16 kB
./lib/elements/rh-context-picker/rh-context-picker.js 2.18 kB
./lib/environment.js 194 B
./lib/functions.js 175 B
./lib/I18nController.js 1.37 kB
./lib/ScreenSizeController.js 876 B
./lib/ssr-controller.js 201 B
./lib/themable.js 549 B
./react/lib/color-palettes.js 97 B
./react/lib/context/headings/consumer.js 103 B
./react/lib/context/headings/provider.js 105 B
./react/lib/elements/rh-context-demo/rh-context-demo.js 186 B
./react/lib/elements/rh-context-picker/rh-context-picker.js 189 B
./react/lib/functions.js 92 B
./react/lib/I18nController.js 97 B
./react/lib/ScreenSizeController.js 102 B
./react/lib/ssr-controller.js 97 B
./react/lib/themable.js 91 B
./react/rh-accordion/rh-accordion-header.js 199 B
./react/rh-accordion/rh-accordion-panel.js 185 B
./react/rh-accordion/rh-accordion.js 202 B
./react/rh-alert/rh-alert.js 184 B
./react/rh-announcement/rh-announcement.js 189 B
./react/rh-audio-player/rh-audio-player-about.js 191 B
./react/rh-audio-player/rh-audio-player-rate-stepper.js 199 B
./react/rh-audio-player/rh-audio-player-scrolling-text-overflow.js 214 B
./react/rh-audio-player/rh-audio-player-subscribe.js 196 B
./react/rh-audio-player/rh-audio-player.js 183 B
./react/rh-audio-player/rh-cue.js 195 B
./react/rh-audio-player/rh-transcript.js 187 B
./react/rh-avatar/rh-avatar.js 173 B
./react/rh-back-to-top/rh-back-to-top.js 183 B
./react/rh-badge/rh-badge.js 174 B
./react/rh-blockquote/rh-blockquote.js 179 B
./react/rh-breadcrumb/rh-breadcrumb.js 179 B
./react/rh-button-group/rh-button-group.js 184 B
./react/rh-button/rh-button.js 174 B
./react/rh-card/rh-card.js 172 B
./react/rh-chip/rh-chip-group.js 182 B
./react/rh-chip/rh-chip.js 187 B
./react/rh-code-block/rh-code-block.js 193 B
./react/rh-cta/rh-cta.js 170 B
./react/rh-dialog/rh-dialog.js 203 B
./react/rh-disclosure/rh-disclosure.js 192 B
./react/rh-footer/rh-footer-block.js 184 B
./react/rh-footer/rh-footer-copyright.js 187 B
./react/rh-footer/rh-footer-links.js 185 B
./react/rh-footer/rh-footer-social-link.js 193 B
./react/rh-footer/rh-footer-universal.js 188 B
./react/rh-footer/rh-footer.js 174 B
./react/rh-health-index/rh-health-index.js 184 B
./react/rh-icon/rh-icon.js 195 B
./react/rh-jump-links/rh-jump-link.js 183 B
./react/rh-jump-links/rh-jump-links-list.js 189 B
./react/rh-jump-links/rh-jump-links.js 195 B
./react/rh-menu-dropdown/rh-menu-dropdown.js 185 B
./react/rh-menu/rh-menu-item-group.js 190 B
./react/rh-menu/rh-menu-item.js 181 B
./react/rh-menu/rh-menu.js 173 B
./react/rh-navigation-link/rh-navigation-link.js 186 B
./react/rh-navigation-primary/rh-navigation-primary-item-menu.js 205 B
./react/rh-navigation-primary/rh-navigation-primary-item.js 198 B
./react/rh-navigation-primary/rh-navigation-primary-overlay.js 199 B
./react/rh-navigation-primary/rh-navigation-primary.js 189 B
./react/rh-navigation-secondary/rh-navigation-secondary-dropdown.js 217 B
./react/rh-navigation-secondary/rh-navigation-secondary-menu-section.js 205 B
./react/rh-navigation-secondary/rh-navigation-secondary-menu.js 199 B
./react/rh-navigation-secondary/rh-navigation-secondary-overlay.js 201 B
./react/rh-navigation-secondary/rh-navigation-secondary.js 213 B
./react/rh-navigation-vertical/rh-navigation-vertical-list.js 198 B
./react/rh-navigation-vertical/rh-navigation-vertical.js 189 B
./react/rh-pagination/rh-pagination.js 178 B
./react/rh-progress-stepper/rh-progress-step.js 196 B
./react/rh-progress-stepper/rh-progress-stepper.js 186 B
./react/rh-scheme-toggle/rh-scheme-toggle.js 183 B
./react/rh-site-status/rh-site-status.js 181 B
./react/rh-skeleton/rh-skeleton.js 176 B
./react/rh-skip-link/rh-skip-link.js 181 B
./react/rh-spinner/rh-spinner.js 175 B
./react/rh-stat/rh-stat.js 171 B
./react/rh-subnav/rh-subnav.js 175 B
./react/rh-surface/rh-surface.js 175 B
./react/rh-switch/rh-switch.js 174 B
./react/rh-table/rh-sort-button.js 200 B
./react/rh-table/rh-table.js 174 B
./react/rh-tabs/rh-tab-panel.js 181 B
./react/rh-tabs/rh-tab.js 187 B
./react/rh-tabs/rh-tabs.js 174 B
./react/rh-tag/rh-tag.js 182 B
./react/rh-tile/rh-tile-group.js 183 B
./react/rh-tile/rh-tile.js 181 B
./react/rh-timestamp/rh-timestamp.js 176 B
./react/rh-tooltip/rh-tooltip.js 175 B
./react/rh-video-embed/rh-video-embed.js 227 B
./uxdot/ssr-failure-recoverable.js 658 B
./uxdot/uxdot-best-practice.js 812 B
./uxdot/uxdot-copy-button.js 1.24 kB
./uxdot/uxdot-copy-permalink.js 1.14 kB
./uxdot/uxdot-demo.js 2.76 kB
./uxdot/uxdot-example.js 1.14 kB
./uxdot/uxdot-feedback.js 983 B
./uxdot/uxdot-header.js 886 B
./uxdot/uxdot-knob-attribute.js 3.73 kB
./uxdot/uxdot-masthead.js 1.45 kB
./uxdot/uxdot-pattern-ssr-controller-client.js 1.24 kB
./uxdot/uxdot-pattern-ssr-controller-server.js 1.71 kB
./uxdot/uxdot-pattern-ssr-controller.js 213 B
./uxdot/uxdot-pattern.js 2.39 kB
./uxdot/uxdot-repo-status-checklist.js 1.39 kB
./uxdot/uxdot-repo-status-list.js 1.24 kB
./uxdot/uxdot-repo.js 867 B
./uxdot/uxdot-sidenav.js 2.04 kB
./uxdot/uxdot-spacer-tokens-table.js 2.45 kB
./uxdot/uxdot-toc.js 1.8 kB

compressed-size-action

@github-actions
Copy link
Contributor

github-actions bot commented Feb 26, 2026

Documentation Health

Module Score
rh-pagination/rh-pagination.js 55/100 ⚠️ 55%
Overall 55/100 ⚠️ 55%
rh-pagination (RhPagination) — 55/100 ⚠️
Category Score
Element description 11/25 ⚠️
Attribute documentation 20/20
Slot documentation 0/15
CSS documentation 4/15
Event documentation 15/15
Demos 5/10 ⚠️

Recommendations:

  1. rh-pagination: use RFC 2119 keywords (MUST, SHOULD, AVOID) to clarify requirements (Element description, +5 pts)
  2. rh-pagination: add descriptions to all slots (Slot documentation, +5 pts)
  3. rh-pagination: describe expected content types for slots (e.g., 'inline text', 'block elements') (Slot documentation, +5 pts)
  4. rh-pagination: mention accessibility considerations for slot content (Slot documentation, +5 pts)
  5. rh-pagination: add descriptions to all CSS parts (CSS documentation, +5 pts)

@zeroedin zeroedin changed the title Fix/pagination/onsubmit fix(pagination): replace onchange with onsubmit Feb 26, 2026
Copy link
Member

@bennypowers bennypowers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lucid "go" text manifested

@bennypowers
Copy link
Member

Does this need l10n?

@zeroedin
Copy link
Collaborator Author

zeroedin commented Feb 26, 2026

Does this need l10n?

As far as I understood its a keyword only and isn't exposed to the client.

https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/enterKeyHint

I asked gemini just for the check:

In the context of the enterKeyHint property, 'go' is a keyword (an enumerated value) defined by the HTML specification. Like other HTML attributes or CSS properties (e.g., type="submit" or display: block), these keywords must be written exactly as specified in English for the browser to recognize them.

How Localization (l10n) Handled:
The browser and the operating system (iOS, Android, etc.) handle the translation for you automatically:

The Keyword: You write element.enterKeyHint = 'go';.

The Browser's Job: The browser sees this keyword and tells the mobile operating system to display the "Go" button.

The OS's Job: If the user’s phone is set to French, the system will automatically display "Aller"; if it's set to Spanish, it will show "Ir".

@bennypowers
Copy link
Member

excellent

@adamjohnson adamjohnson moved this to Review 🔍 in Red Hat Design System Feb 26, 2026
Copy link
Collaborator

@adamjohnson adamjohnson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested on Android 16 with Chrome and Opera Mobile. Works as advertised. Nice job.

@zeroedin zeroedin moved this from Review 🔍 to In Progress 🟢 in Red Hat Design System Feb 26, 2026
Copy link
Collaborator

@hellogreg hellogreg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Working with iOS VoiceOver and Android Talkback 🙌🏻

@zeroedin zeroedin marked this pull request as ready for review February 27, 2026 15:14
@zeroedin zeroedin moved this from In Progress 🟢 to Review 🔍 in Red Hat Design System Feb 27, 2026
@zeroedin zeroedin marked this pull request as draft February 27, 2026 16:24
@zeroedin zeroedin marked this pull request as draft February 27, 2026 16:24
@adamjohnson adamjohnson self-requested a review February 27, 2026 16:26
@zeroedin
Copy link
Collaborator Author

zeroedin commented Feb 27, 2026

noticed URLs aren't actively updating. I didn't notice that the form was being rendered twice to get around focus order when resized to the < 768px breakpoint view.

I implemented a resize observer that physically moves the input field in the dom to maintain the correct focus order and not have to render the form twice.

on second thought just revert the simplified onSubmit change and go back to event.target selector on the onSubmit targeting the correct form input based on which it is called from given the viewport size and user interaction.

@zeroedin zeroedin marked this pull request as ready for review February 27, 2026 17:50
@zeroedin
Copy link
Collaborator Author

In a full reversal again I went back to the resize observer. In order to properly link the <label> and <input> it was important to only render a single form element for the ids, ran into accessibility issues otherwise. The resize observer enables this to function correctly in the AT.

Copy link
Collaborator

@adamjohnson adamjohnson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the base demo currently (demo/index.html):

Screenshot showing the pagination input and 'of 5' text wrapping to a new line incorrectly
  • Where we have "Page {input} of 5", the "of 5" bit should stay on the same line with the input but it currently wraps to the next line.
  • The height of the input does not match the height of the rest of the pagination buttons.
  • If I enter "3" into the input and hit enter, pagination correctly adds aria-current="page" to the third item in the ordered list, but the input displays "Page {1} of 5" instead of "Page {3} of 5"
  • At 330px, the content inside #numeric doesn't have any margin/gap to separate it from the <<|<|>|>> buttons
    • Note: these breakpoint numbers will likely change when fixing the wrapping issue mentioned above.
  • At 344px+, #compact-numeric is also missing its margin/gap on the right side

And, as you know, there are a few failing tests to resolve. 😇

@zeroedin
Copy link
Collaborator Author

zeroedin commented Mar 5, 2026

Closing this PR, will open a new one with some of the changes here, but in the direction of modifying the design by not doing the shift of the form. Ran into different issues with each attempt and want to start with a fresh take on the problem.

@zeroedin zeroedin closed this Mar 5, 2026
@github-project-automation github-project-automation bot moved this from Review 🔍 to Done ☑️ in Red Hat Design System Mar 5, 2026
@bennypowers
Copy link
Member

Thanks for your intensive work on this one, @zeroedin

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

Labels

None yet

Projects

Status: Done ☑️

Development

Successfully merging this pull request may close these issues.

4 participants