From 4bef4ad23b9dc352de6b4c40414043f54455c811 Mon Sep 17 00:00:00 2001 From: Edwin Guzman Date: Mon, 9 Dec 2024 17:50:25 -0500 Subject: [PATCH] eehhh wrong branch base --- src/components/TextInput/TextInput.mdx | 50 +++++++++++++++++ .../TextInput/TextInput.stories.tsx | 54 ++++++++++++++++++- src/components/TextInput/TextInput.tsx | 2 +- .../TextInput/textInputChangelogData.ts | 7 +++ 4 files changed, 110 insertions(+), 3 deletions(-) diff --git a/src/components/TextInput/TextInput.mdx b/src/components/TextInput/TextInput.mdx index 5b632acc2..a67db11b8 100644 --- a/src/components/TextInput/TextInput.mdx +++ b/src/components/TextInput/TextInput.mdx @@ -25,6 +25,7 @@ import { changelogData } from "./textInputChangelogData"; - {isClearable Button} - {Number Type} - {HTML in Helper Text} +- {Focus Ref Management} - {Textarea} - {Changelog} @@ -165,6 +166,55 @@ export const App = () => { +### Focus Ref Management + +Focus management is important for accessibility and can get complicated in pages +that have multiple focusable elements and various user interactions. The +following is an example found in the Research Catalog's +[My Account](https://nypl.org/research/research-catalog/account) page (you have +to sign in) where the page's accessibility requirement conflicted with the +`TextInput` component's internal focus management. This was apparent through the +use of the clearable "X" button and has now been resolved. + +The `TextInput` component keeps track of it's own ref for clearing the input +field. If your app needs to manage focus separately, you should still pass a ref +to the `TextInput` component as you normally would with a React component. + +In the following example, when the user clicks on the "Edit" button, focus needs +to go to the input field. It is the consuming application's responsibility to +send focus to the input field when the "Edit" button is clicked. + + { + setIsEdit(true); + setTimeout(() => inputRef.current?.focus(), 0); + }} +> + Edit + + +// In Edit mode + + setIsEdit(true)} + placeholder="i.e. blue, green, etc." + isClearable + isClearableCallback={() => setValue("")} + value={value} + onChange={(e) => setValue(e.target.value)} +/> +`} language="jsx" /> + + + ## Number Type The `TextInput` component can be configured to render a number input by setting diff --git a/src/components/TextInput/TextInput.stories.tsx b/src/components/TextInput/TextInput.stories.tsx index 8c359f99b..d1506a32c 100644 --- a/src/components/TextInput/TextInput.stories.tsx +++ b/src/components/TextInput/TextInput.stories.tsx @@ -1,13 +1,15 @@ -import { Box, VStack } from "@chakra-ui/react"; +import { Box, VStack, HStack } from "@chakra-ui/react"; import type { Meta, StoryObj } from "@storybook/react"; import { expect, userEvent, waitFor, within } from "@storybook/test"; -import { useState } from "react"; +import { useState, useRef } from "react"; +import Button from "../Button/Button"; import Heading from "../Heading/Heading"; import TextInput, { autoCompleteValuesArray, textInputTypesArray, } from "./TextInput"; +import type { TextInputRefType } from "./TextInput"; import { argsBooleanType } from "../../helpers/storybookUtils"; const meta: Meta = { @@ -292,6 +294,54 @@ export const HTMLHelperText: Story = { name: "HTML in Helper Text", }; +const FocusManagementComponent = () => { + const [isEdit, setIsEdit] = useState(false); + const [value, setValue] = useState(""); + const inputRef = useRef(null); + const editBtnRef = useRef(null); + + return !isEdit ? ( + + ) : ( + + setIsEdit(true)} + placeholder="i.e. blue, green, etc." + isClearable + isClearableCallback={() => setValue("")} + value={value} + onChange={(e) => setValue(e.target.value)} + /> + + + ); +}; + +export const FocusRefManagement: Story = { + render: () => , + name: "Focus Ref Management", +}; + export const Textarea: Story = { args: { additionalHelperTextIds: undefined, diff --git a/src/components/TextInput/TextInput.tsx b/src/components/TextInput/TextInput.tsx index d248a0e24..8444444e0 100644 --- a/src/components/TextInput/TextInput.tsx +++ b/src/components/TextInput/TextInput.tsx @@ -291,7 +291,7 @@ export const TextInput: ChakraComponent< setFinalValue(""); isClearableCallback && isClearableCallback(); // Set focus back to the input element. - (finalRef as any).current.focus(); + (closedRef as any).current.focus(); }; let finalIsInvalid = isInvalid; let fieldOutput; diff --git a/src/components/TextInput/textInputChangelogData.ts b/src/components/TextInput/textInputChangelogData.ts index 2bf61f013..46e524c28 100644 --- a/src/components/TextInput/textInputChangelogData.ts +++ b/src/components/TextInput/textInputChangelogData.ts @@ -9,6 +9,13 @@ import { ChangelogData } from "../../utils/ComponentChangelogTable"; export const changelogData: ChangelogData[] = [ + { + date: "Prerelease", + version: "Prerelease", + type: "Bug Fix", + affects: ["Functionality", "Accessibility"], + notes: ["Fixes conflicting internal and external ref props and values."], + }, { date: "2024-09-19", version: "3.3.2",