Skip to content

🎨 Palette: Add tactile feedback to FlightScreen#42

Open
TargetMisser wants to merge 2 commits intomainfrom
palette-haptic-ux-562722060276858861
Open

🎨 Palette: Add tactile feedback to FlightScreen#42
TargetMisser wants to merge 2 commits intomainfrom
palette-haptic-ux-562722060276858861

Conversation

@TargetMisser
Copy link
Copy Markdown
Owner

🎨 Palette: Micro-UX Haptic Feedback

💡 What: Added physical tactile feedback to the FlightScreen using expo-haptics.

🎯 Why: To make the interface feel more responsive and physical. Users get immediate, delightful feedback when performing important actions like switching tabs, pinning/unpinning flights, or swiping list items.

Accessibility: Provides non-visual confirmation of state changes, benefiting users who rely on multi-sensory feedback.

Changes:

  • Tab switches: Light physical "click" (Impact Light).
  • Pinning: Positive confirmation (Notification Success).
  • Swiping: Physical "snap" feel when crossing the 80px threshold (Selection).
  • Optimized swipe logic to ensure haptics trigger exactly once per gesture.

PR created automatically by Jules for task 562722060276858861 started by @TargetMisser

- Added `expo-haptics` to `FlightScreen` for micro-UX delight.
- Light haptic impact on Arrival/Departure and Today/Tomorrow tab switches.
- Success notification feedback on flight pinning.
- Selection feedback on flight unpinning.
- Physical 'tick' (haptic selection) when swiping flight cards past the threshold.
- Implemented `hasTriggeredHaptic` ref to prevent repeated buzzing during swipe.
- Created UX journal in `.Jules/palette.md`.

Co-authored-by: TargetMisser <52361977+TargetMisser@users.noreply.github.com>
@google-labs-jules
Copy link
Copy Markdown

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 7, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
flight-work-app Ready Ready Preview, Comment, Open in v0 Apr 7, 2026 0:14am

- Fixed CI failure caused by out-of-sync `package-lock.json`.
- Updated lockfile to satisfy dependencies: `@react-native-picker/picker@2.11.4`, `pdfjs-dist@5.6.205`, `react-native-webview@13.16.1`.
- Added missing `expo-secure-store@15.0.8` to lockfile.

Co-authored-by: TargetMisser <52361977+TargetMisser@users.noreply.github.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds micro-UX haptic feedback to FlightScreen interactions (tab/day segmented controls, pin/unpin actions, and swipe-to-toggle gestures) using expo-haptics, and records the related UX guidance in the Jules palette notes.

Changes:

  • Added expo-haptics triggers for tab/day switches, pin/unpin, and swipe threshold crossing.
  • Introduced swipe gesture gating state to avoid repeated haptic triggering during continuous pan updates.
  • Added .Jules/palette.md notes documenting the “trigger once” haptics pattern for gestures.

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 5 comments.

File Description
src/screens/FlightScreen.tsx Adds haptics to key FlightScreen actions (segmented controls, pin/unpin, swipe threshold).
.Jules/palette.md Documents learned patterns for adding haptics without “buzzing” during continuous gestures.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +85 to +86
} else if (g.dx >= -SWIPE_THRESHOLD && hasTriggeredHaptic.current) {
hasTriggeredHaptic.current = false;
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

hasTriggeredHaptic is reset when the swipe moves back above the threshold (dx >= -SWIPE_THRESHOLD), so a single swipe gesture can trigger Haptics.selectionAsync() multiple times if the user jitters across the threshold. If the intent is “exactly once per gesture”, keep the ref true until onPanResponderRelease/Terminate and remove the mid-gesture reset (or update the gating logic accordingly).

Suggested change
} else if (g.dx >= -SWIPE_THRESHOLD && hasTriggeredHaptic.current) {
hasTriggeredHaptic.current = false;

Copilot uses AI. Check for mistakes.
const tab = activeTab;
await AsyncStorage.setItem(PINNED_FLIGHT_KEY, JSON.stringify({ ...item, _pinTab: tab, _pinnedAt: Date.now() }));
setPinnedFlightId(id);
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

Haptics.notificationAsync(...) returns a Promise, but it’s not awaited or handled. If it rejects (e.g., unsupported platform), it can create unhandled promise rejections. Consider calling it with void ...catch(() => {}) or awaiting it inside the surrounding try (and/or gating with Haptics.isAvailableAsync() / Platform.OS !== 'web').

Suggested change
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
void Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success).catch(() => {});

Copilot uses AI. Check for mistakes.
await AsyncStorage.removeItem(PINNED_FLIGHT_KEY);
try { await cancelPinnedNotifications(); } catch (e) { if (__DEV__) console.warn('[cancelPinNotif]', e); }
setPinnedFlightId(null);
Haptics.selectionAsync();
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

Haptics.selectionAsync() is fire-and-forget here; if it rejects on unsupported platforms it can surface as an unhandled promise rejection. Consider using void Haptics.selectionAsync().catch(() => {}) (and/or gating with Haptics.isAvailableAsync() / Platform.OS !== 'web').

Suggested change
Haptics.selectionAsync();
void Haptics.selectionAsync().catch(() => {});

Copilot uses AI. Check for mistakes.
Comment on lines +793 to +796
onPress={() => {
setActiveTab(tab);
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
}}
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

Haptics.impactAsync(...) returns a Promise but isn’t awaited/handled; on unsupported platforms this can generate unhandled promise rejections. Consider wrapping haptics in a small helper that gates by platform/availability and uses void ...catch(() => {}).

Copilot uses AI. Check for mistakes.
Comment on lines +808 to +811
onPress={() => {
setActiveDay(d);
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
}}
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

Same as above: Haptics.impactAsync(...) is not awaited/handled, which can lead to unhandled promise rejections on platforms where haptics are unavailable (notably web). Consider gating/handling via a shared helper.

Copilot uses AI. Check for mistakes.
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.

2 participants