Skip to content

feat(a11y): add global haptics preference and accessibility guardrails#139

Merged
RawJat merged 2 commits intoDinanathDash:mainfrom
RawJat:138/feat(a11y)-Implement-global-haptics-context-and-user-opt-out-toggle
Apr 1, 2026
Merged

feat(a11y): add global haptics preference and accessibility guardrails#139
RawJat merged 2 commits intoDinanathDash:mainfrom
RawJat:138/feat(a11y)-Implement-global-haptics-context-and-user-opt-out-toggle

Conversation

@RawJat
Copy link
Copy Markdown
Collaborator

@RawJat RawJat commented Apr 1, 2026

Summary

This PR introduces a global haptics preference so users can opt out of tactile feedback across the app. It wires the existing dual-path haptics utility into a shared React context, persists the preference in localStorage, and adds a user-facing toggle in settings.

The implementation is intentionally scoped around accessibility: when haptics are disabled, no feedback should fire on either Android (navigator.vibrate) or the iOS Safari fallback path. This also establishes a stricter usage policy so haptics are reserved for meaningful, high-signal interactions only.

What Changed

  • Added a global HapticProvider / HapticsContext
  • Persisted the haptics preference to localStorage
  • Defaulted haptics to enabled for first-time users
  • Updated haptics state handling so the global utility respects the user preference
  • Added an "Enable Haptic Feedback" toggle to settings/preferences
  • Applied haptics only to approved interaction categories:
    • error for validation failures, system errors, failed submissions, and unauthorized actions
    • success for major success states
    • cancel / heavy for destructive or high-consequence actions
  • Avoided haptics for routine navigation, standard button clicks, input interactions, hover states, and repetitive events

Accessibility Notes

This change is intended to reduce sensory fatigue and prevent overuse of feedback. Haptics are now treated as an accessibility-sensitive enhancement rather than a default interaction pattern to be used broadly.

Acceptance Criteria Covered

  • User can disable haptics from settings
  • Preference persists across reloads
  • No Android or iOS haptics fire when disabled
  • iOS fallback DOM interaction does not trigger while disabled
  • Usage follows the defined haptic guidelines

Testing

  • Verified preference persists after reload
  • Verified enabled state still allows expected haptic feedback
  • Verified disabled state suppresses all feedback paths
  • Verified lint passes for the provider changes

Co-authored-by: Dinanath Dash 108653031+DinanathDash@users.noreply.github.com

RawJat and others added 2 commits April 1, 2026 22:59
Co-authored-by: Dinanath Dash <108653031+DinanathDash@users.noreply.github.com>
Co-authored-by: Dinanath Dash <108653031+DinanathDash@users.noreply.github.com>
@RawJat RawJat merged commit 5721dbf into DinanathDash:main Apr 1, 2026
1 check passed
github-actions bot pushed a commit that referenced this pull request Apr 2, 2026
## [1.28.0](v1.27.0...v1.28.0) (2026-04-02)

### Features

* **a11y:** add global haptics preference and accessibility guardrails ([#139](#139)) ([5721dbf](5721dbf)), closes [#138](#138)
* Implement global haptics context and dual-path iOS/Android utility ([f0c4c65](f0c4c65))
* unify keyboard UX, MDX changelog rendering, and navigation reliability ([9858364](9858364))
github-actions bot pushed a commit that referenced this pull request Apr 2, 2026
## [1.28.0](v1.27.0...v1.28.0) (2026-04-02)

### Features

* **a11y:** add global haptics preference and accessibility guardrails ([#139](#139)) ([5721dbf](5721dbf)), closes [#138](#138)
* **app-ui:** improve header navigation and interaction behavior ([0fc9059](0fc9059))
* **changelog:** migrate changelog pipeline from markdown to MDX ([77bd158](77bd158))
* Implement global haptics context and dual-path iOS/Android utility ([f0c4c65](f0c4c65))
* **secrets-ui:** rename variable dialog and improve masked value UX ([9be9e58](9be9e58))

### Bug Fixes

* **runtime:** guard browser view transitions and JSON-LD rendering ([576d4d4](576d4d4))
RawJat added a commit to RawJat/Envault that referenced this pull request Apr 7, 2026
DinanathDash#139)

## Summary

This PR introduces a global haptics preference so users can opt out of
tactile feedback across the app. It wires the existing dual-path haptics
utility into a shared React context, persists the preference in
`localStorage`, and adds a user-facing toggle in settings.

- closes DinanathDash#138 

The implementation is intentionally scoped around accessibility: when
haptics are disabled, no feedback should fire on either Android
(`navigator.vibrate`) or the iOS Safari fallback path. This also
establishes a stricter usage policy so haptics are reserved for
meaningful, high-signal interactions only.

## What Changed

- Added a global `HapticProvider` / `HapticsContext`
- Persisted the haptics preference to `localStorage`
- Defaulted haptics to enabled for first-time users
- Updated haptics state handling so the global utility respects the user
preference
- Added an "Enable Haptic Feedback" toggle to settings/preferences
- Applied haptics only to approved interaction categories:
- `error` for validation failures, system errors, failed submissions,
and unauthorized actions
  - `success` for major success states
  - `cancel` / `heavy` for destructive or high-consequence actions
- Avoided haptics for routine navigation, standard button clicks, input
interactions, hover states, and repetitive events

## Accessibility Notes

This change is intended to reduce sensory fatigue and prevent overuse of
feedback. Haptics are now treated as an accessibility-sensitive
enhancement rather than a default interaction pattern to be used
broadly.

## Acceptance Criteria Covered

- User can disable haptics from settings
- Preference persists across reloads
- No Android or iOS haptics fire when disabled
- iOS fallback DOM interaction does not trigger while disabled
- Usage follows the defined haptic guidelines

## Testing

- Verified preference persists after reload
- Verified enabled state still allows expected haptic feedback
- Verified disabled state suppresses all feedback paths
- Verified lint passes for the provider changes

---

Co-authored-by: Dinanath Dash
<108653031+DinanathDash@users.noreply.github.com>
RawJat pushed a commit to RawJat/Envault that referenced this pull request Apr 7, 2026
## [1.28.0](DinanathDash/Envault@v1.27.0...v1.28.0) (2026-04-02)

### Features

* **a11y:** add global haptics preference and accessibility guardrails ([DinanathDash#139](DinanathDash#139)) ([5721dbf](DinanathDash@5721dbf)), closes [DinanathDash#138](DinanathDash#138)
* **app-ui:** improve header navigation and interaction behavior ([0fc9059](DinanathDash@0fc9059))
* **changelog:** migrate changelog pipeline from markdown to MDX ([77bd158](DinanathDash@77bd158))
* Implement global haptics context and dual-path iOS/Android utility ([f0c4c65](DinanathDash@f0c4c65))
* **secrets-ui:** rename variable dialog and improve masked value UX ([9be9e58](DinanathDash@9be9e58))

### Bug Fixes

* **runtime:** guard browser view transitions and JSON-LD rendering ([576d4d4](DinanathDash@576d4d4))
@RawJat RawJat deleted the 138/feat(a11y)-Implement-global-haptics-context-and-user-opt-out-toggle branch April 7, 2026 18:38
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.

feat(a11y): Implement global haptics context and user opt-out toggle

1 participant