From fc9a2213715a8aa5eed3406fc3ca944b05b0bf66 Mon Sep 17 00:00:00 2001 From: Kerry Date: Fri, 18 Feb 2022 17:35:08 +0100 Subject: [PATCH] Focus trap in poll creation dialog (#7847) * add autofocus Signed-off-by: Kerry Archibald * test Signed-off-by: Kerry Archibald * scope ids Signed-off-by: Kerry Archibald * whitespace Signed-off-by: Kerry Archibald --- .../views/elements/PollCreateDialog.tsx | 16 ++++++++++++- .../views/elements/PollCreateDialog-test.tsx | 23 +++++++++++++++++++ .../PollCreateDialog-test.tsx.snap | 6 ++--- 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/components/views/elements/PollCreateDialog.tsx b/src/components/views/elements/PollCreateDialog.tsx index 87e9a06fb9..a68b5aa495 100644 --- a/src/components/views/elements/PollCreateDialog.tsx +++ b/src/components/views/elements/PollCreateDialog.tsx @@ -35,10 +35,15 @@ interface IProps extends IDialogProps { editingMxEvent?: MatrixEvent; // Truthy if we are editing an existing poll } +enum FocusTarget { + Topic, + NewOption, +} interface IState extends IScrollableBaseState { question: string; options: string[]; busy: boolean; + autoFocusTarget: FocusTarget; } const MIN_OPTIONS = 2; @@ -55,6 +60,7 @@ function creatingInitialState(): IState { question: "", options: arraySeed("", DEFAULT_NUM_OPTIONS), busy: false, + autoFocusTarget: FocusTarget.Topic, }; } @@ -69,6 +75,7 @@ function editingInitialState(editingMxEvent: MatrixEvent): IState { question: poll.question.text, options: poll.answers.map(ans => ans.text), busy: false, + autoFocusTarget: FocusTarget.Topic, }; } @@ -113,7 +120,7 @@ export default class PollCreateDialog extends ScrollableBaseModal { const newOptions = arrayFastClone(this.state.options); newOptions.push(""); - this.setState({ options: newOptions }, () => { + this.setState({ options: newOptions, autoFocusTarget: FocusTarget.NewOption }, () => { // Scroll the button into view after the state update to ensure we don't experience // a pop-in effect, and to avoid the button getting cut off due to a mid-scroll render. this.addOptionRef.current?.scrollIntoView?.(); @@ -185,6 +192,7 @@ export default class PollCreateDialog extends ScrollableBaseModal

{ _t("What is your poll question or topic?") }

{ _t("Create options") }

{ this.state.options.map((op, i) =>
this.onOptionRemove(i)} diff --git a/test/components/views/elements/PollCreateDialog-test.tsx b/test/components/views/elements/PollCreateDialog-test.tsx index f8b99ca130..41af027a98 100644 --- a/test/components/views/elements/PollCreateDialog-test.tsx +++ b/test/components/views/elements/PollCreateDialog-test.tsx @@ -33,6 +33,9 @@ const realDateToISOString = Date.prototype.toISOString; Date.now = jest.fn(() => 2345678901234); // eslint-disable-next-line no-extend-native Date.prototype.toISOString = jest.fn(() => "2021-11-23T14:35:14.240Z"); + +const findById = (component, id) => component.find(`[id="${id}"]`); + afterAll(() => { Date.now = realDateNow; // eslint-disable-next-line no-extend-native @@ -47,6 +50,26 @@ describe("PollCreateDialog", () => { expect(dialog.html()).toMatchSnapshot(); }); + it("autofocuses the poll topic on mount", () => { + const dialog = mount( + , + ); + expect(findById(dialog, 'poll-topic-input').at(0).props().autoFocus).toEqual(true); + }); + + it("autofocuses the new poll option field after clicking add option button", () => { + const dialog = mount( + , + ); + expect(findById(dialog, 'poll-topic-input').at(0).props().autoFocus).toEqual(true); + + dialog.find("div.mx_PollCreateDialog_addOption").simulate("click"); + + expect(findById(dialog, 'poll-topic-input').at(0).props().autoFocus).toEqual(false); + expect(findById(dialog, 'pollcreate_option_1').at(0).props().autoFocus).toEqual(false); + expect(findById(dialog, 'pollcreate_option_2').at(0).props().autoFocus).toEqual(true); + }); + it("renders a question and some options", () => { const dialog = mount( , diff --git a/test/components/views/elements/__snapshots__/PollCreateDialog-test.tsx.snap b/test/components/views/elements/__snapshots__/PollCreateDialog-test.tsx.snap index f302810c3b..ac05f9479f 100644 --- a/test/components/views/elements/__snapshots__/PollCreateDialog-test.tsx.snap +++ b/test/components/views/elements/__snapshots__/PollCreateDialog-test.tsx.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PollCreateDialog renders a blank poll 1`] = `"

Create poll

What is your poll question or topic?

Create options

Add option
Cancel
"`; +exports[`PollCreateDialog renders a blank poll 1`] = `"

Create poll

What is your poll question or topic?

Create options

Add option
Cancel
"`; -exports[`PollCreateDialog renders a question and some options 1`] = `"

Create poll

What is your poll question or topic?

Create options

Add option
Cancel
"`; +exports[`PollCreateDialog renders a question and some options 1`] = `"

Create poll

What is your poll question or topic?

Create options

Add option
Cancel
"`; -exports[`PollCreateDialog renders info from a previous event 1`] = `"

Edit poll

What is your poll question or topic?

Create options

Add option
Cancel
"`; +exports[`PollCreateDialog renders info from a previous event 1`] = `"

Edit poll

What is your poll question or topic?

Create options

Add option
Cancel
"`;