Skip to content

Commit d5abc76

Browse files
committed
wrapped up search component
1 parent d5fca12 commit d5abc76

File tree

5 files changed

+219
-14
lines changed

5 files changed

+219
-14
lines changed

src/components/Search/index.scss

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,17 @@ $baseClass: 'vant-search';
2020

2121
&__round {
2222
.vant-field {
23-
border-radius: 2px;
23+
border-radius: 999px;
24+
}
25+
}
26+
27+
&__showAction {
28+
padding-right: 0;
29+
}
30+
31+
&__leftIcon {
32+
.vant-field__error {
33+
padding-left: 24px;
2434
}
2535
}
2636

@@ -44,4 +54,27 @@ $baseClass: 'vant-search';
4454
}
4555
}
4656
}
57+
58+
&__action {
59+
padding: 0 $space-md;
60+
cursor: pointer;
61+
62+
button {
63+
min-height: 34px;
64+
}
65+
66+
.#{$baseClass}__cancel {
67+
@include search-action;
68+
cursor: pointer;
69+
background-color: $default;
70+
border: 0;
71+
padding: 0;
72+
}
73+
}
74+
75+
&__disabled {
76+
input {
77+
cursor: not-allowed;
78+
}
79+
}
4780
}
Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,105 @@
1-
import React from 'react';
1+
import React, { useState } from 'react';
22
import Search from '.';
33
import '../../styles/stories.scss';
4+
import Button from '../Button';
45

56
export default {
67
title: 'Search',
78
component: Search
89
};
910

1011
export const BasicUsage = () => (
11-
<div className='container grey'>
12+
<div className='container column grey'>
1213
<Search />
14+
<Search shape='round' />
15+
</div>
16+
);
17+
18+
export const CustomLabel = () => (
19+
<div className='container column grey'>
20+
<Search
21+
placeholder='Label width of 65px'
22+
label='Address'
23+
labelWidth='65px'
24+
/>
25+
<Search label='Address' labelAlign='center' />
26+
<Search label='Address' labelAlign='right' />
27+
</div>
28+
);
29+
30+
export const BackgroundColor = () => (
31+
<div className='container grey'>
32+
<Search background='rgb(79, 192, 141)' />
33+
</div>
34+
);
35+
36+
export const MaxLength = () => (
37+
<div className='container grey'>
38+
<Search maxLength={5} />
39+
</div>
40+
);
41+
42+
export const PlaceholderAutoFocus = () => (
43+
<div className='container grey column'>
44+
<Search placeholder='This is a placeholder' />
45+
<Search placeholder='This is a auto focus' autofocus />
46+
</div>
47+
);
48+
49+
export const SearchActions = () => {
50+
const handleClick = (e) => {
51+
e.preventDefault();
52+
alert('Action clicked');
53+
};
54+
const [value, setValue] = useState('');
55+
const [focus, setFocus] = useState(false);
56+
return (
57+
<div className='container column grey'>
58+
<h1>Value: {value}</h1>
59+
<Search cancel={handleClick} showAction />
60+
<Search cancel={handleClick} showAction actionText='Clear' />
61+
<Search
62+
showAction
63+
action={
64+
<Button
65+
click={handleClick}
66+
text='Action'
67+
type='primary'
68+
size='small'
69+
block
70+
/>
71+
}
72+
/>
73+
<Search
74+
placeholder='Search Action, press Enter to search'
75+
search={() => alert('Searched')}
76+
/>
77+
78+
<Search
79+
rightIcon={focus ? 'success' : 'cross'}
80+
clearable={false}
81+
placeholder='Focus blur and input actions'
82+
input={(e) => setValue(e.target.value)}
83+
focus={() => setFocus(true)}
84+
blur={() => setFocus(false)}
85+
/>
86+
</div>
87+
);
88+
};
89+
90+
export const DisabledReadonlyError = () => (
91+
<div className='container column grey'>
92+
<Search disabled />
93+
<Search readonly />
94+
<Search error errorMessage='Something is up' />
95+
</div>
96+
);
97+
98+
export const AlignmentAndIcon = () => (
99+
<div className='container column grey'>
100+
<Search inputAlign='center' placeholder='This is a placeholder' />
101+
<Search inputAlign='right' placeholder='This is a placeholder' />
102+
<Search leftIcon='smile-o' />
103+
<Search leftIcon='' rightIcon='search' clearable={false} />
13104
</div>
14105
);

