...so, recently i've been needing a SearchBar component for my React Web Applications and i've kept postponing having a generic one that i can use in all my projects, but no more!
btw, this is also my first blog post to dev.to
Let's get started!
also if you'd like you can clone this project on github or check it out on stackblitz
Step 1: Initialize Project
Before we get started, we need to initialize a react application, we will use vite & npm, but feel free to use whatever tools you'd like.
Pick React with Typescript:
npm create vite@latest search-bar
cd search-bar
npm install
npm run dev
Next we delete all other files in src/*
except src/App.tsx
& src/main.tsx
And we edit App.tsx
to look something like this:
// src/App.tsx
export const App = () => {
return <>Hello World</>
};
export default App;
Step 2: SearchBar and Card components
Next up we create the 2 needed components, inside src/components/* for our application: <SearchBar/>
& <Card/>
// src/components/Card/index.tsx
import { CardComponent } from './CardComponent';
const Card = CardComponent;
export default Card;
// src/components/Card/CardComponent.tsx
import React, { ReactNode } from 'react';
type CardComponentProps = {
title: string;
subtitle: string;
slug?: string;
children: ReactNode;
};
export const CardComponent = ({
title,
subtitle,
slug,
children,
}: CardComponentProps) => {
return (
<div id={slug} className='card'>
<h6 className='title'>{title}</h6>
{subtitle && <p className='subtitle'>{subtitle}</p>}
<hr />
{children && <div className='content'>{children}</div>}
</div>
);
};
And we have our <Card/>
component. We create the SearchBar in a similar way, with something like this:
// src/components/SearchBar/index.tsx
import { SearchBarComponent } from './SearchBarComponent';
const SearchBar = SearchBarComponent;
export default SearchBar;
// src/components/SearchBar/SearchBarComponent.tsx
import React, { ChangeEvent, Dispatch, SetStateAction } from 'react';
type SearchBarComponentProps = {
label?: string;
inputText: string;
setInputText: Dispatch<SetStateAction<string>>;
};
export const SearchBarComponent = ({
label,
inputText,
setInputText,
}: SearchBarComponentProps) => {
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
const { value } = e.target;
setInputText(value);
};
return (
<div className='search-bar'>
<label>{label}</label>
<input value={inputText} onChange={handleChange} />
</div>
);
};
And we are done, we've created our needed components.
Step 3: Tying it all together
Finally we are going to use a state that will be passed inside of the SearchBar components
We update App.tsx to look something like this:
// src/App.tsx
import React, { ReactNode, useState } from 'react';
import Card from './components/Card';
import SearchBar from './components/SearchBar';
type CardData = {
title: string;
subtitle: string;
content: ReactNode;
};
// const data : CardData[] = ...
export const App = () => {
const [searchText, setSearchText] = useState('');
const filterCard = (e: CardData) =>
e.title.toLowerCase().includes(searchText.toLowerCase());
return (
<>
<SearchBar
label='SEARCH'
inputText={searchText}
setInputText={setSearchText}
/>
<div className='card-container'>
{mockData.filter(filterCard).map((data, index) => (
<Card
key={index}
title={data.title}
subtitle={data.subtitle}
>
{data.content}
</Card>
))}
</div>
</>
);
};
Step 4 (extra): Styling it all
First we style the layout, meaning App.tsx
by creating a App.css
// src/App.tsx
...
import './App.css';
...
// src/App.css
.search-bar {
margin: 2rem auto;
max-width: 80rem;
}
.card-container {
display: flex;
flex-wrap: wrap;
gap: 2rem;
max-width: 80rem;
margin: auto;
}
.card-container > .card {
flex-basis: 30%;
}
Next up we style the SearchBar:
// src/components/SearchBar/SearchBarComponent.tsx
...
import './SearchBarComponent.css';
...
// src/components/SearchBar/SearchBarComponent.css
.search-bar {
position: relative;
max-width: 42rem;
}
.search-bar > input {
width: 100%;
padding: 0.75rem;
padding-top: 1.75rem;
background-color: var(--card-color);
color: var(--text-color-900);
font-size: 1.125rem;
border: none;
border-radius: 0.5rem;
}
.search-bar > label {
position: absolute;
top: 0.5rem;
left: 0.75rem;
font-size: 0.75rem;
color: var(--text-color-800);
}
& Finally we do the Card:
// src/components/Card/CardComponent.tsx
...
import './CardComponent.css';
...
// src/components/Card/CardComponent.css
.card {
background-color: var(--card-color);
aspect-ratio: 4/5;
display: flex;
flex-direction: column;
gap: 0.5rem;
border-radius: 1rem;
padding: 2rem;
}
.card > .title {
color: var(--text-color-900);
font-size: 1.5rem;
font-weight: bold;
margin: 0;
overflow: hidden;
text-overflow: ellipsis;
}
.card > .subtitle {
color: var(--text-color-800);
text-transform: uppercase;
font-size: 1rem;
margin: 0;
overflow: hidden;
text-overflow: ellipsis;
}
.card > hr {
background-color: var(--text-color-800);
width: 2rem;
height: 0.05rem;
margin: 0;
border: none;
margin-right: 100%;
}
.card > .content {
color: var(--text-color-900);
flex-grow: 1;
overflow: hidden;
text-overflow: ellipsis;
}
And so we've created our SearchBar React Component.
Top comments (0)