Skip to content

Commit

Permalink
feat!(tooltip): Add tooltip arrow (#148)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: The tooltip arrow now renders by default.
FloatingUI-related props were refactored.
The `middleware` prop was removed, now you can either pass each supported middleware options or a boolean to enable/disable the feature controlled by each middleware.
  • Loading branch information
JoseLion committed Jul 13, 2024
1 parent 4986057 commit 0d9b40d
Show file tree
Hide file tree
Showing 10 changed files with 272 additions and 94 deletions.
20 changes: 3 additions & 17 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ import {
SpotlightTourProvider,
TourBox,
TourStep,
flip,
offset,
shift,
StopParams,
} from "react-native-spotlight-tour";

Expand Down Expand Up @@ -36,10 +33,6 @@ export function App(): ReactElement {
}, []);

const tourSteps = useMemo((): TourStep[] => [{
floatingProps: {
middleware: [offset(0), shift(), flip()],
placement: "right",
},
render: ({ next }) => (
<SpotDescriptionView>
<DescriptionText>
Expand All @@ -54,8 +47,8 @@ export function App(): ReactElement {
),
}, {
render: DocsTooltip,
},
{
}, {
arrow: true,
render: props => (
<TourBox
title="Tour: Customization"
Expand All @@ -82,10 +75,6 @@ export function App(): ReactElement {
.start(() => resolve());
});
},
floatingProps: {
middleware: [offset(4), shift()],
placement: "top",
},
render: ({ previous, stop }) => (
<SpotDescriptionView>
<DescriptionText>
Expand Down Expand Up @@ -113,14 +102,11 @@ export function App(): ReactElement {
overlayColor={"gray"}
overlayOpacity={0.36}
nativeDriver={true}
floatingProps={{
middleware:[offset(5), shift(), flip()],
placement: "bottom",
}}
onBackdropPress="continue"
onStop={showSummary}
motion="bounce"
shape="circle"
arrow={{ color: "#B0C4DE" }}
>
{({ start }) => (
<>
Expand Down
2 changes: 1 addition & 1 deletion package/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
},
"packageManager": "[email protected]",
"dependencies": {
"@floating-ui/react-native": "^0.10.4",
"@floating-ui/react-native": "^0.10.6",
"react-fast-compare": "^3.2.2",
"react-native-responsive-dimensions": "^3.1.1",
"styled-components": "^6.1.8"
Expand Down
7 changes: 7 additions & 0 deletions package/src/helpers/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ export type OmitR<
*/
export type Optional<T> = T | undefined;

/**
* Transforms the value types of an object to be `Optional`.
*/
export type ToOptional<T> = {
[K in keyof Required<T>]: Optional<T[K]>;
};

/**
* An alias of what a React child looks when passed as function.
*/
Expand Down
70 changes: 52 additions & 18 deletions package/src/lib/SpotlightTour.context.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Middleware, Placement } from "@floating-ui/react-native";
import { FlipOptions, Placement, ShiftOptions } from "@floating-ui/react-native";
import { createContext, ReactElement, useContext } from "react";
import { LayoutRectangle } from "react-native";
import { ColorValue, LayoutRectangle } from "react-native";

/**
* Possible motion effect for the tour spotlight:
Expand Down Expand Up @@ -81,27 +81,69 @@ export interface StopParams {
isLast: boolean;
}

export interface ArrowOptions {
/**
* The color of the tooltip arrow.
*
* @default white
*/
color?: ColorValue;
/**
* The rounding radius of the arrow tip.
*
* @default 2.5
*/
corner?: number;
/**
* The size of the tooltip arrow.
*
* @default 16
*/
size?: number;
}

/**
* Configuration object which accepts Floating Ui
* middleware, placement and sameScrollView configurations.
*/
export interface FloatingProps {
export interface TooltipProps {
/**
* Array of middleware objects to modify the positioning or provide data for
* rendering.
* Tooltip arrow options. It accepts 3 types of value:
* - boolean: When `false`, disable rendering the arrow. While `true` renders
* using the default values.
* - number: Use it to change the size of the arrow only.
* - object: Options to further customize the arrow style.
*
* @default 20
*/
middleware?: Middleware[];
arrow?: number | boolean | ArrowOptions;
/**
* Where to place the floating element relative to the reference element.
* Enables flipping the placement of the tooltip in order to keep it in view.
*
* @default true
*/
flip?: FlipOptions | boolean;
/**
* Offset points between the tooltip and the spotlight.
*
* @default 4
*/
offset?: number;
/**
* The placement of the tooltip relative to the spotlight.
*
* @default "bottom"
*/
placement?: Placement;
/**
* `true` for same scroll view, `false` otherwise.
* Enables shifting the tooltip in order to keep it in view.
*
* @default { padding: 8 }
*/
sameScrollView?: boolean;
shift?: ShiftOptions | boolean;
}

export interface TourStep {
export interface TourStep extends TooltipProps {
/**
* Hook called right before the step starts. Useful to run effects or
* animations required fo the step to show correctly. If a promise is
Expand All @@ -110,14 +152,6 @@ export interface TourStep {
* @default undefined
*/
before?: () => void | Promise<void>;
/**
* Specifies {@link FloatingProps} in order to configure Floating UI
* in a specific tour step layout.
*
* @default middlewares: [flip(), offset(4), shift()]
* @default placement: "bottom"
*/
floatingProps?: FloatingProps;
/**
* Specifies the transition motion for the step. You can set the default
* motion globally on the `SpotlightTourProvider` props too.
Expand Down
30 changes: 13 additions & 17 deletions package/src/lib/SpotlightTour.provider.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { flip, offset, shift } from "@floating-ui/react-native";
import React, {
forwardRef,
useCallback,
Expand All @@ -22,26 +21,18 @@ import {
SpotlightTourCtx,
TourStep,
ZERO_SPOT,
FloatingProps,
TooltipProps,
} from "./SpotlightTour.context";
import { TourOverlay, TourOverlayRef } from "./components/tour-overlay/TourOverlay.component";

export interface SpotlightTourProviderProps {
export interface SpotlightTourProviderProps extends TooltipProps {
/**
* The children to render in the provider. It accepts either a React
* component, or a function that returns a React component. When the child is
* a function, the `SpotlightTour` context can be accessed from the first
* argument.
*/
children: React.ReactNode | ChildFn<SpotlightTour>;
/**
* Specifies {@link FloatingProps} in order to configure Floating UI
* in all tour steps layout.
*
* @default middlewares: [flip(), offset(4), shift()]
* @default placement: "bottom"
*/
floatingProps?: FloatingProps;
/**
* Sets the default transition motion for all steps. You can override this
* value on each step too.
Expand Down Expand Up @@ -116,11 +107,12 @@ export interface SpotlightTourProviderProps {
*/
export const SpotlightTourProvider = forwardRef<SpotlightTour, SpotlightTourProviderProps>((props, ref) => {
const {
arrow,
flip,
offset,
placement,
shift,
children,
floatingProps = {
middleware: [flip(), offset(4), shift()],
placement: "bottom",
},
motion = "bounce",
nativeDriver = true,
onBackdropPress,
Expand Down Expand Up @@ -191,7 +183,7 @@ export const SpotlightTourProvider = forwardRef<SpotlightTour, SpotlightTourProv
? steps[current]
: undefined;

return step ?? { floatingProps, render: () => <></> };
return step ?? { render: () => <></> };
}, [steps, current]);

const tour = useMemo((): SpotlightTourCtx => ({
Expand Down Expand Up @@ -226,7 +218,6 @@ export const SpotlightTourProvider = forwardRef<SpotlightTour, SpotlightTourProv
backdropOpacity={overlayOpacity}
color={overlayColor}
current={current}
floatingProps={floatingProps}
motion={motion}
nativeDriver={nativeDriver}
onBackdropPress={onBackdropPress}
Expand All @@ -235,6 +226,11 @@ export const SpotlightTourProvider = forwardRef<SpotlightTour, SpotlightTourProv
shape={shape}
spot={spot}
tourStep={currentStep}
arrow={arrow}
flip={flip}
offset={offset}
placement={placement}
shift={shift}
/>
</SpotlightTourContext.Provider>
);
Expand Down
Loading

0 comments on commit 0d9b40d

Please sign in to comment.