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

chore: Add focus-trap example #988

Merged
merged 5 commits into from
Feb 13, 2022

Conversation

ItsJonQ
Copy link

@ItsJonQ ItsJonQ commented Jan 27, 2022

This update adds a basic example for the FocusTrap component as part of this effort: #939

Screenshots

FocusTrap example update

How to test?

Does this PR introduce breaking changes?

Nope! Only adding an example.

@vercel
Copy link

vercel bot commented Jan 27, 2022

This pull request is being automatically deployed with Vercel (learn more).
To see the status of your deployments, click below or on the icon next to each commit.

reakit – ./

🔍 Inspect: https://vercel.com/ariakit/reakit/D9YBjAusWxkAFB9v2K2ABwtKEjf6
✅ Preview: Canceled

[Deployment for f858069 canceled]

ariakit – ./

🔍 Inspect: https://vercel.com/ariakit/ariakit/4teJa7pUCjCc3EPVTJbGm2fLUxY9
✅ Preview: https://ariakit-git-fork-itsjonq-chore-focus-trap-example-ariakit.vercel.app

@codesandbox-ci
Copy link

codesandbox-ci bot commented Jan 27, 2022

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

@codecov
Copy link

codecov bot commented Jan 27, 2022

Codecov Report

Merging #988 (f858069) into main (72944c1) will increase coverage by 4.19%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #988      +/-   ##
==========================================
+ Coverage   65.06%   69.26%   +4.19%     
==========================================
  Files         174      179       +5     
  Lines        4311     4402      +91     
  Branches     1186     1206      +20     
==========================================
+ Hits         2805     3049     +244     
+ Misses       1505     1352     -153     
  Partials        1        1              
Impacted Files Coverage Δ
...t/src/focus-trap/__examples__/focus-trap/index.tsx 100.00% <100.00%> (ø)
packages/ariakit/src/popover/popover-state.ts 73.23% <0.00%> (-14.48%) ⬇️
...kages/ariakit/src/composite/composite-typeahead.ts 39.06% <0.00%> (-8.11%) ⬇️
packages/ariakit/src/popover/popover.tsx 93.93% <0.00%> (-0.18%) ⬇️
packages/ariakit/src/portal/portal.tsx 57.00% <0.00%> (-0.15%) ⬇️
packages/ariakit/src/dialog/dialog-state.ts 100.00% <0.00%> (ø)
packages/ariakit/src/disclosure/disclosure.ts 100.00% <0.00%> (ø)
packages/ariakit/src/hovercard/__debug-polygon.ts 0.00% <0.00%> (ø)
...kages/ariakit/src/dialog/__utils/dialog-context.ts 100.00% <0.00%> (ø)
.../popover/__examples__/popover-responsive/index.tsx 0.00% <0.00%> (ø)
... and 35 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 72944c1...f858069. Read the comment docs.

@diegohaz
Copy link
Member

Great job! I'd suggest we make this example more simple though. And let users disable the focus trap behavior so keyboard users accessing the docs will be able to use the site. Let's also avoid using ariakit-utils in the examples.

Wrote this snippet to illustrate what I'm talking about:

import { FocusEvent, useRef } from "react";
import { useCheckboxState, Checkbox, CheckboxCheck } from "ariakit/checkbox";
import { FocusTrap } from "ariakit/focus-trap";
import "./style.css";

export default function Example() {
  const focusTrapped = useCheckboxState({ defaultValue: true });
  const firstRef = useRef<HTMLButtonElement>(null);
  const lastRef = useRef<HTMLButtonElement>(null);

  const onTrapFocus = (event: FocusEvent) => {
    if (event.relatedTarget === firstRef.current) {
      lastRef.current?.focus();
    } else {
      firstRef.current?.focus();
    }
  };

  return (
    <>
      {focusTrapped.value && <FocusTrap onFocus={onTrapFocus} />}
      <div className="wrapper">
        <button className="button" ref={firstRef}>
          First
        </button>
        <Checkbox
          state={focusTrapped}
          clickOnEnter
          as="button"
          className="button"
        >
          <CheckboxCheck />
          Trap focus
        </Checkbox>
        <button className="button" ref={lastRef}>
          Last
        </button>
      </div>
      {focusTrapped.value && <FocusTrap onFocus={onTrapFocus} />}
    </>
  );
}

@diegohaz diegohaz changed the title Focus Trap - Add example chore: Add focus-trap example Jan 28, 2022
@ItsJonQ
Copy link
Author

ItsJonQ commented Feb 2, 2022

@diegohaz Wow! Thank you so much 🙇

I've updated the example based on your snippet. I adjusted the styles a bit to make the example a little clearer.

FocusTrap example update

Let me know if this works! Happy to make any updates necessary

Copy link
Member

@diegohaz diegohaz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Niiice! I made a suggestion to fix the tab order.

Also, would you like to add some tests? We can test with press.Tab() and press.ShiftTab() (do a global search on the project to find some examples).

Comment on lines 22 to 33
<div className="wrapper">
<label className="label">
<Checkbox state={focusTrapped} clickOnEnter className="checkbox" />
Trap focus
</label>
<button className="button" ref={firstRef}>
First
</button>
<button className="button" ref={lastRef}>
Last
</button>
</div>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The behavior is a little bit weird now when the focus is trapped. When pressing Tab, the focus never goes to the checkbox, when pressing Shift+Tab, the focus never goes to the last button.

I think we can just make the checkbox the first item ref to fix this:

Suggested change
<div className="wrapper">
<label className="label">
<Checkbox state={focusTrapped} clickOnEnter className="checkbox" />
Trap focus
</label>
<button className="button" ref={firstRef}>
First
</button>
<button className="button" ref={lastRef}>
Last
</button>
</div>
<div className="wrapper">
<label className="label">
<Checkbox state={focusTrapped} ref={firstRef} className="checkbox" />
Trap focus
</label>
<button className="button" ref={lastRef}>
Button
</button>
</div>

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you so much @diegohaz !! Sorry for the delay! I was able to update the example with your suggestion. I've also added the focus trap test. The Ariakit test utils are really great! ❤️

Comment on lines 15 to 18
<div>
<Example />
<div tabIndex={0}>Outside</div>
</div>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! 👍 We usually render just <Example />, but these extra elements are handy here. Do you think we should add another element before so we can test shift+tab as well?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yea! Let's do that 💪

<div tabIndex={0}>Outside</div>
</div>
);
focus(getByRole("checkbox"));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should use something that better describes a user action here, like await press.Tab() or await click().

);
// Disabling focus trap
await click(getByLabelText("Trap focus"));
await focus(getByRole("button"));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
await focus(getByRole("button"));
await press.Tab();

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@diegohaz I updated both tests to rely on user interactions - Tab and ShiftTab. These utils are great!

@diegohaz diegohaz changed the base branch from v2 to master February 10, 2022 22:45
Copy link
Member

@diegohaz diegohaz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! Thank you! ❤️

@diegohaz diegohaz merged commit 4803562 into ariakit:main Feb 13, 2022
@ariakit-bot
Copy link

Thanks a lot for contributing!

Based on our community guidelines, every person who has a PR of any kind merged is offered an invitation to the Reakit organization.

Should you accept, you'll get write access to the main repository and a fancy Reakit logo on your GitHub profile. You'll be able to label and close issues, create new branches etc. Make sure to read our contribution and community guidelines, which explains all of this in more detail.

If you have any questions, let me know!

@ItsJonQ ItsJonQ mentioned this pull request Feb 19, 2022
69 tasks
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

Successfully merging this pull request may close these issues.

None yet

3 participants