DEV Community

doruletzz
doruletzz

Posted on

🔎 Search Bar in React

...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
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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>
    );
};

Enter fullscreen mode Exit fullscreen mode

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>
    );
};
Enter fullscreen mode Exit fullscreen mode

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>
        </>
    );
};

Enter fullscreen mode Exit fullscreen mode

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%;
}
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

& 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;
}
Enter fullscreen mode Exit fullscreen mode

And so we've created our SearchBar React Component.

Top comments (0)