Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable autofocus of step content via step options #2117

Open
DaDom opened this issue Oct 24, 2022 · 7 comments
Open

Disable autofocus of step content via step options #2117

DaDom opened this issue Oct 24, 2022 · 7 comments

Comments

@DaDom
Copy link

DaDom commented Oct 24, 2022

Hey there!

I'd like to "re-discuss" #1588 - I have the same use case, in which I would like to keep an input in the highlighted app part focused, and not have the step popup take focus away. Currently, you use floating-ui to focus the step element after 300ms timeout (see here).

I understand that this is something where you would like to figure out a general strategy around a11y. In my case, I would however rather disable this behavior entirely via some step option autoFocus = false or something like that.
Would you accept a PR that introduces this ability, or you would not like to have such changes until you have a clearer position on this topic overall?

@RobbieTheWagner
Copy link
Member

@DaDom I think we should find a way to add arbitrary elements into the focus trap that we implement. That way, we can keep what we have, but also allow adding more possible focus targets into the mix.

@DaDom
Copy link
Author

DaDom commented Oct 24, 2022

Great, that makes sense.
So, equivalent to StepOptionsAttachTo.element it might be a new step option like this - assuming that you may provide more than one selector/element:

focusableElements?: HTMLElement | HTMLElement[] | string | string[] | (() => HTMLElement | HTMLElement[] | string | string[] | null | undefined)

Providing a value for this option will:

  • Include all matching elements into the focus trap
  • Auto-focus the first matching element when the step is shown

Is that what you had in mind?
Btw., am I correct that you have chosen 300ms as delay before applying focus due to the css transition duration of 0.3s for shepherd-modal-overlay-container?

@DaDom
Copy link
Author

DaDom commented Oct 24, 2022

Alternatively, following your existing approach of finding all focusable elements here, we might also do the same inside of the resulting HTMLElement of StepOptionsAttachTo.element.
This could then be toggled with a simple boolean flag like this:

interface StepOptionsAttachTo {
  element?: HTMLElement | string | (() => HTMLElement | string | null | undefined);
  on?: PopperPlacement;
  focusable?: boolean;
}

Let me know what you think!

@MaggusK
Copy link

MaggusK commented Feb 12, 2023

Me too!!
I'm new with shepherd, its the best js guiding tool (and I tested a lot!) but this described behavior, from my point of view, is a bug.
I have inputs that start an ajax action (saving) on focus lost. So currently I can not use them during highlighting.

(Exact workflow: click an element inside the highlighted element -> an input appears that increases the highlighted element -> the input gets focused -> shepherd does a redraw -> the focus of input gets lost -> input disappear)

@amitPurohit01
Copy link

hi , is there any update on this bug, i am not able to highlight input element, but for text area it works fine

@amitPurohit01
Copy link

hi this is reply to my question , for me it was not working because i was trying to open them in mat-dialog but and i had to remove and it started working , thank you

@crudobaker
Copy link

Hey!

I think the option of configuring the autofocus property on step declaration is the best choice, like @DaDom proposal.

For the moment, what works for my case is set the focus with a timeout, to override the autofocus on the current step.

In this example the PressEnterOnTarget advance on action listens the Enter event on the target element to continue the tour.

export const PressEnterOnTarget = {
  configure: () => {
    const currentStep = Shepherd.activeTour?.getCurrentStep();
    const pressEnterListener = event => {
      if (event.key === 'Enter') {
        currentStep.getTour().next();
      }
    };
    currentStep.getTarget().addEventListener('keypress', pressEnterListener);

    // it adds the focus on the target element
    setTimeout(() => currentStep.getTarget().focus(), 500);

    return () => currentStep.getTarget().removeEventListener('keypress', pressEnterListener);
  },
};

Hope it helps, and keep waiting for the improvement!

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

No branches or pull requests

5 participants