fix(react-native): migrate Button off @gluestack-ui/button - #1501
Conversation
…ggleButton off @gluestack-ui/button Replaces createButton's Pressable factory (pressed-state tracking via @react-native-aria/interactions, unused hover/focus aggregation, and a role="button" default) with plain Pressable + useState press tracking and an explicit accessibilityRole="button" default. Adds a baseline play-function test to Button's previously-untested Playground story. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: cf43234 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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 |
There was a problem hiding this comment.
Pull request overview
Migrates the React Native Button family (Button, IconButton, UnstyledIconButton, ToggleButton) off @gluestack-ui/button by removing the shared createButton factory usage and implementing the needed behavior directly with React Native Pressable, while also updating Storybook interaction coverage and removing the dependency from the package.
Changes:
- Replace
createButtonusage with directPressablerendering + internal pressed-state tracking viaonPressIn/onPressOutanduseState. - Reimplement
ButtonGroup’sreversedbehavior by reversing the rendered children array. - Remove
@gluestack-ui/buttonfrom dependencies/lockfile and add/update Storybookplayinteraction tests and a changeset.
Reviewed changes
Copilot reviewed 14 out of 15 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
pnpm-lock.yaml |
Removes @gluestack-ui/button (and related snapshot entries) from the lockfile. |
packages/react-native/package.json |
Drops @gluestack-ui/button dependency from @utilitywarehouse/hearth-react-native. |
packages/react-native/src/components/Button/Button.tsx |
Stops using createButton; renders ButtonRoot directly and re-exports subcomponents directly. |
packages/react-native/src/components/Button/ButtonRoot.tsx |
Adds internal pressed tracking and sets Pressable defaults (accessibilityRole, disabled). |
packages/react-native/src/components/Button/ButtonGroup.tsx |
Reimplements reversed by reversing children ordering before rendering ButtonGroupRoot. |
packages/react-native/src/components/Button/Button.stories.tsx |
Adds play test for Playground and introduces a States story with interaction assertions. |
packages/react-native/src/components/IconButton/IconButton.tsx |
Removes createButton wrapper; uses IconButtonRootComponent directly. |
packages/react-native/src/components/IconButton/IconButtonRoot.tsx |
Adds internal pressed tracking and ensures Pressable has accessibilityRole and disabled. |
packages/react-native/src/components/IconButton/IconButton.stories.tsx |
Updates interaction-test comments to reflect direct Pressable usage. |
packages/react-native/src/components/UnstyledIconButton/UnstyledIconButton.tsx |
Removes createButton wrapper; uses root/icon/spinner components directly. |
packages/react-native/src/components/UnstyledIconButton/UnstyledIconButtonRoot.tsx |
Adds internal pressed tracking and passes disabled to Pressable. |
packages/react-native/src/components/UnstyledIconButton/UnstyledIconButton.stories.tsx |
Updates interaction-test comments to reflect direct Pressable usage. |
packages/react-native/src/components/ToggleButton/ToggleButton.tsx |
Removes createButton wrapper; renders ToggleButtonRoot directly. |
packages/react-native/src/components/ToggleButton/ToggleButtonRoot.tsx |
Adds internal pressed tracking and explicit default accessibilityRole="button". |
.changeset/button-remove-gluestack.md |
Adds a patch changeset documenting the migration off @gluestack-ui/button. |
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…puted disabled/selected Copilot review on #1501: ToggleButtonRoot and UnstyledIconButtonRoot spread props.accessibilityState after the computed disabled/selected value, letting a consumer-supplied accessibilityState silently override the real state exposed to assistive tech. Swap the spread order so the computed value always wins. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Summary
@gluestack-ui/buttonfromButton,IconButton,UnstyledIconButton, andToggleButton(all previously wired through the sharedcreateButtonfactory).createButtonprovided pressed-state tracking (via@react-native-aria/interactions), unused hover/focus/focus-visible aggregation, and a web-orientedrole="button"default. Replaced with a plainPressable+useStatepress tracker (composed with any consumeronPressIn/onPressOut) and an explicitaccessibilityRole="button"default.ButtonGroup'sreversedprop (child reordering) is reimplemented as a plain array reversal, since gluestack'sGroupfactory was the only thing consuming it.play-function test toButton.stories.tsx > Playground(previously untested) and aStatesstory covering default/disabled/loading, per this epic's baseline-then-migrate convention.IconButton/UnstyledIconButton/ToggleButton's existing baseline tests are unchanged and re-verified against the migrated implementation.Test plan
pnpm typecheck— cleanpnpm lint(scoped to Button-family) — cleanpnpm checks(repo root) — 10/10 tasks passonPressfiring, disabled/aria-disabled) pass@gluestack-ui/buttonremoved frompackage.json, no remaining source references🧹 [HOUSEKEEPING], patch)Note: while verifying, found a pre-existing, unrelated flake where some interaction tests intermittently fail on a stray
ReanimatedErrorfrom the globalBottomSheetModalProviderdecorator in.storybook/preview.tsx(every real assertion still passes). Filed as UWDS-4922 rather than fixed here, since it's unrelated to this migration.🤖 Generated with Claude Code