fatihsolhan / v-onboarding

v-onboarding is a super-slim, fully-typed onboarding component for Vue 3
https://v-onboarding.fatihsolhan.com/
MIT License
170 stars 22 forks source link

feat: enhanced hooks (declaring options for advanced functionality) #83

Closed rozsazoltan closed 11 months ago

rozsazoltan commented 1 year ago

Feature

Currently, there are two defined hooks: beforeHook and afterHook. You can implement your own custom functions to run at the end of each step within the on.beforeStep and on.afterStep. Currently, it is not possible to associate and pass settings to the hooks, including the developer-defined extra functions.

There has been a demand, considering that within the hook, we can determine whether the current step is 'previous' or 'next' relative to the previously displayed step, i.e., whether the step is moving 'backward' or 'forward'.

At first, I thought of declaring this as a variable and created the direction function parameter. However, I continued to refine the idea and instead declared it as options, serving as the parameter for hook settings. As a result, both hooks have currently expanded with a single setting for specifying the direction. However, in the future, other hook-specific or global settings can also be passed to the functions defined by the developer.

Before this feature

{
  on: {
    beforeStep: () => console.log("I don't know if we were going backwards or forwards now"),
    afterStep: () => console.log("I don't know if we were going backwards or forwards now"),
  }
}

I have no way to distinguish the direction of the step, so the function declared here runs regardless of whether I stepped forward or backward to this question. However, it might only make sense in one of these cases.

With feature

// typescript for hook options

// global options
interface onGlobalOptions {
  index: number
  step: StepEntity
  direction: 1 | -1 | number
  isForward: boolean
  isBackward: boolean
}
// options for beforeStep
export type onBeforeStepOptions = onGlobalOptions & {
  // custom options here
}
// options for afterStep
export type onAfterStepOptions = onGlobalOptions & {
  // custom options here
}
// declared directions
export const Direction = {
  BACKWARD: -1,
  FORWARD: 1
}
{
  on: {
    beforeStep: ({ direction }) => console.log(`Current direction: ${direction > 0 ? "forward" : "backward"}`),
    afterStep: (options) => console.log(`Current direction: ${options.isForward === true ? "forward" : "backward"}`),
  }
}

So, in short, the opportunity arose within the hook to distinguish when a code snippet should run. For example, you might want to run an animation when moving forward, but it may not make sense when moving backward.

Access to the data of the step (inspired by hackathi)

By creating hook options, you can easily pass the data of the current step to the function, allowing you to create dynamic functions using it. As hackathi mentioned, this can be easily achieved by passing the StepEntity. Furthermore, the index of the current step can also be passed, which I have also implemented.

function exampleGlobalStepHook (options) {
  if (options.index < 5) console.log("Initial steps")
  else console.log("Advanced settings")

  if (options.step.content.description.length < 30) console.log("Easy")
  else console.log("Hard")
}
{
  on: {
    beforeStep: exampleGlobalStepHook,
    afterStep: exampleGlobalStepHook,
  }
}

Updated

netlify[bot] commented 1 year ago

Deploy Preview for eloquent-lamport-f2ffa1 canceled.

Name Link
Latest commit 66a94c02754cd6596030991d09dfaf1861767abf
Latest deploy log https://app.netlify.com/sites/eloquent-lamport-f2ffa1/deploys/650ff0ffb116cf00082bc820
netlify[bot] commented 1 year ago

Deploy Preview for beamish-dango-bc9c2d canceled.

Name Link
Latest commit 66a94c02754cd6596030991d09dfaf1861767abf
Latest deploy log https://app.netlify.com/sites/beamish-dango-bc9c2d/deploys/650ff0fff65f7b000879590e
hackathi commented 1 year ago

As a sidenote adjacent to this PR: It'd be really cool if these callbacks could also accept the step as a parameter.

My Use-Case in particular is playing audio associated which each step; this would be really easy if I coud just extend the StepEntity and have the afterStep callback handle all the code directly. Right now I have to keep a reference to the Wrapper element and use it's computed activeStep property, which isn't really elegant IMO.

Anyway, thanks for the library!

hackathi commented 1 year ago

@rozsazoltan you're the MVP. Seriously. Thank you so much!

fatihsolhan commented 1 year ago

Thank you @rozsazoltan, these improved hooks will bring much more value to the v-onboarding, I appreciate your effort 🙏 @hackathi Thank you for using the v-onboarding and helping us to improve it 🙏

@rozsazoltan is this PR ready to merge, are you planning any other changes?

rozsazoltan commented 1 year ago

Hey! What I wanted to created has been implemented. I tried to structure the code in a way that it can be easily extended in the future, so I believe the current changes are final, and we can proceed with the merge.

github-actions[bot] commented 11 months ago

:tada: This PR is included in version 2.6.0 :tada:

The release is available on:

Your semantic-release bot :package::rocket: