Skip to content

Commit

Permalink
add global haptics
Browse files Browse the repository at this point in the history
  • Loading branch information
EvanBacon committed Sep 10, 2024
1 parent d472754 commit 9b30ea7
Show file tree
Hide file tree
Showing 12 changed files with 142 additions and 2 deletions.
8 changes: 7 additions & 1 deletion app/(index,orders,products,analytics)/_layout.native.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,13 @@ export default function RootLayout({ segment }: { segment: string }) {
options={{
title: "Settings",
presentation: "modal",
headerLargeTitle: true,
headerTransparent: true,
headerBlurEffect: "prominent",
headerShadowVisible: true,
headerStyle: {
// Hack to ensure the collapsed small header shows the shadow / border.
backgroundColor: "rgba(255,255,255,0.01)",
},
}}
/>
</Stack>
Expand Down
12 changes: 12 additions & 0 deletions app/(index,orders,products,analytics)/analytics.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
import ShadAnalytics from "@/components/shad/analytics";
import { router } from "expo-router";
import { useScrollRef } from "@/lib/tab-to-top";
import * as Haptics from "expo-haptics";

export default function AnalyticsRoute() {
const ref = useScrollRef();
return (
<ShadAnalytics
ref={ref}
navigate={router.navigate}
onButtonClick={async (size: number) => {
if (process.env.EXPO_OS !== "web") {
Haptics.impactAsync(
[
Haptics.ImpactFeedbackStyle.Light,
Haptics.ImpactFeedbackStyle.Medium,
Haptics.ImpactFeedbackStyle.Heavy,
][size]
);
}
}}
dom={{
contentInsetAdjustmentBehavior: "automatic",
automaticallyAdjustsScrollIndicatorInsets: true,
Expand Down
20 changes: 19 additions & 1 deletion app/(index,orders,products,analytics)/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,27 @@ import * as Notifications from "expo-notifications";
import { router } from "expo-router";
import React from "react";
import { useScrollRef } from "@/lib/tab-to-top";
import * as Haptics from "expo-haptics";

export default function IndexRoute() {
return <Dashboard notify={notify} ref={useScrollRef()} {...extraProps} />;
return (
<Dashboard
notify={notify}
onButtonClick={async (size: number) => {
if (process.env.EXPO_OS !== "web") {
Haptics.impactAsync(
[
Haptics.ImpactFeedbackStyle.Light,
Haptics.ImpactFeedbackStyle.Medium,
Haptics.ImpactFeedbackStyle.Heavy,
][size]
);
}
}}
ref={useScrollRef()}
{...extraProps}
/>
);
}

// native notify function
Expand Down
12 changes: 12 additions & 0 deletions app/(index,orders,products,analytics)/orders.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Orders from "@/components/shad/orders";
import { router } from "expo-router";
import { useScrollRef } from "@/lib/tab-to-top";
import * as Haptics from "expo-haptics";

export default function OrdersRoute() {
const ref = useScrollRef();
Expand All @@ -12,6 +13,17 @@ export default function OrdersRoute() {
contentInsetAdjustmentBehavior: "automatic",
automaticallyAdjustsScrollIndicatorInsets: true,
}}
onButtonClick={async (size: number) => {
if (process.env.EXPO_OS !== "web") {
Haptics.impactAsync(
[
Haptics.ImpactFeedbackStyle.Light,
Haptics.ImpactFeedbackStyle.Medium,
Haptics.ImpactFeedbackStyle.Heavy,
][size]
);
}
}}
/>
);
}
12 changes: 12 additions & 0 deletions app/(index,orders,products,analytics)/products.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Products from "@/components/shad/products";
import { router } from "expo-router";
import { useScrollRef } from "@/lib/tab-to-top";
import * as Haptics from "expo-haptics";

export default function ProductsRoute() {
const ref = useScrollRef();
Expand All @@ -9,6 +10,17 @@ export default function ProductsRoute() {
<Products
ref={ref}
navigate={router.navigate}
onButtonClick={async (size: number) => {
if (process.env.EXPO_OS !== "web") {
Haptics.impactAsync(
[
Haptics.ImpactFeedbackStyle.Light,
Haptics.ImpactFeedbackStyle.Medium,
Haptics.ImpactFeedbackStyle.Heavy,
][size]
);
}
}}
dom={{
contentInsetAdjustmentBehavior: "automatic",
automaticallyAdjustsScrollIndicatorInsets: true,
Expand Down
12 changes: 12 additions & 0 deletions app/(index,orders,products,analytics)/settings.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import SettingsRoute from "@/components/shad/settings";
import * as Haptics from "expo-haptics";
import { router } from "expo-router";
import { StatusBar } from "react-native";

Expand All @@ -11,6 +12,17 @@ export default function Settings() {
contentInsetAdjustmentBehavior: "automatic",
automaticallyAdjustsScrollIndicatorInsets: true,
}}
onButtonClick={async (size: number) => {
if (process.env.EXPO_OS !== "web") {
Haptics.impactAsync(
[
Haptics.ImpactFeedbackStyle.Light,
Haptics.ImpactFeedbackStyle.Medium,
Haptics.ImpactFeedbackStyle.Heavy,
][size]
);
}
}}
/>
<StatusBar barStyle="light-content" />
</>
Expand Down
43 changes: 43 additions & 0 deletions components/global-button-haptics.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { IS_DOM } from "expo/dom";
import { useEffect } from "react";

// Function to determine the size scale based on button dimensions
function getSizeScale(button: HTMLButtonElement) {
const width = button.offsetWidth;
const height = button.offsetHeight;
const area = width * height;

// Assign a scale based on button area (you can tweak these thresholds)
if (area < 4000) {
return 0; // Small
} else if (area < 7000) {
return 1; // Medium
} else {
return 2; // Large
}
}

export function useGlobalButtonHaptics(haptics?: (size: number) => void) {
if (!IS_DOM) {
return null;
}

useEffect(() => {
if (!haptics) return;

const listener = (event: MouseEvent) => {
// Check if the clicked element is a button
if (event.target?.tagName === "BUTTON") {
haptics(getSizeScale(event.target as HTMLButtonElement));
}
};
// Global event listener for clicks
document.addEventListener("click", listener);

return () => {
document.removeEventListener("click", listener);
};
}, [haptics]);

return null;
}
5 changes: 5 additions & 0 deletions components/shad/analytics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,19 @@ import {
import { Separator } from "@/components/ui/separator";

import ShadLayout from "./shad-layout";
import { useGlobalButtonHaptics } from "../global-button-haptics";

export default function AnalyticsRoute({
navigate,
onButtonClick,
}: {
navigate: typeof import("expo-router").router["navigate"];
dom?: import("expo/dom").DOMProps;
ref?: import("react").RefObject<import("react-native-webview").WebView>;
onButtonClick: (size: number) => Promise<void>;
}) {
useGlobalButtonHaptics(onButtonClick);

return (
<ShadLayout navigate={navigate}>
<Charts />
Expand Down
6 changes: 6 additions & 0 deletions components/shad/dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,19 @@ import {
MoreVertical,
Truck,
} from "lucide-react";
import { useEffect } from "react";
import { useGlobalButtonHaptics } from "../global-button-haptics";

export default function DashboardRoute({
navigate,
notify,
onButtonClick,
}: {
notify: () => void;
onButtonClick: (size: number) => Promise<void>;
} & Props) {
useGlobalButtonHaptics(onButtonClick);

return (
<ShadLayout navigate={navigate}>
<main className="grid flex-1 items-start gap-4 p-4 sm:px-6 sm:py-0 md:gap-8 lg:grid-cols-3 xl:grid-cols-3">
Expand Down
5 changes: 5 additions & 0 deletions components/shad/orders.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,21 @@ import { File, ListFilter, MoreHorizontal, PlusCircle } from "lucide-react";

import ShadLayout from "./shad-layout";
import { IS_DOM } from "expo/dom";
import { useGlobalButtonHaptics } from "../global-button-haptics";

const baseUrl = IS_DOM ? process.env.EXPO_DOM_BASE_URL : "";

export default function OrdersRoute({
navigate,
onButtonClick,
}: {
navigate: typeof import("expo-router").router["navigate"];
dom?: import("expo/dom").DOMProps;
ref?: import("react").RefObject<import("react-native-webview").WebView>;
onButtonClick: (size: number) => Promise<void>;
}) {
useGlobalButtonHaptics(onButtonClick);

return (
<ShadLayout navigate={navigate}>
<main className="grid flex-1 items-start gap-4 p-4 sm:px-6 sm:py-0 md:gap-8">
Expand Down
5 changes: 5 additions & 0 deletions components/shad/products.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,21 @@ import { Textarea } from "@/components/ui/textarea";
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
import ShadLayout from "./shad-layout";
import { IS_DOM } from "expo/dom";
import { useGlobalButtonHaptics } from "../global-button-haptics";

const baseUrl = IS_DOM ? process.env.EXPO_DOM_BASE_URL : "";

export default function ProductsRoute({
navigate,
onButtonClick,
}: {
navigate: typeof import("expo-router").router["navigate"];
dom?: import("expo/dom").DOMProps;
ref?: import("react").RefObject<import("react-native-webview").WebView>;
onButtonClick: (size: number) => Promise<void>;
}) {
useGlobalButtonHaptics(onButtonClick);

return (
<ShadLayout navigate={navigate}>
<main className="grid flex-1 items-start gap-4 p-4 sm:px-6 sm:py-0 md:gap-8">
Expand Down
4 changes: 4 additions & 0 deletions components/shad/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@

import ShadLayout from "./shad-layout";
import StoryWrapper from "../mdx/mdx-route";
import { useGlobalButtonHaptics } from "../global-button-haptics";
// import { useEffect } from "react";

export default function SettingsRoute({
navigate,
onButtonClick,
}: {
navigate: typeof import("expo-router").router["navigate"];
dom?: import("expo/dom").DOMProps;
onButtonClick: (size: number) => Promise<void>;
}) {
useGlobalButtonHaptics(onButtonClick);
// useEffect(() => {
// import("eruda").then((eruda) => eruda.default.init());
// }, []);
Expand Down

0 comments on commit 9b30ea7

Please sign in to comment.