Skip to content

Commit

Permalink
Remove searchfield ref, add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
kyledurand committed Mar 20, 2024
1 parent 31fc7ff commit c02e145
Show file tree
Hide file tree
Showing 15 changed files with 218 additions and 105 deletions.
22 changes: 11 additions & 11 deletions polaris-react/playground/DetailsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import {
TopBar,
FooterHelp,
Link,
Picker,
AlphaPicker,
} from '../src';
import type {DropZoneProps, PageProps} from '../src';

Expand Down Expand Up @@ -695,21 +695,21 @@ export function DetailsPage() {
value={selected}
/>
<br />
<Picker
activator={{label: 'Vendor'}}
<AlphaPicker
searchField={{
label: 'Search vendors',
placeholder: 'Search vendors',
autoComplete: 'off',
}}
activator={{
label: 'Tags',
placeholder: 'Search tags',
}}
options={[
{
value: 'Burberry',
children: 'Burberry',
},
{
value: 'Gucci',
children: 'Gucci',
},
{
value: 'Prada',
children: 'Prada',
},
]}
/>
</LegacyCard.Section>
Expand Down
73 changes: 1 addition & 72 deletions polaris-react/playground/Playground.tsx
Original file line number Diff line number Diff line change
@@ -1,82 +1,11 @@
import React from 'react';
import {PlusCircleIcon} from '@shopify/polaris-icons';

import {BlockStack, Card, Layout, Page, Picker, Text} from '../src';
import {Page} from '../src';

export function Playground() {
const [selected, setSelected] = React.useState('');
const options = [
{
value: '012345678',
children: 'Burberry',
},
{
value: '123456789',
children: 'Chanel',
},
{
value: '234567890',
children: 'Dior',
},
{
value: '345678901',
children: 'Gucci',
},
{
value: '456789012',
children: 'Hermès',
},
{
value: '567890123',
children: 'Louis Vuitton',
},
{
value: '678901234',
children: <span>Prada</span>,
},
{
value: '789012345',
children: <div>Versace</div>,
},
];

return (
<Page title="Playground">
{/* Add the code you want to test in here */}
<Layout>
<Layout.Section>
<h1>Playground</h1>
</Layout.Section>
<Layout.Section variant="oneThird">
<Card>
<BlockStack gap="200">
<Text as="h3">Organization</Text>
<Picker
searchField={{
label: 'Search for a product',
placeholder: 'Search for a product',
autoComplete: 'off',
onChange: (value) => console.log(value),
}}
activator={{
label: 'Product',
placeholder: 'Select a product',
}}
options={options}
onSelect={setSelected}
addAction={{
value: 'addy',
children: 'Add product',
icon: PlusCircleIcon,
}}
/>
<ul>
<li>Selected: {selected}</li>
</ul>
</BlockStack>
</Card>
</Layout.Section>
</Layout>
</Page>
);
}
16 changes: 8 additions & 8 deletions polaris-react/src/components/Picker/Picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {Listbox} from '../Listbox';
import type {IconProps} from '../Icon';
import {Icon} from '../Icon';

import {Activator, TextField} from './components';
import {Activator, SearchField} from './components';
import type {ActivatorProps} from './components';

export interface PickerProps extends Omit<ListboxProps, 'children'> {
Expand Down Expand Up @@ -71,7 +71,7 @@ export function Picker({
);
const [popoverActive, setPopoverActive] = useState(false);
const [activeOptionId, setActiveOptionId] = useState<string>();
const [active, setActive] = useState<string>();
const [activeItem, setActiveItem] = useState<string>();
const [textFieldLabelId, setTextFieldLabelId] = useState<string>();
const [listboxId, setListboxId] = useState<string>();
const [textFieldFocused, setTextFieldFocused] = useState<boolean>(false);
Expand All @@ -88,7 +88,7 @@ export function Picker({
}, []);

const handleSelect = useCallback((selected: string) => {
setActive(selected);
setActiveItem(selected);
}, []);

const onOptionSelected = useCallback(() => {
Expand Down Expand Up @@ -189,7 +189,7 @@ export function Picker({
);

const firstSelectedOption = reactChildrenText(
options.find((option) => option.value === active)?.children,
options.find((option) => option.value === activeItem)?.children,
);
const firstSelectedLabel = firstSelectedOption
? firstSelectedOption?.toString()
Expand Down Expand Up @@ -227,7 +227,7 @@ export function Picker({
borderColor="border"
>
<ComboboxTextFieldContext.Provider value={textFieldContextValue}>
<TextField
<SearchField
{...searchField}
value={query}
onChange={(value) => {
Expand All @@ -236,6 +236,8 @@ export function Picker({
}}
prefix={<Icon source={SearchIcon} />}
labelHidden
focused
autoFocus
/>
</ComboboxTextFieldContext.Provider>
</Box>
Expand All @@ -257,7 +259,7 @@ export function Picker({
{filteredOptions?.map((option) => (
<Listbox.Option
key={option.value}
selected={option.value === active}
selected={option.value === activeItem}
{...option}
/>
))}
Expand All @@ -280,5 +282,3 @@ const reactChildrenText = (children: React.ReactNode): string => {
? reactChildrenText(children?.props?.children)
: '';
};

Picker.TextField = TextField;
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export function Activator({
return (
<UnstyledButton
className={classNames(styles.Activator, disabled && styles.disabled)}
disabled={disabled}
onClick={onClick}
>
<BlockStack as="span" gap="100">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react';
import {mountWithApp} from 'tests/utilities';

import {Activator} from '../Activator';
import {UnstyledButton} from '../../../../UnstyledButton';

describe('<Activator />', () => {
it('renders a label', () => {
const activator = mountWithApp(<Activator label="label" />);

expect(activator).toContainReactText('label');
});

it('renders a placeholder', () => {
const activator = mountWithApp(<Activator placeholder="placeholder" />);

expect(activator).toContainReactText('placeholder');
});

it('renders a disabled activator', () => {
const activator = mountWithApp(<Activator disabled />);

expect(activator).toContainReactComponent(UnstyledButton, {disabled: true});
});
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.TextField {
.SearchField {
flex-grow: 1;
padding: var(--p-space-100) 0;
outline: none;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React, {useMemo, useId, useCallback, useEffect, useRef} from 'react';
import React, {useMemo, useId, useCallback, useEffect} from 'react';

import {Label, labelID} from '../../../Label';
import type {TextFieldProps} from '../../../TextField';
import {useComboboxTextField} from '../../../../utilities/combobox';
import {InlineStack} from '../../../InlineStack';

import styles from './TextField.module.css';
import styles from './SearchField.module.css';

export function TextField({
export function SearchField({
value,
id: idProp,
type = 'text',
Expand All @@ -18,8 +18,9 @@ export function TextField({
labelHidden,
prefix,
placeholder,
focused,
autoFocus,
}: TextFieldProps) {
const inputRef = useRef<HTMLInputElement>(null);
const comboboxTextFieldContext = useComboboxTextField();

const {
Expand Down Expand Up @@ -70,8 +71,6 @@ export function TextField({
[onChange, onTextFieldChange],
);

if (inputRef.current) inputRef.current.focus();

return (
<>
<Label id={textFieldId} hidden={labelHidden}>
Expand All @@ -80,8 +79,7 @@ export function TextField({
<InlineStack gap="100" blockAlign="center">
<span>{prefix}</span>
<input
className={styles.TextField}
ref={inputRef}
className={styles.SearchField}
value={value}
id={textFieldId}
type={type}
Expand All @@ -94,6 +92,7 @@ export function TextField({
aria-controls={listboxId}
onFocus={handleFocus}
onBlur={handleBlur}
autoFocus={focused ?? autoFocus}
onChange={({target}) => handleChange(target.value, textFieldId)}
/>
</InlineStack>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {SearchField} from './SearchField';
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import React from 'react';
import {mountWithApp} from 'tests/utilities';

import {SearchField} from '../SearchField';
import {Label} from '../../../../Label';
import type {ComboboxTextFieldType} from '../../../../../utilities/combobox';
import {ComboboxTextFieldContext} from '../../../../../utilities/combobox';
import type {TextFieldProps} from '../../../../TextField';

function mountWithProvider(
props: {
textFieldProps?: Partial<TextFieldProps>;
textFieldProviderValue?: Partial<ComboboxTextFieldType>;
} = {},
) {
const textField = mountWithApp(
<ComboboxTextFieldContext.Provider
value={{...props.textFieldProviderValue}}
>
<SearchField
label="label"
onChange={noop}
autoComplete="off"
{...props.textFieldProps}
/>
</ComboboxTextFieldContext.Provider>,
);

return textField;
}

describe('<TextField />', () => {
it('renders a label', () => {
const picker = mountWithProvider({
textFieldProps: {
label: 'Field',
},
});

expect(picker).toContainReactComponent(Label, {children: 'Field'});
});

it('renders a prefix', () => {
const picker = mountWithProvider({
textFieldProps: {
prefix: <div>Prefix</div>,
},
});

expect(picker).toContainReactComponent('div', {children: 'Prefix'});
});

it('renders accessibility attributes', () => {
const picker = mountWithProvider({
textFieldProviderValue: {
activeOptionId: 'option1',
listboxId: 'listbox1',
setTextFieldLabelId: () => 'TextFieldLabel',
},
});

expect(picker).toContainReactComponent('input', {
role: 'combobox',
'aria-activedescendant': 'option1',
'aria-haspopup': 'listbox',
'aria-autocomplete': 'list',
'aria-expanded': 'true',
'aria-controls': 'listbox1',
});
});
});

function noop() {}

This file was deleted.

2 changes: 1 addition & 1 deletion polaris-react/src/components/Picker/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export {TextField} from './TextField';
export {SearchField} from './SearchField';
export * from './Activator';
1 change: 0 additions & 1 deletion polaris-react/src/components/Picker/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export * from './Picker';
export {TextField as PickerTextField} from './components';
Loading

0 comments on commit c02e145

Please sign in to comment.