@acusti/dropdown 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -294,8 +294,9 @@ type Props = {
294
294
  * Whether the body is a list of selectable items (the default) or
295
295
  * arbitrary interactive content such as a form. hasItems={false} turns
296
296
  * off item selection and item keyboard navigation, gives the popup
297
- * role="dialog" (unless isSearchable), and keeps it open on clicks
298
- * inside the body. Defaults to true and isn’t inferred from the children.
297
+ * role="dialog" (unless isSearchable), keeps it open on clicks inside
298
+ * the body, and leaves Space and Enter pressed in the body to the
299
+ * controls there. Defaults to true and isn’t inferred from the children.
299
300
  */
300
301
  hasItems?: boolean;
301
302
  /**
@@ -322,7 +323,10 @@ type Props = {
322
323
  /**
323
324
  * Whether the dropdown stays open after an item is submitted, e.g. for a
324
325
  * multi-select. Defaults to !hasItems: a menu closes on submit, while a
325
- * hasItems={false} dialog stays open.
326
+ * hasItems={false} dialog stays open. In a hasItems={false} dropdown, a
327
+ * submit is a form in the body being submitted, or Enter in a
328
+ * single-line input that appears in the body with no form or in the
329
+ * trigger.
326
330
  */
327
331
  keepOpenOnSubmit?: boolean;
328
332
  /**
@@ -714,6 +718,54 @@ function InteractiveDropdown() {
714
718
  }
715
719
  ```
716
720
 
721
+ The body’s controls keep their own keys while the dropdown is open: Space
722
+ and Enter go to whatever has focus there. Space types a space into a text
723
+ field, toggles a checkbox, and presses a button; Enter adds a line break to
724
+ a textarea, submits the form around a text input, presses a button, and
725
+ follows a link. The same goes for whatever keeps focus outside the dropdown
726
+ while it’s open, as when it opened on hover. Escape closes the dropdown
727
+ unless focus is in a text field (a text input, a textarea, or an editable
728
+ element). On the trigger, Space and Enter open the dropdown and, unless
729
+ focus is in a text field or a checkbox there, close it again, as a click
730
+ there does. Once it is open, Enter in a textarea or an editable element
731
+ used as the trigger adds a line break there. Enter in a single-line input
732
+ used as the trigger is a submit, whether or not a form owns it: the
733
+ dropdown takes the key, so a form around the trigger isn’t submitted from
734
+ that input while the dropdown is open.
735
+
736
+ A `hasItems={false}` dropdown stays open until it is dismissed. Pass
737
+ `keepOpenOnSubmit={false}` to close it when its content is submitted. A
738
+ submit is a form in the body being submitted, by Enter in one of its inputs
739
+ or by its submit button, or Enter in a single-line input, either one in the
740
+ body that no form owns or one used as the trigger:
741
+
742
+ ```tsx
743
+ <Dropdown hasItems={false} keepOpenOnSubmit={false}>
744
+ Rename
745
+ <form onSubmit={handleSubmit}>
746
+ <label>
747
+ Name <input name="name" required />
748
+ </label>
749
+ <button type="submit">Save</button>
750
+ </form>
751
+ </Dropdown>
752
+ ```
753
+
754
+ Unless the form opts out of validation (`noValidate`, or a submit button
755
+ with `formNoValidate`), its `submit` event doesn’t fire until the browser’s
756
+ validation passes, so the dropdown stays open while a required field is
757
+ empty. To keep it open after a submit that your own checks reject, call
758
+ `event.stopPropagation()` in the form’s `onSubmit` before it returns. A
759
+ check that finishes later, such as a server round trip or a form library
760
+ that validates asynchronously, can’t keep it open.
761
+
762
+ Enter in such an input, in the body or the trigger, counts the way a form
763
+ would count it: not when a handler has prevented the key, as a combobox
764
+ does to pick an option, and not when it commits an IME composition.
765
+
766
+ When a submit closes the dropdown while focus is in its body, focus returns
767
+ to the trigger, as it does on Escape.
768
+
717
769
  ### Placement Customization with CSS Variables
718
770
 
719
771
  Placement is best customized in CSS instead of props. The component exposes
@@ -1262,7 +1314,11 @@ intent delay while the highlight stays on the parent, and only → moves the
1262
1314
  highlight into it.
1263
1315
 
1264
1316
  - **Enter/Space**: Open the dropdown; with an item highlighted, select it
1265
- (leaf items) or open its submenu (parent items)
1317
+ (leaf items) or open its submenu (parent items). In the body of a
1318
+ `hasItems={false}` dropdown, they go to
1319
+ [the control that has focus](#dropdown-with-interactive-content) instead,
1320
+ and on its open trigger, outside a text field or a checkbox, they close
1321
+ it
1266
1322
  - **Escape**: Close the dropdown entirely — including any open submenus —
1267
1323
  and return focus to the trigger (macOS-style; use ← to back out one level
1268
1324
  at a time)
@@ -1280,6 +1336,13 @@ highlight into it.
1280
1336
  input, or one inside a custom trigger), where they move the caret instead
1281
1337
  - **Type characters**: Jump to the best-matching item in the current level
1282
1338
 
1339
+ While text is being composed with an IME, in a searchable dropdown’s input
1340
+ or a text field in a custom trigger, the dropdown ignores every keydown
1341
+ that the browser reports as part of the composition. With a Japanese IME,
1342
+ the Enter that commits the text doesn’t submit (the next Enter is an
1343
+ ordinary one), and the arrow keys and Escape don’t move the highlight or
1344
+ close the dropdown. Other IMEs can report their keys differently.
1345
+
1283
1346
  For accessibility, the component focuses on semantic HTML structure and
1284
1347
  keyboard navigation. It works best when you use appropriate HTML elements
1285
1348
  in your dropdown content (like `<ul>` and `<li>` for lists, `<button>`
@@ -70,8 +70,9 @@ export type Props = {
70
70
  * Whether the body is a list of selectable items (the default) or
71
71
  * arbitrary interactive content such as a form. hasItems={false} turns
72
72
  * off item selection and item keyboard navigation, gives the popup
73
- * role="dialog" (unless isSearchable), and keeps it open on clicks
74
- * inside the body. Defaults to true and isn’t inferred from the children.
73
+ * role="dialog" (unless isSearchable), keeps it open on clicks inside
74
+ * the body, and leaves Space and Enter pressed in the body to the
75
+ * controls there. Defaults to true and isn’t inferred from the children.
75
76
  */
76
77
  hasItems?: boolean;
77
78
  /**
@@ -98,7 +99,10 @@ export type Props = {
98
99
  /**
99
100
  * Whether the dropdown stays open after an item is submitted, e.g. for a
100
101
  * multi-select. Defaults to !hasItems: a menu closes on submit, while a
101
- * hasItems={false} dialog stays open.
102
+ * hasItems={false} dialog stays open. In a hasItems={false} dropdown, a
103
+ * submit is a form in the body being submitted, or Enter in a
104
+ * single-line input that appears in the body with no form or in the
105
+ * trigger.
102
106
  */
103
107
  keepOpenOnSubmit?: boolean;
104
108
  /**