Skip to content

Commit

Permalink
feat: hideClose tooltip option
Browse files Browse the repository at this point in the history
  • Loading branch information
VojtechVidra committed Oct 31, 2023
1 parent 72d4dd1 commit dcd68a0
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 21 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rbnd/flows",
"version": "0.0.14",
"version": "0.0.15",
"description": "A better way to onboard users and drive product adoption.",
"repository": {
"type": "git",
Expand Down
7 changes: 6 additions & 1 deletion src/flow-state.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { FlowsContext } from "./flows-context";
import { render } from "./render";
import type { Flow, FlowStep, FlowStepIndex, TrackingEvent } from "./types";
import { isModalStep, isTooltipStep } from "./utils";

interface InterfaceFlowState {
flowId: string;
Expand Down Expand Up @@ -101,7 +102,11 @@ export class FlowState implements InterfaceFlowState {

prevStep(): this {
this.stepHistory = this.stepHistory.slice(0, -1);
while (this.currentStep && "wait" in this.currentStep)
while (
this.stepHistory.length &&
this.currentStep &&
!(isTooltipStep(this.currentStep) || isModalStep(this.currentStep))
)
this.stepHistory = this.stepHistory.slice(0, -1);
if (this.currentStep) this.flowsContext.onPrevStep?.(this.currentStep);
this.track({ type: "prevStep" });
Expand Down
2 changes: 1 addition & 1 deletion src/jsx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ if (typeof window !== "undefined")
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- there can be other prop keys
if (key === "dangerouslySetInnerHTML") {
const value = props[key];
if (value) el.innerHTML = value.__html;
if (value?.__html) el.innerHTML = value.__html;
return;
}
el.setAttribute(key, props[key]);
Expand Down
45 changes: 27 additions & 18 deletions src/render.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { computePosition, offset, flip, shift, autoUpdate } from "@floating-ui/dom";
import type { FlowModalStep, FlowStep, FlowTooltipStep, Placement } from "./types";
import type { FlowModalStep, FlowTooltipStep, Placement } from "./types";
import type { FlowState } from "./flow-state";
import { isModalStep, isTooltipStep } from "./utils";

const updateTooltip = ({
target,
Expand Down Expand Up @@ -57,21 +58,28 @@ const renderTooltip = ({
state: FlowState;
target: Element;
}): { cleanup: () => void } => {
const backBtn = state.hasPrevStep && (
<div className="flows-back-wrap">
<button className="flows-back flows-button">Back</button>
</div>
);
const continueBtn = getStepContinueButton({ state, step });

const tooltip = (
<div className="flows-tooltip">
<div className="flows-header">
<h1 className="flows-title" dangerouslySetInnerHTML={{ __html: step.title }} />
{state.hasNextStep && <button className="flows-cancel flows-button">Close</button>}
</div>
{step.body && <div className="flows-body" dangerouslySetInnerHTML={{ __html: step.body }} />}
<div className="flows-tooltip-footer">
{state.hasPrevStep && (
<div className="flows-back-wrap">
<button className="flows-back flows-button">Back</button>
</div>
{state.hasNextStep && !step.hideClose && (
<button className="flows-cancel flows-button">Close</button>
)}
{getStepContinueButton({ state, step })}
</div>
{step.body && <div className="flows-body" dangerouslySetInnerHTML={{ __html: step.body }} />}
{(backBtn || (Array.isArray(continueBtn) ? continueBtn.length : continueBtn)) && (
<div className="flows-tooltip-footer">
{backBtn}
{continueBtn}
</div>
)}
</div>
);
root.appendChild(tooltip);
Expand Down Expand Up @@ -111,32 +119,33 @@ const renderModal = ({
root.appendChild(modal);
};

const isTooltipStep = (step: FlowStep): step is FlowTooltipStep => "element" in step;
const isModalStep = (step: FlowStep): step is FlowModalStep => !isTooltipStep(step);
const createRoot = (): HTMLElement => {
const root = document.createElement("div");
root.className = "flows-root";
root.style.pointerEvents = "auto";
document.body.appendChild(root);
return root;
};

export const render = (state: FlowState): void => {
const step = state.currentStep;
if (!step) return;

state.cleanup();

if ("wait" in step) return;
const root = document.createElement("div");
root.className = "flows-root";
root.style.pointerEvents = "auto";
document.body.appendChild(root);
if (isTooltipStep(step)) {
const target = document.querySelector(step.element);
if (target) {
state.waitingForElement = false;
const root = createRoot();
const { cleanup } = renderTooltip({ root, step, state, target });
state.flowElement = { element: root, cleanup };
} else {
state.waitingForElement = true;
root.remove();
}
}
if (isModalStep(step)) {
const root = createRoot();
renderModal({ root, step, state });
state.flowElement = { element: root };
}
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export interface FlowTooltipStep {
element: string;
options?: { text: string; action: number }[];
placement?: Placement;
hideClose?: boolean;
}
export interface FlowModalStep {
key?: string;
Expand Down
5 changes: 5 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { FlowStep, FlowTooltipStep, FlowModalStep } from "./types";

export const isTooltipStep = (step: FlowStep): step is FlowTooltipStep => "element" in step;
export const isModalStep = (step: FlowStep): step is FlowModalStep =>
!isTooltipStep(step) && ("title" in step || "body" in step);

0 comments on commit dcd68a0

Please sign in to comment.