Skip to content

Commit

Permalink
Feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
nmanu1 committed Nov 24, 2021
1 parent 8d540eb commit f07ac40
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 45 deletions.
43 changes: 26 additions & 17 deletions sample-app/src/components/DropdownSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ export interface Option {
display: JSX.Element
}

interface DropdownSectionProps<T> {
export interface DropdownSectionProps {
focusStatus?: string,
options: T[],
options: Option[],
optionIdPrefix: string,
onFocusChange: (value: string, focusedOptionId: string) => void,
onFocusChange?: (value: string, focusedOptionId: string) => void,
onLeaveSectionFocus?: (focusNext: boolean) => void,
onClickOption: (option: T, optionIndex: number) => void,
onClickOption?: (option: Option, optionIndex: number) => void,
label?: string,
cssClasses: {
sectionContainer: string,
Expand All @@ -23,29 +23,38 @@ interface DropdownSectionProps<T> {
}
}

export default function DropdownSection<T extends Option>({
export default function DropdownSection({
focusStatus,
options,
optionIdPrefix,
onFocusChange,
onFocusChange = () => {},
onLeaveSectionFocus = () => {},
onClickOption,
onClickOption = () => {},
label = '',
cssClasses
}: DropdownSectionProps<T>): JSX.Element | null {
}: DropdownSectionProps): JSX.Element | null {

const [focusedOptionIndex, setFocusedOptionIndex] = useState<number>(0);

function changeOptionFocus(focusNext: boolean) {
let newIndex = focusNext ? focusedOptionIndex + 1 : focusedOptionIndex - 1;

if (newIndex > -1 && newIndex < options.length) {
function incrementOptionFocus() {
let newIndex = focusedOptionIndex + 1;
if (newIndex < options.length) {
onFocusChange(options[newIndex].value, `${optionIdPrefix}-${newIndex}`);
} else {
focusNext ? onLeaveSectionFocus(true) : onLeaveSectionFocus(false);
newIndex = newIndex === -1 ? 0 : options.length - 1;
onLeaveSectionFocus(true);
newIndex = options.length - 1;
}
setFocusedOptionIndex(newIndex);
}

function decrementOptionFocus() {
let newIndex = focusedOptionIndex - 1;
if (newIndex > -1) {
onFocusChange(options[newIndex].value, `${optionIdPrefix}-${newIndex}`);
} else {
onLeaveSectionFocus(false);
newIndex = 0;
}
setFocusedOptionIndex(newIndex);
}

Expand All @@ -56,9 +65,9 @@ export default function DropdownSection<T extends Option>({
}

if (evt.key === 'ArrowDown' || evt.key === 'ArrowRight') {
changeOptionFocus(true);
incrementOptionFocus();
} else if (evt.key === 'ArrowUp' || evt.key === 'ArrowLeft') {
changeOptionFocus(false);
decrementOptionFocus();
}
}
}
Expand All @@ -78,7 +87,7 @@ export default function DropdownSection<T extends Option>({
}
});

function renderOption(option: T, index: number) {
function renderOption(option: Option, index: number) {
const className = classNames(cssClasses.option, {
[cssClasses.focusedOption]: focusStatus === 'active' && index === focusedOptionIndex
})
Expand Down
46 changes: 22 additions & 24 deletions sample-app/src/components/InputDropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useReducer, KeyboardEvent, useRef, useEffect, useState } from "react"
import DropdownSection, { Option } from "./DropdownSection";
import ScreenReader from "./ScreenReader";

interface Props {
Expand Down Expand Up @@ -76,24 +77,26 @@ export default function InputDropdown({

const childrenArray = React.Children.toArray(children);
const childrenWithProps = childrenArray.map((child, index) => {
if (!React.isValidElement(child)) {
if (!(React.isValidElement(child) && child.type === DropdownSection)) {
return child;
}

const modifiedOnClickOption : typeof child.props.onClickOption = (option: typeof child.props.options[0]) => {
child.props.onClickOption(option);
const modifiedOnClickOption = (option: Option, optionIndex: number) => {
child.props.onClickOption?.(option, optionIndex);
dispatch({ type: 'HideSections' });
}

const modifiedOnFocusChange = (value: string, focusedOptionId: string) => {
child.props.onFocusChange(value);
child.props.onFocusChange?.(value, focusedOptionId);
setFocusedOptionId(focusedOptionId);
};

if (focusedSectionIndex === undefined) {
return React.cloneElement(child, { onLeaveSectionFocus, focusStatus: 'reset', onClickOption: modifiedOnClickOption });
} else if (index === focusedSectionIndex) {
return React.cloneElement(child, { onLeaveSectionFocus, focusStatus: 'active', onFocusChange: modifiedOnFocusChange, onClickOption: modifiedOnClickOption });
return React.cloneElement(child, {
onLeaveSectionFocus, focusStatus: 'active', onFocusChange: modifiedOnFocusChange, onClickOption: modifiedOnClickOption
});
} else {
return React.cloneElement(child, { onLeaveSectionFocus, focusStatus: 'inactive', onClickOption: modifiedOnClickOption });
}
Expand All @@ -104,32 +107,36 @@ export default function InputDropdown({
function onLeaveSectionFocus(focusNext: boolean) {
if (focusedSectionIndex === undefined && focusNext) {
dispatch({ type: 'FocusSection', newIndex: 0 });
} else if (focusedSectionIndex !== undefined && focusedSectionIndex < numSections - 1) {
let newSectionIndex: number | undefined = focusNext ? focusedSectionIndex + 1 : focusedSectionIndex - 1;
} else if (focusedSectionIndex !== undefined) {
let newSectionIndex: number | undefined = focusNext
? focusedSectionIndex + 1
: focusedSectionIndex - 1;
if (newSectionIndex < 0) {
newSectionIndex = undefined;
onInputChange(latestUserInput);
}
dispatch({ type: 'FocusSection', newIndex: newSectionIndex });
} else if (focusedSectionIndex === numSections - 1 && !focusNext) {
let newSectionIndex: number | undefined = focusedSectionIndex - 1;
if (newSectionIndex < 0) {
newSectionIndex = undefined;
} else if (newSectionIndex > numSections - 1) {
newSectionIndex = numSections - 1;
}
dispatch({ type: 'FocusSection', newIndex: newSectionIndex });
}
}

function handleDocumentClick(evt: MouseEvent) {
const target = evt.target as HTMLElement;
if (!(target.isSameNode(inputRef.current) || (dropdownRef.current !== null && dropdownRef.current.contains(target)))) {
if (!(target.isSameNode(inputRef.current) || (dropdownRef.current?.contains(target)))) {
dispatch({ type: 'HideSections' });
}
}

function handleDocumentKeydown(evt: globalThis.KeyboardEvent) {
if ((evt.key === 'Escape' || evt.key === 'Tab')) {
if (['ArrowDown'].includes(evt.key)) {
evt.preventDefault();
}

if (evt.key === 'Escape' || evt.key === 'Tab') {
dispatch({ type: 'HideSections' });
} else if (evt.key === 'ArrowDown' && numSections > 0 && focusedSectionIndex === undefined) {
dispatch({ type: 'FocusSection', newIndex: 0 });
}
}

Expand All @@ -145,22 +152,13 @@ export default function InputDropdown({
});

function onKeyDown(evt: KeyboardEvent<HTMLInputElement>) {
if (['ArrowDown', 'ArrowRight'].includes(evt.key)) {
evt.preventDefault();
}

if (evt.key === 'Enter') {
onInputChange(inputValue);
onSubmit(inputValue);
dispatch({ type: 'HideSections' });
} else if ((evt.key === 'ArrowDown' || evt.key === 'ArrowRight' ) && numSections > 0 && focusedSectionIndex === undefined) {
dispatch({ type: 'FocusSection', newIndex: 0 });
}
}

console.log(numSections);
console.log(focusedSectionIndex);

return (
<>
<div className={cssClasses.inputContainer}>
Expand Down
8 changes: 4 additions & 4 deletions sample-app/src/components/SearchBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import '../sass/SearchBar.scss';
import '../sass/Autocomplete.scss';
import LoadingIndicator from './LoadingIndicator';
import { useAutocomplete } from '../hooks/useAutocomplete';
import DropdownSection, { Option } from './DropdownSection';
import DropdownSection from './DropdownSection';
import { processTranslation } from './utils/processTranslation';
import { useRef } from 'react';
import { AutocompleteResponse, SearchIntent } from '@yext/answers-headless';
Expand Down Expand Up @@ -85,7 +85,7 @@ export default function SearchBar({
screenReaderInstructionsId={screenReaderInstructionsId}
screenReaderText={screenReaderText}
onSubmit={executeQuery}
onInputChange={(value) => {
onInputChange={value => {
answersActions.setQuery(value);
}}
onInputFocus={() => {
Expand All @@ -100,9 +100,9 @@ export default function SearchBar({
>
{
options.length > 0 &&
<DropdownSection<Option>
<DropdownSection
options={options}
optionIdPrefix={`Autocomplete__option-${0}`}
optionIdPrefix={'Autocomplete__option-0'}
onFocusChange={(value) => {
answersActions.setQuery(value);
}}
Expand Down

0 comments on commit f07ac40

Please sign in to comment.