Files
headlessui/packages/@headlessui-vue/src/components/focus-trap/README.md
T
Robin Malfait 6f8225c437 Next batch of Vue components (#282)
* add little editor hack

By adding a html`..` to the template strings editors can get syntax
highlighting for these template strings. Even better, prettier can even
format the contents inside those because now it is "aware" of what kind
of content is inside of these template strings.

You might notice that for the Menu component I have a jsx`..`, this is
another little hack, this only provides us with syntax highlighting and
not with prettier support.

The reason why we have this is that for some reason, when you have:

html`
  <MenuItem>
`

It will be formatted as:

html`
  <menuitem>
`

There might exist a better name we can use instead of jsx, but for now,
this will do. Having syntax highlighting is already 10x better than what
we had before!

* add Alert component

* update changelog

* update REACT readme for Alert component

* expose Alert component

* add Disclosure component

* expose Disclosure component

* add FocusTrap component

* add FocusTrap example

* expose FocusTrap

* update test utils

We've been making some changes in the React utils, so we have to update
them here as well!

* add Popover component

* expose Popover

* drop unused state

* type Disclosure's API object

* add Portal component

* add Portal example

* expose Portal component

* use correct containElement assertion

* add useInertOthers hook

* add Dialog component

* fix various typo's

* expose Dialog

* add Popover example

* force focus on the Popover button on click

* drop own id when using labels

We are nesting the Label and Description components, if we also add the
id of ourselves we get strange results when using Voice Over.

First you would hear the contents (which includes the labels and
descriptions) then you would hear the labels and descriptions again.

We don't want to hear things twice!

* add Dialog example

* ensure to stop propagation

Otherwise if you nest a Menu inside a Dialog and you press `Escape` the
Dialog will close as well, which is not the expected behaviour.

* improve focus management

When you trigger a Popover using a `click` event, then start using `Tab`
the next `a`-tags do not contain the default focus styles. These only
happen when you trigger it using the keyboard first.

Using a tabindex="0" does make it "focusable" and the default browser
styles will be visible. If we remove the tabindex in a
requestAnimationFrame or a setTimeout then the focus styles will be
removed as well.

This should not cause to many issues (fingers crossed) because the
document.activeElement was already referring to the correct element!

* remove Alert component

There are a lot of unknowns and context dependendant questions to
implement Alerts in a good way. The current Alert component just had a
role set, and it had no JS attached.

We will revisit this, once we start working on Alert Dialogs,
Notification center notifications (dismissable, hide after x time, ...)

* ensure Popover.Overlay auto shows/hides based on Popover state

* enable focus trapping based on `open` prop

Only enable focus trapping in the Dialog when `open` is true, regardless
of the `static` prop.

* handle attrs on Dialog manually

* add low level Description component

* add low level Label component

* add RadioGroup component

* expose RadioGroup

* update README with links to new components

* update changelog with all the changes

* add RadioGroup example

* improve type in test

* cleanup internal Dialog Description

We have a low level Description component abstraction that can be used
instead of the Dialog specifiction Description.

* refactor raw window events to a shared useWindowEvent

* passthrough prop bag via context for abstract Description

The Description component is a generic low level component that is
re-used. This causes an issue that the render prop "bag"/"slot" doesn't
contain the data from let's say a Dialog component.

This commit will ensure that you can specify a bag (React) and slot
(Vue) on the DescriptionProvider, so that the Description component can
read it from the context.

* improve render function in React

These contain a few changes that are purely internal changes. Nothing
changes / breaks in the public API of the components.

- Instead of using multiple arguments in your `render()` functions, we now
use an object.
- `propsBag` / `bag` is renamed to `slot`.
- We also provide a `name` to the render function, so that we can use
  that to improve error messages.

* use the new internal render api (React)

* improve render function in Vue

* use the new internal render api (Vue)
2021-04-04 17:49:44 +02:00

1.8 KiB

FocusTrap

A component for making sure that you can't Tab out of the contents of this component.

Focus strategy:

  • An initialFocus prop can be passed in, this is a ref object, which is a ref to the element that should receive initial focus.
  • If an input element exists with an autoFocus prop, it will receive initial focus.
  • If none of those exists, it will try and focus the first focusable element.
  • If that doesn't exist, it will throw an error.

Once the FocusTrap will unmount, the focus will be restored to the element that was focused before the FocusTrap was rendered.

NOTE: This component will throw when there are no focusable elements. This is an accessibility feature. At least try to provide a close button or similar so that users don't get stuck.

Installation

# npm
npm install @headlessui/vue

# Yarn
yarn add @headlessui/vue

Basic example

<FocusTrap>
  <form>
    <input type="email" name="Email" />
    <input type="password" name="password" />
    <button>Submit</button>
  </form>
</FocusTrap>

Component API

FocusTrap

<FocusTrap>
  <form>
    <input type="email" name="Email" />
    <input type="password" name="password" />
    <button>Submit</button>
  </form>
</FocusTrap>
Props
Prop Type Default Description
as String | Component div The element or component the FocusTrap should render as.
initialFocus React.MutableRefObject undefined A ref to an element that should receive focus first.