Skip to content

Commit

Permalink
Merge pull request #2923 from bryceosterhaus/2910
Browse files Browse the repository at this point in the history
feat(@clayui/drop-down): add ability to add attributes to form element
  • Loading branch information
bryceosterhaus authored Feb 12, 2020
2 parents 3ef2e28 + 06661e9 commit 4a86bc0
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 21 deletions.
7 changes: 5 additions & 2 deletions packages/clay-drop-down/src/DropDownWithItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,12 @@ export interface IProps extends IDropDownContentProps {
searchable?: boolean;

/**
* Pass the props to ClayInput.
* Pass the props to the Search component.
*/
searchProps?: React.ComponentProps<typeof Search>;
searchProps?: Omit<
React.ComponentProps<typeof Search>,
'onChange' | 'spritemap' | 'value'
>;

/**
* The value that will be passed to the search input element.
Expand Down
51 changes: 34 additions & 17 deletions packages/clay-drop-down/src/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,15 @@
import ClayButton from '@clayui/button';
import {ClayInput} from '@clayui/form';
import ClayIcon from '@clayui/icon';
import classNames from 'classnames';
import React from 'react';

interface IProps extends React.HTMLAttributes<HTMLInputElement> {
/**
* Props to add to form element
*/
formProps?: React.HTMLAttributes<HTMLFormElement>;

/**
* Callback for when input value changes.
*/
Expand All @@ -28,24 +34,35 @@ interface IProps extends React.HTMLAttributes<HTMLInputElement> {

const ClayDropDownSearch: React.FunctionComponent<IProps> = ({
className,
formProps = {},
spritemap,
...otherProps
}: IProps) => (
<form className={className}>
<div className="dropdown-section">
<ClayInput.Group small>
<ClayInput.GroupItem>
<ClayInput {...otherProps} insetAfter type="text" />

<ClayInput.GroupInsetItem after tag="span">
<ClayButton displayType="unstyled" type="button">
<ClayIcon spritemap={spritemap} symbol="search" />
</ClayButton>
</ClayInput.GroupInsetItem>
</ClayInput.GroupItem>
</ClayInput.Group>
</div>
</form>
);
}: IProps) => {
const {className: formClassName, ...otherFormProps} = formProps;

return (
<form
className={classNames(className, formClassName)}
{...otherFormProps}
>
<div className="dropdown-section">
<ClayInput.Group small>
<ClayInput.GroupItem>
<ClayInput {...otherProps} insetAfter type="text" />

<ClayInput.GroupInsetItem after tag="span">
<ClayButton displayType="unstyled" type="button">
<ClayIcon
spritemap={spritemap}
symbol="search"
/>
</ClayButton>
</ClayInput.GroupInsetItem>
</ClayInput.GroupItem>
</ClayInput.Group>
</div>
</form>
);
};

export default ClayDropDownSearch;
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,9 @@ exports[`ClayDropDownWithItems renders a DropDownWithItems with search 1`] = `
class="dropdown-menu"
style="left: -999px; top: -995px;"
>
<form>
<form
class=""
>
<div
class="dropdown-section"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,9 @@ exports[`ClayDropDown renders with search input 1`] = `
class="dropdown-menu show"
style="left: -999px; top: -995px;"
>
<form>
<form
class=""
>
<div
class="dropdown-section"
>
Expand Down
25 changes: 25 additions & 0 deletions packages/clay-drop-down/src/__tests__/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -303,4 +303,29 @@ describe('ClayDropDown', () => {

expect(onClickFn).toHaveBeenCalled();
});

it('prevents form submission', () => {
const onSubmitFn = jest.fn();

const {container} = render(
<DropDownWithState>
<ClayDropDown.Search
formProps={{onSubmit: onSubmitFn}}
onChange={() => {}}
spritemap="/foo/bar"
value="test"
/>
</DropDownWithState>
);

const toggleButton = container.querySelector('.dropdown-toggle');

fireEvent.click(toggleButton as HTMLButtonElement, {});

const input = document.querySelector('input');

fireEvent.submit(input as HTMLInputElement, {});

expect(onSubmitFn).toHaveBeenCalled();
});
});
41 changes: 41 additions & 0 deletions packages/clay-drop-down/stories/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,39 @@ storiesOf('Components|ClayDropDown', module)
</ClayDropDown.ItemList>
</DropDownWithState>
))
.add('search', () => {
const [query, setQuery] = React.useState('');

return (
<DropDownWithState>
<ClayDropDown.Search
formProps={{onSubmit: e => e.preventDefault()}}
onChange={event => setQuery(event.target.value)}
spritemap={spritemap}
value={query}
/>

<ClayDropDown.ItemList>
{[
{href: '#one', label: 'one'},
{href: '#two', label: 'two'},
{disabled: true, href: '#three', label: 'three'},
{href: '#four', label: 'four'},
]
.filter(({label}) => label.match(query))
.map(({href, label, ...otherProps}, i) => (
<ClayDropDown.Item
href={href}
key={i}
{...otherProps}
>
{label}
</ClayDropDown.Item>
))}
</ClayDropDown.ItemList>
</DropDownWithState>
);
})
.add('radio', () => (
<DropDownWithState>
<ClayDropDown.ItemList>
Expand Down Expand Up @@ -227,6 +260,14 @@ storiesOf('Components|ClayDropDown', module)
helpText="You can customize this menu or see all you have by pressing 'more'."
items={items}
onSearchValueChange={setValue}
searchProps={{
formProps: {
onSubmit: e => {
e.preventDefault();
alert('Submitted!');
},
},
}}
searchValue={value}
searchable={boolean('Searchable', true)}
spritemap={spritemap}
Expand Down

0 comments on commit 4a86bc0

Please sign in to comment.