Skip to content

Commit

Permalink
fix(select): remove hidden input from hidden-select
Browse files Browse the repository at this point in the history
  • Loading branch information
Peterl561 committed Dec 22, 2024
1 parent 11a543c commit a683374
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 26 deletions.
1 change: 0 additions & 1 deletion apps/docs/content/docs/components/select.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,6 @@ the popover and listbox components.
- Keyboard support for opening the listbox using the arrow keys, including automatically focusing the first or last item accordingly.
- Typeahead to allow selecting options by typing text, even without opening the listbox.
- Browser autofill integration via a hidden native `<select>` element.
- Support for mobile form navigation via software keyboard.
- Mobile screen reader listbox dismissal support.

<Spacer y={4} />
Expand Down
32 changes: 7 additions & 25 deletions packages/components/select/src/hidden-select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import {FocusableElement} from "@react-types/shared";
import React, {ReactNode, RefObject} from "react";
import {useFormReset} from "@react-aria/utils";
import {useInteractionModality} from "@react-aria/interactions";
import {useVisuallyHidden} from "@react-aria/visually-hidden";
import {MultiSelectProps, MultiSelectState} from "@nextui-org/use-aria-multiselect";
import {useFormValidation} from "@react-aria/form";
Expand Down Expand Up @@ -71,7 +70,6 @@ export function useHiddenSelect<T>(
onChange,
} = props;
let {validationBehavior, isRequired, isInvalid} = data;
let modality = useInteractionModality();
let {visuallyHiddenProps} = useVisuallyHidden();

useFormReset(props.selectRef!, state.selectedKeys, state.setSelectedKeys);
Expand All @@ -84,34 +82,23 @@ export function useHiddenSelect<T>(
props.selectRef,
);

const commonProps = {
autoComplete,
disabled: isDisabled,
"aria-invalid": isInvalid || undefined,
"aria-required": (isRequired && validationBehavior === "aria") || undefined,
required: isRequired && validationBehavior === "native",
};

return {
containerProps: {
...visuallyHiddenProps,
"aria-hidden": true,
["data-a11y-ignore"]: "aria-hidden-focus",
},
inputProps: {
...commonProps,
type: "text",
tabIndex: modality == null || state.isFocused || state.isOpen ? -1 : 0,
value: [...state.selectedKeys].join(",") ?? "",
style: {fontSize: 16},
onFocus: () => triggerRef.current?.focus(),
onChange: () => {}, // The onChange is handled by the `select` element
style: {display: "none"},
},
selectProps: {
...commonProps,
autoComplete,
disabled: isDisabled,
"aria-invalid": isInvalid || undefined,
"aria-required": (isRequired && validationBehavior === "aria") || undefined,
required: isRequired && validationBehavior === "native",
name,
tabIndex: -1,
size: state.collection.size,
value:
selectionMode === "multiple"
? [...state.selectedKeys].map((k) => String(k))
Expand All @@ -132,19 +119,14 @@ export function useHiddenSelect<T>(
export function HiddenSelect<T>(props: HiddenSelectProps<T>) {
let {state, triggerRef, selectRef, label, name, isDisabled} = props;

let {containerProps, inputProps, selectProps} = useHiddenSelect(
{...props, selectRef},
state,
triggerRef,
);
let {containerProps, selectProps} = useHiddenSelect({...props, selectRef}, state, triggerRef);

// If used in a <form>, use a hidden input so the value can be submitted to a server.
// If the collection isn't too big, use a hidden <select> element for this so that browser
// autofill will work. Otherwise, use an <input type="hidden">.
if (state.collection.size <= 300) {
return (
<div {...containerProps} data-testid="hidden-select-container">
<input {...inputProps} />
<label>
{label}
<select {...selectProps} ref={selectRef}>
Expand Down

0 comments on commit a683374

Please sign in to comment.