Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Select): flag to put create option at top of typeahead #8165

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion packages/react-core/src/components/Select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ export interface SelectProps
isDisabled?: boolean;
/** Flag to indicate if the typeahead select allows new items */
isCreatable?: boolean;
/** Flag to indicate if create option should be at top of typeahead */
isCreateOptionOnTop?: boolean;
/** Flag indicating if placeholder styles should be applied */
hasPlaceholderStyle?: boolean;
/** @beta Flag indicating if the creatable option should set its value as a SelectOptionObject */
Expand Down Expand Up @@ -226,6 +228,7 @@ export class Select extends React.Component<SelectProps & OUIAProps, SelectState
isDisabled: false,
hasPlaceholderStyle: false,
isCreatable: false,
isCreateOptionOnTop: false,
validated: 'default',
'aria-label': '',
'aria-labelledby': '',
Expand Down Expand Up @@ -433,6 +436,7 @@ export class Select extends React.Component<SelectProps & OUIAProps, SelectState
const {
onFilter,
isCreatable,
isCreateOptionOnTop,
onCreateOption,
createText,
noResultsFoundText,
Expand Down Expand Up @@ -542,7 +546,7 @@ export class Select extends React.Component<SelectProps & OUIAProps, SelectState
} as SelectOptionObject)
: newValue;

typeaheadFilteredChildren.push(
const createSelectOption = (
<SelectOption
key={`create ${newValue}`}
value={newOptionValue}
Expand All @@ -551,6 +555,12 @@ export class Select extends React.Component<SelectProps & OUIAProps, SelectState
{createText} "{newValue}"
</SelectOption>
);

if (isCreateOptionOnTop) {
typeaheadFilteredChildren.unshift(createSelectOption);
} else {
typeaheadFilteredChildren.push(createSelectOption);
}
}
}

Expand Down Expand Up @@ -1020,6 +1030,7 @@ export class Select extends React.Component<SelectProps & OUIAProps, SelectState
footer,
loadingVariant,
isCreateSelectOptionObject,
isCreateOptionOnTop,
shouldResetOnSelect,
isFlipEnabled,
removeFindDomNode,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -560,3 +560,35 @@ test('applies focus styling to the create option when reached via keyboard navig

expect(createOption.parentElement).toHaveClass('pf-m-focus');
});

test('appends create option to list of options', async () => {
const user = userEvent.setup();

render(
<Select variant={SelectVariant.typeahead} onToggle={() => {}} isOpen isCreatable>
{selectOptions}
</Select>
);

const input = screen.getByRole('textbox');
await user.type(input, `m`);

const createOption = screen.getAllByRole('option')[3];
expect(createOption).toHaveTextContent('Create "m"');
});

test('prepends create option to list of options if isCreateOptionOnTop flag is set', async () => {
const user = userEvent.setup();

render(
<Select variant={SelectVariant.typeahead} onToggle={() => {}} isOpen isCreateOptionOnTop isCreatable>
{selectOptions}
</Select>
);

const input = screen.getByRole('textbox');
await user.type(input, `m`);

const createOption = screen.getAllByRole('option')[0];
expect(createOption).toHaveTextContent('Create "m"');
});
17 changes: 17 additions & 0 deletions packages/react-core/src/components/Select/examples/Select.md
Original file line number Diff line number Diff line change
Expand Up @@ -1209,6 +1209,7 @@ class TypeaheadSelectInput extends React.Component {
selected: null,
isDisabled: false,
isCreatable: false,
isCreateOptionOnTop: false,
isInputValuePersisted: false,
isInputFilterPersisted: false,
hasOnCreateOption: false,
Expand Down Expand Up @@ -1258,6 +1259,12 @@ class TypeaheadSelectInput extends React.Component {
});
};

this.toggleCreateOptionOnTop = checked => {
this.setState({
isCreateOptionOnTop: checked
});
};

this.toggleCreateNew = checked => {
this.setState({
hasOnCreateOption: checked
Expand Down Expand Up @@ -1289,6 +1296,7 @@ class TypeaheadSelectInput extends React.Component {
selected,
isDisabled,
isCreatable,
isCreateOptionOnTop,
hasOnCreateOption,
isInputValuePersisted,
isInputFilterPersisted,
Expand All @@ -1315,6 +1323,7 @@ class TypeaheadSelectInput extends React.Component {
placeholderText="Select a state"
isDisabled={isDisabled}
isCreatable={isCreatable}
isCreateOptionOnTop={isCreateOptionOnTop}
onCreateOption={(hasOnCreateOption && this.onCreateOption) || undefined}
shouldResetOnSelect={resetOnSelect}
>
Expand Down Expand Up @@ -1343,6 +1352,14 @@ class TypeaheadSelectInput extends React.Component {
id="toggle-creatable-typeahead"
name="toggle-creatable-typeahead"
/>
<Checkbox
label="isCreateOptionOnTop"
isChecked={this.state.isCreateOptionOnTop}
onChange={this.toggleCreateOptionOnTop}
aria-label="toggle createOptionOnTop checkbox"
id="toggle-create-option-on-top-typeahead"
name="toggle-create-option-on-top-typeahead"
/>
<Checkbox
label="onCreateOption"
isChecked={this.state.hasOnCreateOption}
Expand Down