<body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
</body>
*,
*:after,
*:before {
    margin: 0;
    padding: 0;
}
.sr-only {
    border: 0 !important;
    clip: rect(1px, 1px, 1px, 1px) !important;
    -webkit-clip-path: inset(50%) !important;
    clip-path: inset(50%) !important;
    height: 1px !important;
    margin: -1px !important;
    overflow: hidden !important;
    padding: 0 !important;
    position: absolute !important;
    width: 1px !important;
    white-space: nowrap !important;
}
img {
    width: 100%;
}
:root {
    --bg: hsl(0, 0%, 98%);
    --bg-offset: hsl(0, 0%, 100%);
    --text: hsl(200, 15%, 8%);
    --gray: hsl(0, 0%, 52%);
    --border: rgba(0, 0, 0, 0.1);
}
ul,
ol {
    list-style: none;
}
body {
    background: var(--bg);
    font-family: sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    font-size: 14px;
}
h1,
h2 {
    heigh: 18px;
}
.wrapper {
    width: 96%;
    max-width: 1140px;
    margin: 0 auto;
}
.card-grid {
    margin: 2em 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    grid-gap: 48px;
}
.card {
    background-color: var(--bg-offset);
    padding: 0px;
    box-shadow: 0px 2px 4px var(--border);
    transition: all 0.3s cubic-bezier(0.075, 0.82, 0.165, 1);

    &:hover {
        transform: scale(1.1);

        .card-content {
            h2 {
                display: block;
                -webkit-line-clamp: none;
                -webkit-box-orient: none;
                overflow: visible;
            }
        }
    }
}
.card-image {
    max-height: 150px;

    img {
        min-height: 100%;
        width: 100%;
        object-fit: cover;
        object-position: center;
    }
}
.card-content {
    padding: 32px 15px;

    h2 {
        display: -webkit-box;
        -webkit-line-clamp: 1;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }
}
.card-list {
    margin-top: 16px;

    li {
        color: var(--text);
        margin-top: 8px;

        span {
            color: var(--gray);
        }
    }
}

/* search input */
.search-wrapper {
    margin: 48px 0;
    display: flex;
    justify-content: space-between;
}

@media (max-width: 375px) {
    .search-input {
        width: 100%;
    }
    .search-wrapper {
        justify-content: start;
        flex-wrap: wrap;
    }
}

.search-input {
    background-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0xNS44NTMgMTYuNTZjLTEuNjgzIDEuNTE3LTMuOTExIDIuNDQtNi4zNTMgMi40NC01LjI0MyAwLTkuNS00LjI1Ny05LjUtOS41czQuMjU3LTkuNSA5LjUtOS41IDkuNSA0LjI1NyA5LjUgOS41YzAgMi40NDItLjkyMyA0LjY3LTIuNDQgNi4zNTNsNy40NCA3LjQ0LS43MDcuNzA3LTcuNDQtNy40NHptLTYuMzUzLTE1LjU2YzQuNjkxIDAgOC41IDMuODA5IDguNSA4LjVzLTMuODA5IDguNS04LjUgOC41LTguNS0zLjgwOS04LjUtOC41IDMuODA5LTguNSA4LjUtOC41eiIvPjwvc3ZnPg==");
    background-color: var(--bg-offset);
    background-size: 16px 16px;
    background-position: left 10px center;
    background-repeat: no-repeat;
    padding: 1.4em 2em;
    padding-left: 2.7em;
    border: 1px solid var(--border);
    color: var(--gray);
    box-shadow: 0px 4px 6px var(--border);
    transition: all 0.4s cubic-bezier(0.215, 0.61, 0.355, 1);

    &:hover {
        box-shadow: 0px 0px 0px var(--border);
    }
}
View Compiled
import React from "https://cdn.skypack.dev/react@17.0.1";
import ReactDOM from "https://cdn.skypack.dev/react-dom@17.0.1";

import { useState, useEffect } from "https://cdn.skypack.dev/react";

function App() {
    const [error, setError] = useState(null);
    const [isLoaded, setIsLoaded] = useState(false);
    const [items, setItems] = useState([]);

    //     set search query to empty string
    const [q, setQ] = useState("");
    //     set search parameters
    //     we only what to search countries by capital and name
    //     this list can be longer if you want
    //     you can search countries even by their population
    // just add it to this array
    const [searchParam] = useState(["capital", "name"]);

    // Note: the empty deps array [] means
    // this useEffect will run once
    // similar to componentDidMount()

    useEffect(() => {
        fetch("https://restcountries.eu/rest/v2/all")
            .then((res) => res.json())
            .then(
                (result) => {
                    setIsLoaded(true);
                    setItems(result);
                },

                // Note: it's important to handle errors here
                // instead of a catch() block so that we don't swallow
                // exceptions from actual bugs in components.
                (error) => {
                    setIsLoaded(true);
                    setError(error);
                }
            );
    }, []);

    /* here we create a function 
//     we filter the items
// use array property .some() to return an item even if other requirements didn't match
    */
    function search(items) {
        return items.filter((item) => {
            return searchParam.some((newItem) => {
                return (
                    item[newItem]
                        .toString()
                        .toLowerCase()
                        .indexOf(q.toLowerCase()) > -1
                );
            });
        });
    }

    if (error) {
        return (
            <p>
                {error.message}, if you get this error, the free API I used
                might have stopped working, but I created a simple example that
                demonstrate how this works,{" "}
                <a href="https://codepen.io/Spruce_khalifa/pen/mdXEVKq">
                    {" "}
                    check it out{" "}
                </a>{" "}
            </p>
        );
    } else if (!isLoaded) {
        return <>loading...</>;
    } else {
        return (
            <div className="wrapper">
                <div className="search-wrapper">
                    <label htmlFor="search-form">
                        <input
                            type="search"
                            name="search-form"
                            id="search-form"
                            className="search-input"
                            placeholder="Search for..."
                            value={q}
                            /* 
                            // set the value of our useState e
                            //  anytime the user types in the search box
                            */
                            onChange={(e) => setQ(e.target.value)}
                        />
                        <span className="sr-only">Search countries here</span>
                    </label>
                </div>
                <ul className="card-grid">
                    {search(items).map((item) => (
                        <li>
                            <article className="card" key={item.callingCodes}>
                                <div className="card-image">
                                    <img src={item.flag} alt={item.name} />
                                </div>
                                <div className="card-content">
                                    <h2 className="card-name">{item.name}</h2>
                                    <ol className="card-list">
                                        <li>
                                            population:{" "}
                                            <span>{item.population}</span>
                                        </li>
                                        <li>
                                            Region: <span>{item.region}</span>
                                        </li>
                                        <li>
                                            Capital: <span>{item.capital}</span>
                                        </li>
                                    </ol>
                                </div>
                            </article>
                        </li>
                    ))}
                </ul>
            </div>
        );
    }
}

ReactDOM.render(<App />, document.getElementById("root"));
View Compiled
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.