├── .gitignore
├── assets
└── demo
│ ├── ios.gif
│ ├── web.gif
│ ├── android.gif
│ └── qr_code.png
├── LICENSE.md
├── package.json
├── README.md
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/assets/demo/ios.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gurayyarar/React-Native-Animated-Searchbox/HEAD/assets/demo/ios.gif
--------------------------------------------------------------------------------
/assets/demo/web.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gurayyarar/React-Native-Animated-Searchbox/HEAD/assets/demo/web.gif
--------------------------------------------------------------------------------
/assets/demo/android.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gurayyarar/React-Native-Animated-Searchbox/HEAD/assets/demo/android.gif
--------------------------------------------------------------------------------
/assets/demo/qr_code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gurayyarar/React-Native-Animated-Searchbox/HEAD/assets/demo/qr_code.png
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright (c) 2020 Güray Yarar
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 |
6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 |
8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-animated-searchbox",
3 | "version": "0.0.1",
4 | "description": "A simple search box with animation. Compatible with Expo CLI and React Native CLI.",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/gurayyarar/React-Native-Animated-Searchbox.git"
12 | },
13 | "keywords": [
14 | "react-native",
15 | "react-native-component",
16 | "react-native-searchbox",
17 | "react-component",
18 | "ios",
19 | "android",
20 | "web"
21 | ],
22 | "author": "gurayyarar",
23 | "license": "MIT",
24 | "bugs": {
25 | "url": "https://github.com/gurayyarar/React-Native-Animated-Searchbox/issues"
26 | },
27 | "homepage": "https://github.com/gurayyarar/React-Native-Animated-Searchbox#readme",
28 | "dependencies": {
29 | "prop-types": "^15.7.2"
30 | },
31 | "peerDependencies": {
32 | "react-native": ">=0.20.0",
33 | "prop-types": "^15.5.7"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Native - Animated Searchbox
2 | A simple search box with animation. Compatible with Expo CLI and React Native CLI.
3 |
4 | * Easy to use,
5 | * Lightweight, fast, flexible and easy customizable,
6 | * Support both IOS & Android Devices,
7 | * Also Support React Native Web
8 |
9 |
10 | ## Install
11 | We used a search SVG icon in this project.
12 | So, you need to install the [React Native SVG](https://github.com/react-native-community/react-native-svg#installation) library before continue the installation.
13 |
14 | After that;
15 |
16 | ```
17 | npm install react-native-animated-searchbox --save
18 |
19 | //or
20 |
21 | yarn add react-native-animated-searchbox
22 | ```
23 |
24 | ## Demo
25 | #### SNACK EXPO IO
26 | [https://snack.expo.io/@gurayyarar/react-native---animated-searchbox](https://snack.expo.io/@gurayyarar/react-native---animated-searchbox)
27 |
28 | #### EXPO APP ON ANDROID
29 | 
30 |
31 |
32 | #### AS GIF (FOR QUICK CHECK)
33 |
34 | |IOS|ANDROID|WEB|
35 | |---|-------|---|
36 | ||||
37 |
38 |
39 | ## Usage
40 | ```
41 | //Call for the open
42 | openSearchBox = () => this.refSearchBox.open();
43 |
44 | //Call for the close
45 | closeSearchBox = () => this.refSearchBox.close();
46 |
47 | render() {
48 | return (
49 |
50 |
51 | this.refSearchBox = ref}
53 | placeholder={"Search..."}
54 | />
55 |
56 |
57 | )}
58 |
59 | ```
60 |
61 | ## Properties
62 | | Key | Description | Value Type | Is Required | Default |
63 | |----------------------|-----------------------------------------------------------------------------------------|-----------------------------------|-------------|---------------------------|
64 | | height | Height of the search box | ``number`` | false | 48 |
65 | | borderRadius | Border radius of the search box | ``number`` | false | 48 |
66 | | fontSize | Font size of the search box | ``number`` | false | 20 |
67 | | backgroundColor | Background color of the search box | ``color codes (hex,rgb,rgba)`` | false | rgba(255,255,255,0.70) |
68 | | placeholderTextColor | Placeholder text color | ``color codes (hex,rgb,rgba)`` | false | #555555 |
69 | | searchIconSize | Search icon width and height size | ``number`` | false | 20 |
70 | | searchIconColor | Search icon color | ``color codes (hex,rgb,rgba)`` | false | #555555 |
71 | | focusAfterOpened | If true, keyboard will show after search box opened | ``boolean`` | false | false |
72 | | shadowColor | Box\-shadow color of the search box\. If you don't want to please type ``transparent`` | ``color codes (hex,rgb,rgba)`` | false | rgba(0,0,0,0.12\) |
73 | | placeholder | Placeholder text of the search box | ``string/text`` | true | |
74 | | animationSpeed | Animation speeds as miliseconds | ``array ([number, number])`` | false | [200, 250] |
75 |
76 | And also supporting props all of the [TextInput Component of React Native](https://reactnative.dev/docs/textinput).
77 |
78 |
79 | ## Events
80 | |Key|Description|
81 | |---|-----------|
82 | |onOpening|Trigger on search box start to open|
83 | |onClosing|Trigger on search box start to close|
84 | |onOpened|Trigger on search box fully opened|
85 | |onClosed|Trigger on search box fully closed|
86 |
87 | And also supporting events all of the [TextInput Component of React Native](https://reactnative.dev/docs/textinput).
88 |
89 |
90 | ## FAQ
91 | **Can I use this template for personal or commercial websites/web projects?**
92 |
93 | Sure, you can use both of personal and commercial websites/web projects.
94 |
95 | **Is the attribution link required?**
96 |
97 | No, not required. (Though very much appreciated)
98 |
99 |
100 | ## License
101 | **React Native - Animated Searchbox** is an open source project that is licensed under the [MIT license](http://opensource.org/licenses/MIT).
102 |
103 |
104 | ## Credits
105 | * [Unsplash](https://unsplash.com/) - Beautiful, free images and photos that you can download and use for any project.
106 | * [Ionicons](https://ionicons.com/) - Premium designed icons for use in web, iOS, Android, and desktop apps.
107 |
108 |
109 | ## Donations
110 | Donations are **greatly appreciated!**
111 |
112 | **[BUY ME A COFFEE](http://bit.ly/2yEjtx5)**
113 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {View, Animated, Easing, TouchableOpacity, TextInput, StyleSheet} from 'react-native';
3 | import PropTypes from 'prop-types';
4 | import Svg, {Path} from "react-native-svg";
5 |
6 | class ReactNativeAnimatedSearchbox extends React.Component {
7 | state = {
8 | width: 0,
9 | textInputAnimated: new Animated.Value(0),
10 | parentViewWidthAnimated: new Animated.Value(this.props.height),
11 | isScaled: false
12 | }
13 |
14 | //Get parent width value
15 | onLayout = e => {
16 | const {width} = e.nativeEvent.layout;
17 | this.setState({width});
18 | }
19 |
20 | //Search icon
21 | searchIcon = () => {
22 | const {searchIconSize, searchIconColor} = this.props;
23 | return (
24 |
31 | )
32 | }
33 |
34 | //Animation start - open effect
35 | open = () => {
36 | const {focusAfterOpened, animationSpeed, onOpened, onOpening} = this.props;
37 | onOpening && onOpening();
38 |
39 | Animated.timing(this.state.textInputAnimated, {
40 | toValue: 1,
41 | duration: animationSpeed[0],
42 | easing: Easing.linear,
43 | }).start(() => {
44 | setTimeout(() => {
45 | this.setState({isScaled: true});
46 |
47 | Animated.timing(this.state.parentViewWidthAnimated, {
48 | toValue: this.state.width,
49 | duration: animationSpeed[1],
50 | easing: Easing.linear,
51 | }).start(() => {
52 | onOpened && onOpened();
53 | if (focusAfterOpened) this.refTextInput.focus();
54 | });
55 | }, 125);
56 | });
57 | }
58 |
59 | //Animation start - close effect
60 | close = () => {
61 | const {animationSpeed, onClosed, onClosing} = this.props;
62 | onClosing && onClosing();
63 |
64 | Animated.timing(this.state.parentViewWidthAnimated, {
65 | toValue: this.props.height,
66 | duration: animationSpeed[1],
67 | easing: Easing.linear,
68 | }).start(() => {
69 | this.setState({isScaled: false});
70 |
71 | setTimeout(() => {
72 | Animated.timing(this.state.textInputAnimated, {
73 | toValue: 0,
74 | duration: animationSpeed[0],
75 | easing: Easing.linear,
76 | }).start(() => {
77 | onClosed && onClosed();
78 | });
79 | }, 125);
80 | });
81 | }
82 |
83 | render() {
84 | const {height, borderRadius, fontSize, backgroundColor, placeholderTextColor, shadowColor, placeholder} = this.props;
85 |
86 | return (
87 |
88 |
89 |
95 |
96 | (this.refTextInput = ref)}
99 | placeholderTextColor={this.state.isScaled ? placeholderTextColor : 'transparent'}
100 | placeholder={placeholder}
101 | style={[styles.searchInput,
102 | {
103 | shadowColor: shadowColor,
104 | backgroundColor: backgroundColor,
105 | height: height,
106 | borderRadius: borderRadius,
107 | fontSize: fontSize,
108 | paddingLeft: height,
109 | }
110 | ]}
111 | />
112 |
113 | {
114 | this.state.isScaled
115 | ? (
116 |
117 | {this.searchIcon()}
118 |
119 | )
120 | : null
121 | }
122 |
123 |
124 | {
125 | this.state.isScaled
126 | ? null
127 | : (
128 |
130 | {this.searchIcon()}
131 |
132 | )
133 | }
134 |
135 | )
136 | }
137 | }
138 |
139 | const styles = StyleSheet.create({
140 | container: {
141 | position: 'relative',
142 | width: '100%'
143 | },
144 | animatedContainer: {
145 | marginLeft: 'auto'
146 | },
147 | searchInput: {
148 | shadowOffset: {width: 0, height: 10},
149 | shadowOpacity: 1,
150 | shadowRadius: 12,
151 | },
152 | inputSearchIcon: {
153 | position: 'absolute',
154 | left: 0,
155 | flex: 1,
156 | justifyContent: 'center',
157 | alignItems: 'center'
158 | },
159 | inputClosedSearchIcon: {
160 | position: 'absolute',
161 | right: 0,
162 | flex: 1,
163 | justifyContent: 'center',
164 | alignItems: 'center'
165 | }
166 | });
167 |
168 | ReactNativeAnimatedSearchbox.defaultProps = {
169 | height: 48,
170 | borderRadius: 48,
171 | searchIconColor: '#555555',
172 | searchIconSize: 20,
173 | focusAfterOpened: false,
174 | placeholderTextColor: '#555555',
175 | fontSize: 16,
176 | backgroundColor: 'rgba(255,255,255,0.70)',
177 | shadowColor: 'rgba(0,0,0,0.12)',
178 | animationSpeed: [200, 250]
179 | }
180 |
181 | ReactNativeAnimatedSearchbox.propTypes = {
182 | height: PropTypes.number,
183 | borderRadius: PropTypes.number,
184 | fontSize: PropTypes.number,
185 | backgroundColor: PropTypes.string,
186 | placeholderTextColor: PropTypes.string,
187 | searchIconSize: PropTypes.number,
188 | searchIconColor: PropTypes.string,
189 | focusAfterOpened: PropTypes.bool,
190 | shadowColor: PropTypes.string,
191 | placeholder: PropTypes.string.isRequired,
192 | animationSpeed: PropTypes.array,
193 | onOpened: PropTypes.func,
194 | onClosed: PropTypes.func,
195 | onOpening: PropTypes.func,
196 | onClosing: PropTypes.func
197 | }
198 |
199 | export default ReactNativeAnimatedSearchbox;
--------------------------------------------------------------------------------