+
window.alert(e.target)} />
);
diff --git a/src/components/Search/index.scss b/src/components/Search/index.scss
new file mode 100644
index 000000000..51c39b686
--- /dev/null
+++ b/src/components/Search/index.scss
@@ -0,0 +1,80 @@
+@import '../../styles/colors.scss';
+@import '../../styles/spacing.scss';
+@import '../../styles/variables.scss';
+@import '../../styles/typography.scss';
+
+$baseClass: 'vant-search';
+
+.#{$baseClass} {
+ background-color: $default;
+ width: 100%;
+ display: flex;
+ padding: 10px 12px;
+ position: relative;
+ align-items: center;
+
+ &:first-of-type(i) {
+ position: absolute;
+ left: 8px;
+ }
+
+ &__round {
+ .vant-field {
+ border-radius: 999px;
+ }
+ }
+
+ &__showAction {
+ padding-right: 0;
+ }
+
+ &__leftIcon {
+ .vant-field__error {
+ padding-left: 24px;
+ }
+ }
+
+ .vant-field {
+ background-color: $grey-background;
+ padding: 0 0 0 8px;
+
+ .vant-field__input {
+ padding: 5px 8px 5px 0;
+
+ .vant-icon__container {
+ padding: 0;
+ }
+
+ input {
+ width: 100%;
+ background-color: $grey-background;
+ border: none;
+ border-radius: 2px;
+ padding-left: $space-md;
+ }
+ }
+ }
+
+ &__action {
+ padding: 0 $space-md;
+ cursor: pointer;
+
+ button {
+ min-height: 34px;
+ }
+
+ .#{$baseClass}__cancel {
+ @include search-action;
+ cursor: pointer;
+ background-color: $default;
+ border: 0;
+ padding: 0;
+ }
+ }
+
+ &__disabled {
+ input {
+ cursor: not-allowed;
+ }
+ }
+}
diff --git a/src/components/Search/index.stories.tsx b/src/components/Search/index.stories.tsx
new file mode 100644
index 000000000..98e58dcfc
--- /dev/null
+++ b/src/components/Search/index.stories.tsx
@@ -0,0 +1,105 @@
+import React, { useState } from 'react';
+import Search from '.';
+import '../../styles/stories.scss';
+import Button from '../Button';
+
+export default {
+ title: 'Search',
+ component: Search
+};
+
+export const BasicUsage = () => (
+
+
+
+
+);
+
+export const CustomLabel = () => (
+
+
+
+
+
+);
+
+export const BackgroundColor = () => (
+
+
+
+);
+
+export const MaxLength = () => (
+
+
+
+);
+
+export const PlaceholderAutoFocus = () => (
+
+
+
+
+);
+
+export const SearchActions = () => {
+ const handleClick = (e) => {
+ e.preventDefault();
+ alert('Action clicked');
+ };
+ const [value, setValue] = useState('');
+ const [focus, setFocus] = useState(false);
+ return (
+
+
Value: {value}
+
+
+
+ }
+ />
+ alert('Searched')}
+ />
+
+ setValue(e.target.value)}
+ focus={() => setFocus(true)}
+ blur={() => setFocus(false)}
+ />
+
+ );
+};
+
+export const DisabledReadonlyError = () => (
+
+
+
+
+
+);
+
+export const AlignmentAndIcon = () => (
+
+
+
+
+
+
+);
diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx
new file mode 100644
index 000000000..4caef6d7b
--- /dev/null
+++ b/src/components/Search/index.tsx
@@ -0,0 +1,124 @@
+import React, { useState } from 'react';
+
+import classnames from '../../utils/classNames';
+
+import './index.scss';
+import { IProps } from './types';
+import Field from '../Field';
+
+const baseClass = 'vant-search';
+
+const Search = ({
+ label,
+ shape = 'square',
+ background,
+ maxLength,
+ placeholder,
+ clearable = true,
+ autofocus,
+ showAction,
+ disabled,
+ readonly,
+ error,
+ inputAlign = 'left',
+ leftIcon = 'search',
+ rightIcon,
+ actionText = 'Cancel',
+ search,
+ input,
+ focus,
+ blur,
+ clear,
+ cancel,
+ action,
+ errorMessage,
+ labelAlign,
+ labelWidth
+}: IProps) => {
+ const [value, setValue] = useState('');
+
+ const handleSearch = (e) => {
+ e.preventDefault();
+ if (search) search(e);
+ };
+ const handleActionClick = (e) => {
+ e.preventDefault();
+ if (cancel) cancel(e);
+ };
+
+ const handleInput = (e) => {
+ if (input) input(e);
+ setValue(e.target.value);
+ };
+
+ const handleFocus = (e) => {
+ if (focus) focus(e);
+ };
+
+ const handleBlur = (e) => {
+ if (blur) blur(e);
+ };
+
+ const handleClear = (e) => {
+ e.preventDefault();
+ if (clear) {
+ clear(e);
+ }
+ setValue('');
+ };
+
+ const searchProps = {
+ className: classnames(baseClass, [
+ { label },
+ { [shape]: shape },
+ { disabled },
+ { showAction },
+ { leftIcon }
+ ]),
+ style: {},
+ onSubmit: handleSearch
+ };
+
+ if (background)
+ Object.assign(searchProps, { style: { backgroundColor: background } });
+
+ return (
+
+ );
+};
+
+export default Search;
diff --git a/src/components/Search/types.ts b/src/components/Search/types.ts
index f9f3501eb..00792a8ed 100644
--- a/src/components/Search/types.ts
+++ b/src/components/Search/types.ts
@@ -1,3 +1,30 @@
+import { ReactElement } from 'react';
+import { TAlignment } from '../Field/types';
+
export interface IProps {
label?: string;
+ labelWidth?: string;
+ labelAlign?: TAlignment;
+ shape?: 'round' | 'square';
+ background?: string;
+ maxLength?: number;
+ placeholder?: string;
+ errorMessage?: string;
+ clearable?: boolean;
+ autofocus?: boolean;
+ showAction?: boolean;
+ disabled?: boolean;
+ readonly?: boolean;
+ error?: boolean;
+ inputAlign?: TAlignment;
+ leftIcon?: string;
+ rightIcon?: string;
+ actionText?: string;
+ search?: Function;
+ input?: Function;
+ focus?: Function;
+ blur?: Function;
+ clear?: Function;
+ cancel?: Function;
+ action?: ReactElement;
}
diff --git a/src/index.tsx b/src/index.tsx
index 3748492a6..0c43765c5 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -3,19 +3,22 @@ import Icon from './components/Icons';
import Tag from './components/Tag';
import Navbar from './components/Navbar';
import Field from './components/Field';
+import Search from './components/Search';
export { default as Button } from './components/Button';
export { default as Icon } from './components/Icons';
export { default as Tag } from './components/Tag';
export { default as Navbar } from './components/Navbar';
export { default as Field } from './components/Field';
+export { default as Search } from './components/Search';
const Vant = {
Button,
Icon,
Tag,
Navbar,
- Field
+ Field,
+ Search
};
export default Vant;
diff --git a/src/styles/colors.scss b/src/styles/colors.scss
index 4492ffa39..37acfc48c 100644
--- a/src/styles/colors.scss
+++ b/src/styles/colors.scss
@@ -10,6 +10,7 @@ $grey: #969799;
$dark-text: #323233;
$light-text: #fff;
$grey-text: #ebedf0;
+$grey-background: #f7f8fa;
$placeholder: #c8c9cc;
$word-limit: #656566;
diff --git a/src/styles/stories.scss b/src/styles/stories.scss
index 20fad8484..b0f843e78 100644
--- a/src/styles/stories.scss
+++ b/src/styles/stories.scss
@@ -14,7 +14,7 @@ body {
align-items: center;
&.grey {
- background-color: #f7f8fa;
+ background-color: $grey-background;
}
&.button {
@@ -51,7 +51,7 @@ body {
padding: 15px;
display: flex;
flex-direction: column;
- background-color: #f7f8fa;
+ background-color: $grey-background;
h1 {
font-size: 22px;
diff --git a/src/styles/typography.scss b/src/styles/typography.scss
index c80daee6f..27733cb1b 100644
--- a/src/styles/typography.scss
+++ b/src/styles/typography.scss
@@ -31,3 +31,9 @@
color: $dark-text;
font-weight: 300;
}
+
+@mixin search-action {
+ font-size: 14px;
+ line-height: 34px;
+ font-weight: 300;
+}