src/components/Search/index.tsx

Lines changed: 79 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,38 +17,108 @@ const Search = ({
1717
maxLength,
1818
placeholder,
1919
clearable = true,
20-
autoFocus,
20+
autofocus,
2121
showAction,
2222
disabled,
2323
readonly,
2424
error,
2525
inputAlign = 'left',
2626
leftIcon = 'search',
2727
rightIcon,
28-
actionText,
28+
actionText = 'Cancel',
2929
search,
3030
input,
31-
foucs,
31+
focus,
3232
blur,
3333
clear,
34-
cancel
34+
cancel,
35+
action,
36+
errorMessage,
37+
labelAlign,
38+
labelWidth
3539
}: IProps) => {
3640
const [value, setValue] = useState('');
3741

42+
const handleSearch = (e) => {
43+
e.preventDefault();
44+
if (search) search(e);
45+
};
46+
const handleActionClick = (e) => {
47+
e.preventDefault();
48+
if (cancel) cancel(e);
49+
};
50+
51+
const handleInput = (e) => {
52+
if (input) input(e);
53+
setValue(e.target.value);
54+
};
55+
56+
const handleFocus = (e) => {
57+
if (focus) focus(e);
58+
};
59+
60+
const handleBlur = (e) => {
61+
if (focus) blur(e);
62+
};
63+
64+
const handleClear = (e) => {
65+
e.preventDefault();
66+
if (clear) {
67+
clear(e);
68+
}
69+
setValue('');
70+
};
71+
3872
const searchProps = {
39-
className: classnames(baseClass, [{ label }, { shape }])
73+
className: classnames(baseClass, [
74+
{ label },
75+
{ [shape]: shape },
76+
{ disabled },
77+
{ showAction },
78+
{ leftIcon }
79+
]),
80+
style: {},
81+
onSubmit: handleSearch
4082
};
41-
const ICON_SIZE = '16px';
83+
84+
if (background)
85+
Object.assign(searchProps, { style: { backgroundColor: background } });
86+
4287
return (
4388
<form {...searchProps}>
44-
{/* <Icon name='search' size={ICON_SIZE} /> */}
4589
<Field
4690
value={value}
47-
input={(e) => setValue(e.target.value)}
91+
label={label}
92+
labelAlign={labelAlign}
93+
labelWidth={labelWidth}
94+
input={handleInput}
95+
blur={handleBlur}
96+
focus={handleFocus}
97+
clear={handleClear}
4898
clearable={clearable}
49-
clear={() => setValue('')}
5099
leftIcon={leftIcon}
100+
maxLength={maxLength}
101+
placeholder={placeholder}
102+
autofocus={autofocus}
103+
readonly={readonly}
104+
disabled={disabled}
105+
error={error}
106+
errorMessage={errorMessage}
107+
inputAlign={inputAlign}
108+
rightIcon={rightIcon}
51109
/>
110+
{showAction && (
111+
<div className={`${baseClass}__action`}>
112+
{action || (
113+
<button
114+
onClick={handleActionClick}
115+
className={`${baseClass}__cancel`}
116+
>
117+
{actionText}
118+
</button>
119+
)}
120+
</div>
121+
)}
52122
</form>
53123
);
54124
};

src/components/Search/types.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1+
import { ReactElement } from 'react';
12
import { TAlignment } from '../Field/types';
23

34
export interface IProps {
45
label?: string;
6+
labelWidth?: string;
7+
labelAlign?: TAlignment;
58
shape?: 'round' | 'square';
69
background?: string;
710
maxLength?: number;
811
placeholder?: string;
12+
errorMessage?: string;
913
clearable?: boolean;
10-
autoFocus?: boolean;
14+
autofocus?: boolean;
1115
showAction?: boolean;
1216
disabled?: boolean;
1317
readonly?: boolean;
@@ -18,8 +22,9 @@ export interface IProps {
1822
actionText?: string;
1923
search?: Function;
2024
input?: Function;
21-
foucs?: Function;
25+
focus?: Function;
2226
blur?: Function;
2327
clear?: Function;
2428
cancel?: Function;
29+
action?: ReactElement;
2530
}

src/styles/typography.scss

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,9 @@
3131
color: $dark-text;
3232
font-weight: 300;
3333
}
34+
35+
@mixin search-action {
36+
font-size: 14px;
37+
line-height: 34px;
38+
font-weight: 300;
39+
}

0 commit comments

Comments
 (0)