🟩 - Easy Flashcards

Easy level React coding assignments (36 cards)

1
Q

Chips Input

Description
In this task, you are asked to create a Chips Input component that allows users to input a series of tags or keywords. The component will display these tags as “chips” (small labels), which users can add and remove dynamically.
Features:
1. Input Field: Users can type text into an input field.
2. Add Chips: When the user presses the “Enter” key, the typed text will be added as a new chip (tag). Empty or whitespace-only chips should not be added
3. Remove Chips: Users can delete a chip by clicking the
“X” button next to it.
4. Horizontal Display: The chips should be displayed in a horizontal list.
5. Persistence: The list of chips should be maintained even when the component re-renders.

Important Points:
1. The input field should be of type text.
2. Button should be labeled “X” to delete chips
3. If two chips have the same name, deleting one should NOT delete both.
4. Make sure to use onKeyDown event handler instead of onKeyPress because onKeyPress is deprecated.

https://namastedev.com/practice/chips-input

A

style.css

body {
  font-family: sans-serif;
  -webkit-font-smoothing: auto;
  -moz-font-smoothing: auto;
  -moz-osx-font-smoothing: grayscale;
  font-smoothing: auto;
  text-rendering: optimizeLegibility;
  font-smooth: always;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
}

h1 {
  font-size: 1.5rem;
}

.chips-container {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 8px;
}

.chip {
  background-color: #e0e0e0;
  border-radius: 16px;
  padding: 4px 12px;
  display: flex;
  align-items: center;
  font-size: 14px;
}

.chip button {
  margin-left: 8px;
  border: none;
  background: transparent;
  cursor: pointer;
  font-weight: bold;
  color: red;
}

.chips-input-field {
  margin-top: 8px;
  padding: 6px;
  font-size: 16px;
  width: 100%;
  max-width: 300px;
}

.chip {
  transition: background-color 0.2s ease;
}

ChipsInput.js

import React, { useState } from "react";
import './styles.css'
function ChipsInput() {
  const [chips, setChips] = useState([]);
  const [inputValue, setInputValue] = useState('');
  const handleKeyDown = (e) => {
    if (e.key === 'Enter') {
      const trimmed = inputValue.trim();
      if (trimmed !== '') {
        setChips([...chips, trimmed]);
        setInputValue('');
      }
    }
  };

  const handleDelete = (indexToDelete) => {
    setChips(chips.filter((_, index) => index !== indexToDelete));
  };

  return (
    <div style={{display:"flex", flexDirection:"column",alignItems:"center", margin:"40px 0"}}>
      <h2>Chips Input</h2>
      <input
        type="text" 
        placeholder="Type a chip and press tag"
        style={{ padding: "8px", width: "200px" }}
        onChange={(e) => setInputValue(e.target.value)}
        value={inputValue}
        onKeyDown={handleKeyDown}
      />
      <div className="chips-container">
        {chips.map((chip, index) => (
          <span className="chip" key={index}>
            {chip} <button onClick={() => handleDelete(index)}>X</button>
          </span>
        ))}
      </div>
    </div>
  );
}

export default ChipsInput;

App.js

import ChipsInput from './ChipsInput.js'
export default function App() {
  return <ChipsInput/>
}

Style Reasoning:
πŸ”€ 1. Base Typography and Text Rendering

body {
  font-family: sans-serif;
  -webkit-font-smoothing: auto;
  -moz-font-smoothing: auto;
  -moz-osx-font-smoothing: grayscale;
  font-smoothing: auto;
  text-rendering: optimizeLegibility;
  font-smooth: always;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
}

Why these styles?
* Ensures text looks crisp and readable on most platforms (especially macOS and iOS).
* text-rendering: optimizeLegibility; improves kerning and ligatures.
* -webkit-tap-highlight-color: transparent and -webkit-touch-callout: none remove blue highlight and callout menus on mobile taps β€” better UX for touch devices.
✨ This base styling is often used in production apps for consistent cross-device font rendering and interaction.

🧱 2. Basic Layout: Headings and Container

h1 {
  font-size: 1.5rem;
}

Why this?
* Slightly smaller and more modern than default browser h1. Fits better in components-focused UIs.

.chips-container {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 8px;
}

Why this?
* flex + wrap: Allows chips to flow to the next line when there’s not enough space.
* gap: Adds consistent spacing between chips β€” cleaner than using margin.
* padding: Adds internal spacing so chips don’t hug the edge of the container.

🏷️ 3. Chips Design

.chip {
  background-color: #e0e0e0;
  border-radius: 16px;
  padding: 4px 12px;
  display: flex;
  align-items: center;
  font-size: 14px;
}

Why this?
* Light gray background for neutral appearance.
* border-radius: 16px: Rounded pill-style shape β€” visually familiar as “chip”.
* padding gives breathing room around text.
* display: flex + align-items: center: Ensures text and “X” button align vertically.

.chip button {
  margin-left: 8px;
  border: none;
  background: transparent;
  cursor: pointer;
  font-weight: bold;
  color: red;
}

Why this?
* “X” button feels integrated into chip (no border/background).
* Red color: visually distinct for a delete action.
* cursor: pointer signals interactivity.

🎯 4. Input Field Styling

.chips-input-field {
  margin-top: 8px;
  padding: 6px;
  font-size: 16px;
  width: 100%;
  max-width: 300px;
}

Why this?
* margin-top: Separates from chips for clarity.
* padding: Improves tap/click target.
* max-width: Keeps UI tidy and limits excessive horizontal growth.
* font-size: Matches body text size for readability.

✨ 5. Enhancement: Smooth Transitions

.chip {
  transition: background-color 0.2s ease;
}

Why this?
* Smooth transitions make the UI feel more modern and responsive.
* Prepares the chip for future enhancements like hover effects or animation when removed.

βœ… Summary
| —- | —————————————— | ———————————– |
| 1. | Consistent, legible fonts across platforms | font-smoothing, text-rendering |
| 2. | Clean layout for wrapping chips | flex-wrap, gap, padding |
| 3. | Chip UI & delete behavior | border-radius, button, color |
| 4. | Usable input field | max-width, font-size, padding |
| 5. | Add polish | transition |

Step | Goal | Style |

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Guess the Number

Description
Build a “Guess the Number” game where the user tries to guess a randomly generated number between 1 and 100. The game provides feedback after each guess and tracks the number of attempts.
Requirements
1. Generate a Random Number
* Random number between 1 and 100 (inclusive) is generated at the start of the game.
2. User Input
* User enters a guess between 1 and 100.
* The input field must have an id=”guess-input” for easy testing.

  1. Feedback After Each Guess
    * Correct Guess: “Congratulations! You guessed the number in X attempts.”
    * Guess is less than Random number: “Too low! Try again.”
    * Guess is greater than Random number: “Too high! Try again.”
    * Invalid Input: “Please enter a number between 1 and 100.”
  2. Track Attempts
    * Keep count of the number of guesses made.
  3. Buttons and Their Functions
    * A button labelled “Reset Game” starts a new game.
    * A button labeled “Check Guess” checks the current guess and give feedback

Input/Output Example
Input: 50
Output: Too high! Try again.
Input: 30
Output: Too low! Try again.
Input: 40
Output: Congratulations! You guessed the number i
Input: 105
Output: Please enter a number between 1 and 100.
Input: apple
Output: Please enter a number between 1 and 100.

https://namastedev.com/practice/guess-the-number

A

style.css

body {
  font-family: sans-serif;
  -webkit-font-smoothing: auto;
  -moz-font-smoothing: auto;
  -moz-osx-font-smoothing: grayscale;
  font-smoothing: auto;
  text-rendering: optimizeLegibility;
  font-smooth: always;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
}

h1 {
  font-size: 1.5rem;
}

.game-container {
  max-width: 400px;
  margin: 50px auto;
  text-align: center;
  background-color: #f9f9f9;
  padding: 24px;
  border-radius: 16px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.1);
}

.guess-input {
  width: 80%;
  max-width: 300px;
  padding: 10px;
  font-size: 16px;
  border: 1px solid #ccc;
  border-radius: 8px;
  margin-bottom: 16px;
}

.button-row {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-bottom: 16px;
}

.button-row button {
  padding: 8px 16px;
  font-size: 14px;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: background-color 0.3s ease;
  color: white;
}

.button-row button:first-child {
  background-color: #4caf50;
}

.button-row button:first-child:hover {
  background-color: #388e3c;
}

.button-row button:last-child {
  background-color: #f44336;
}

.button-row button:last-child:hover {
  background-color: #d32f2f;
}

.feedback {
  font-weight: bold;
  margin-bottom: 8px;
}

.attempts {
  color: #666;
  font-size: 14px;
}

GuessTheNumber.jsx

import React, { useState } from "react";
import './styles.css'

function GuessTheNumber() {
  
  const getRandomNumber = () => Math.floor(Math.random() * 100) + 1;

  const [randomNumber, setRandomNumber] = useState(getRandomNumber);
  const [guess, setGuess] = useState('');
  const [feedback, setFeedback] = useState('');
  const [attempts, setAttempts] = useState(0);

  const handleGuess = () => {
    const num = Number(guess.trim());

    if (isNaN(num) || num < 1 || num > 100) {
      setFeedback("Please enter a number between 1 and 100.");
      return;
    }

    setAttempts(attempts + 1);

    if (num === randomNumber) {
      setFeedback(`πŸŽ‰ Congratulations! You guessed the number in ${attempts + 1} attempts.`);
    } else if (num < randomNumber) {
      setFeedback("Too low! Try again.");
    } else {
      setFeedback("Too high! Try again.");
    }
  };

  const resetGame = () => {
    setRandomNumber(getRandomNumber());
    setGuess('');
    setFeedback('');
    setAttempts(0);
  };

  return (
    <div className="game-container">
      <h2>Guess the Number</h2>
      <input
        id="guess-input"
        placeholder="Enter a number between 1 and 100"
        value={guess}
        onChange={(e) => setGuess(e.target.value)}
        className="guess-input"
      />
      <div className="button-row">
        <button onClick={handleGuess}>Check Guess</button>
        <button onClick={resetGame}>Reset Game</button>
      </div>
      <p className="feedback">{feedback}</p>
      <p className="attempts">Attempts: {attempts}</p>
    </div>
  );
}

export default GuessTheNumber;

App.js

import GuessTheNumber from './GuessTheNumber'
export default function App() {
  return <GuessTheNumber/>
}

πŸ”§ Step-by-Step Styling Evolution
1. 🎁 Add a wrapper class
Gives the game structure and central alignment.

.game-container {
  max-width: 400px;
  margin: 50px auto;
  text-align: center;
  background-color: #f9f9f9;
  padding: 24px;
  border-radius: 16px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.1);
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Progress Bar

Description:
Create a Progress Bar Component in React that visually represents a single progress value. Users should be able to increment or decrement progress using buttons. Make sure to use inline css.

Requirements
1. Display one progress bar.
2. The bar should reflect a numeric progress (0-100%).
3. Include buttons labeled ‘+10%’ and ‘-10%’ to increase or decrease the bar’s value.
4. Prevent values from going below 0% or above 100%.
5. Change bar color based on value (e.g., red, orange, green).
6. Color is selected based on thresholds:
* Red if less than 40%
* Orange if between 40-79%
* Green if 80% or more
Constraints & Edge Casès
* Constraint 1: Progress must stay between 0 and 100.
* Constraint 2: The background color-changing div must have an id=”testBgColor” for testing the background color of progress bar.
* Edge Case 1: If decrementing would take a value below
0, clamp it to 0.
* Edge Case 2: If incrementing would take a value above
100, clamp it to 100.

https://namastedev.com/practice/progress-bar

A

ProgressBars.js

import React, { useState } from "react";

function ProgressBar() {
  const [progress, setProgress] = useState(0);

  // Clamp value between 0 and 100
  const clamp = (value) => Math.max(0, Math.min(100, value));

  // Increase by 10
  const increment = () => {
    setProgress((prev) => clamp(prev + 10));
  };

  // Decrease by 10
  const decrement = () => {
    setProgress((prev) => clamp(prev - 10));
  };

  // Determine color based on progress
  const getColor = () => {
    if (progress < 40) return "red";
    if (progress < 80) return "orange";
    return "green";
  };

  return (
    <div style={{ textAlign: "center", marginTop: "50px" }}>
      <h2>Progress: {progress}%</h2>

      <div
        style={{
          width: "80%",
          height: "30px",
          border: "1px solid #ccc",
          borderRadius: "8px",
          margin: "auto",
          overflow: "hidden",
        }}
      >
        <div
          id="testBgColor"
          style={{
            height: "100%",
            width: `${progress}%`,
            backgroundColor: getColor(),
            transition: "width 0.3s ease",
          }}
        />
      </div>

      <div style={{ marginTop: "20px" }}>
        <button
          onClick={decrement}
          style={{
            padding: "10px 20px",
            marginRight: "10px",
            fontSize: "16px",
            cursor: "pointer",
          }}
        >
          -10%
        </button>
        <button
          onClick={increment}
          style={{
            padding: "10px 20px",
            fontSize: "16px",
            cursor: "pointer",
          }}
        >
          \+10%
        </button>
      </div>
    </div>
  );
}

export default ProgressBar;

App.js

import ProgressBars from "./ProgressBars";

export default function App() {
  return <ProgressBars />;
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Array to Zigzag String Converter

Description
Create a React component that allows users to input multiple comma-separated strings and outputs a zigzag merged string.
The component merges the strings such that strings at even indices are appended as is, while strings at odd indices are reversed before appending.

Requirements
* A user can enter multiple strings separated by commas. in an input field.
The input box should have a placeholder like “Enter strings like one,two,three”
* A button is provided to trigger the merging operation.
* Upon clicking the button:
The input string is split by commas into an array.
Each string at an even index (0, 2, 4, …) is kept as is.
Each string at an odd index (1, 3, 5, …) is reversed.
All strings are joined together without any separator.
The merged string is displayed prefixed with “Output:
* If the input is empty or only spaces, the output should be empty.

Edge Cases & Constraints
* Input strings may contain spaces around commas; these should be trimmed.
* Empty input should result in empty output.
* Strings can contain special characters and numbers.
* Large or long strings should be handled correctly.
* The output concatenates all processed strings in zigzag order without spaces.
Example Inputs & Outputs
// Example 1: Two words input
Input: “hello, world”
Output: “Output: hellodlrow”
// Example 2: Single word input
Input: “single”
Output: “Output: single”
// Example 3: Multiple words
Input: “one, two, three, four”
Output: “Output: oneowtthreeruof”
// Example 4: Input with special characters
Input: “zig, zag!, foo#, bar$”
Output: “Output: zig!gazfoo#$rab”
// Example 5: Empty input
Input: “”
Output: “Output: “

Testing Requirements
* Verify that the input box has the correct placeholder text: “Enter strings like one,two,three”:
* Test that entering comma-separated strings and clicking submit produces the expected zigzag merged output.
* Test that single word inputs are handled correctly and the output should also be a single word.
* Test that empty input results in an empty output string.
* Test that input with special characters and numbers merges correctly with odd-index strings reversed.
* Confirm the output text is always prefixed with “Output:
* Confirm that leading and trailing spaces in input strings are trimmed before processing.

Data Test IDs (required for testing)
* data-testid=”input-box”: The input field where the user types comma-separated strings.
* data-testid=”submit-button”: The button which triggers the zigzag merging process.
* data-testid=”output-result”: The paragraph or element that displays the output result.

https://namastedev.com/practice/array-to-zigzag-string-converter

A

ZigzagString.js

import React, { useState } from "react";

function ZigzagString() {
  const [input, setInput] = useState("");
  const [output, setOutput] = useState("");

  const handleMerge = () => {
    const trimmed = input.trim();

    if (!trimmed) {
      setOutput("Output: ");
      return;
    }

    const parts = trimmed
      .split(",")
      .map((p) => p.trim())
      .filter((s) => s.length > 0);

    const result = parts
      .map((str, i) => (i % 2 === 0 ? str : str.split("").reverse().join("")))
      .join("");

    setOutput(`Output: ${result}`);
  };

  return (
    <div
      style={{
        maxWidth: "500px",
        margin: "50px auto",
        padding: "24px",
        textAlign: "center",
        backgroundColor: "#fff",
        borderRadius: "12px",
        boxShadow: "0 6px 18px rgba(0,0,0,0.1)",
        fontFamily: "sans-serif",
      }}
    >
      <input
        type="text"
        placeholder="Enter strings like one,two,three"
        value={input}
        onChange={(e) => setInput(e.target.value)}
        data-testid="input-box"
        style={{
          padding: "10px",
          width: "100%",
          maxWidth: "350px",
          fontSize: "16px",
          border: "1px solid #ccc",
          borderRadius: "8px",
          marginBottom: "16px",
        }}
      />
      <br />
      <button
        onClick={handleMerge}
        data-testid="submit-button"
        style={{
          padding: "10px 20px",
          fontSize: "14px",
          backgroundColor: "#4caf50",
          color: "white",
          border: "none",
          borderRadius: "8px",
          cursor: "pointer",
          transition: "background-color 0.3s ease",
        }}
        onMouseOver={(e) => (e.target.style.backgroundColor = "#388e3c")}
        onMouseOut={(e) => (e.target.style.backgroundColor = "#4caf50")}
      >
        Merge Strings
      </button>
      <p
        data-testid="output-result"
        style={{
          fontWeight: "bold",
          color: "#333",
          fontSize: "18px",
          marginTop: "20px",
        }}
      >
        {output}
      </p>
    </div>
  );
}

export default ZigzagString;

App.js

import React from "react";
import ZigzagString from "./ZigzagString";

export default function App() {
  return (
    <div style={{ padding: "20px" }}>
      <h1 style={{ textAlign: "center", fontFamily: "sans-serif" }}>
        Array to Zigzag String
      </h1>
      <ZigzagString />
    </div>
  );
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Tooltip

Description
Create a class-based React component named Tooltip that displays a list of icons. When a user hovers over an icon, a tooltip should appear showing the name of that icon.
This question tests your ability to handle mouse events (onMouseEnter, onMouseLeave), maintain component state, and use conditional rendering to show or hide Ul elements dynamically.
You must use the following list of icons with corresponding labels:
const icons = [
{ emoji: ‘🏠’, label: ‘Home’ },
{ emoji: ‘πŸ“§’, label: ‘Email’ },
{ emoji: ‘βš™οΈ’, label: ‘Settings’ }
];
The tooltip should always display the value of the label field from this array, corresponding to the hovered icon.

Component Behavior
* Renders a list of icons (using emoji).
* Each icon has a text label shown only when hovered.
* Tooltip is positioned above the icon.
* Tooltip disappears when the mouse is no longer hovering over the icon.
* Only one tooltip should be visible at a time.
* Tooltip text must match exactly what’s defined in the Label property.

https://namastedev.com/practice/tooltip

A

styles.css

.tooltip-container {
  display: flex;
  gap: 24px;
  font-size: 28px;
  padding: 50px;
  justify-content: center;
}

.tooltip-item {
  position: relative;
  text-align: center;
  cursor: pointer;
  transition: transform 0.2s ease;
}

.tooltip-item:hover {
  transform: scale(1.1);
}

.tooltip-box {
  position: absolute;
  bottom: 130%;
  left: 50%;
  transform: translateX(-50%);
  background: #222;
  color: #fff;
  padding: 6px 12px;
  border-radius: 6px;
  font-size: 14px;
  white-space: nowrap;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
  z-index: 1000;
  opacity: 0;
  animation: fadeIn 0.3s forwards;
}

@keyframes fadeIn {
  to {
    opacity: 1;
  }
}

Tooltip.js

import React, { Component } from 'react';
import './styles.css'; 

class Tooltip extends Component {
  
  render() {
    const icons = [
      { emoji: '🏠', label: 'Home' },
      { emoji: 'πŸ“§', label: 'Email' },
      { emoji: 'βš™οΈ', label: 'Settings' }
    ];

    return (
      <div className="tooltip-container">
        {icons.map((icon, index) => (
          <div
            key={index}
            className="tooltip-item"
          >
            <span>{icon.emoji}</span>
           
          </div>
        ))}
      </div>
    );
  }
}

export default Tooltip;

App.js

import Tooltip from './Tooltip'
export default function App() {
  return <Tooltip/>
}

Hook based implementation

import React, { useState } from 'react';
import './styles.css';

const icons = [
  { emoji: '🏠', label: 'Home' },
  { emoji: 'πŸ“§', label: 'Email' },
  { emoji: 'βš™οΈ', label: 'Settings' }
];

export default function Tooltip() {
  const [hoveredIndex, setHoveredIndex] = useState(null);

  return (
    <div className="tooltip-container">
      {icons.map((icon, index) => (
        <div
          key={index}
          className="tooltip-item"
          onMouseEnter={() => setHoveredIndex(index)}
          onMouseLeave={() => setHoveredIndex(null)}
        >
          <span>{icon.emoji}</span>
          {hoveredIndex === index && (
            <div className="tooltip-box">{icon.label}</div>
          )}
        </div>
      ))}
    </div>
  );
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Authentication

Description
Build a simple user authentication system using React Context API. The goal is to understand how to create context, provide context, and consume context within your components, as well as manage basic authentication state globally.
Requirements:
1. UserContext:
Create a UserContext using
React. createContext().
Store the following in the context:
isLoggedIn: A boolean that is false by default, and it toggles between true and false using the login and logout functions.
login(): function to log in a user. logout (): function to log out the user.
2. App: Wrap the app with UserProvider.
3. Navbar Component:
* Displays the app title (App) in the navigation bar.
* Uses UserContext to access isLoggedIn, login, and logout.
* If the user is not logged in:
Shows a “Login” button that triggers the login function when clicked.
* If the user is logged in:
Shows a “Welcome, User!” message.
Displays a “Logout” button that triggers the logout function when clicked.
4. Dashboard Component:
* Uses UserContext to access the isLoggedin state.
* If the user is not logged in:
Displays a message: “Please login to access your dashboard”.
* If the user is logged in:
Displays the message: “This is your dashboard”.

https://namastedev.com/practice/authentication

A

styles.css

/* index.css or App.css */

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  background-color: #f0f2f5;
  color: #333;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.app {
  width: 400px;
  background-color: #ffffff;
  border-radius: 12px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
  overflow: hidden;
}

nav {
  background-color: #4a90e2;
  color: white;
  padding: 16px 24px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

nav h1 {
  font-size: 20px;
}

nav span {
  font-size: 14px;
  margin-right: 10px;
}

nav button {
  background-color: white;
  color: #4a90e2;
  border: none;
  padding: 6px 12px;
  border-radius: 4px;
  font-weight: bold;
  cursor: pointer;
  transition: background-color 0.3s ease;
}

nav button:hover {
  background-color: #e0eaff;
}

.dashboard {
  padding: 40px 20px;
  text-align: center;
}

.dashboard h2 {
  font-size: 18px;
  color: #333;
}

App.js

import React from 'react';
import { UserProvider } from './userContext';
import Navbar from './Navbar';
import Dashboard from './Dashboard';

const App = () => {
  return (
    <UserProvider>
      <div className="app">
        <Navbar />
        <Dashboard />
      </div>
    </UserProvider>
  );
};

export default App;

userContext.js

import React, { createContext, useState } from 'react';

// Create the context
const UserContext = createContext();

// Create a provider component
const UserProvider = ({ children }) => {
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  const login = () => setIsLoggedIn(true);
  const logout = () => setIsLoggedIn(false);

  return (
    <UserContext.Provider value={{ isLoggedIn, login, logout }}>
      {children}
    </UserContext.Provider>
  );
};

export { UserContext, UserProvider };

Navbar.js

import React, { useContext } from 'react';
import { UserContext } from './userContext';

const Navbar = () => {
  const { isLoggedIn, login, logout } = useContext(UserContext);

  return (
    <nav>
      <h1>App</h1>
      <div>
        {!isLoggedIn ? (
          <button onClick={login}>Login</button>
        ) : (
          <>
            <span>Welcome, User!</span>
            <button onClick={logout}>Logout</button>
          </>
        )}
      </div>
    </nav>
  );
};

export default Navbar;

Dashboard.js

import React, { useContext } from 'react';
import { UserContext } from './userContext';

const Dashboard = () => {
  const { isLoggedIn } = useContext(UserContext);

  return (
    <div className="dashboard">
      <h2>
        {isLoggedIn
          ? 'This is your dashboard'
          : 'Please login to access your dashboard'}
      </h2>
    </div>
  );
};

export default Dashboard;
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

usePreviousHook

Description
You have to build a simple Counter App in React that also shows the previous count value. The goal is to allow users to increase, decrease, or reset the counter using buttons. In addition to displaying the current count, the app should also show the previous count using a custom usePrevious hook.

Things To Do
State Management
Use the useState hook to keep track of the current count value.
const currentCount, setCurrentCount] = useState(0);
The initial value of the count should be 0.

Previous State Hook
Create a custom hook usePrevious to store the previous value of the count.
The hook should return undefined on the first render, and return the previous value after each update.
const previousCount = usePrevious (currentCount);

Button Functionality
* Implement the increment function to increase the count by 1.
* The button should be labeled Increment.
* Implement the decrement function to decrease the count by 1.
* The button should be labeled Decrement.
* Implement the reset function to set the count back to 0.
* The button should be labeled Reset.

Display Output
Show the current count inside a heading element:
Current Count: {currentCount)
Show the previous count (using the usePrevious hook) in a separate heading element:
Previous Count: {previousCount)

A

App.js

import Counter from './Counter';
import './styles.css';

export default function App() {
  return <Counter />;
}

usePrevious.js

import { useEffect, useRef } from "react";

export default function usePrevious(value) {
  const ref = useRef();

  useEffect(() => {
    ref.current = value;
  }, [value]);

  return ref.current;
}

Counter.js

import "./styles.css";
import { useState } from "react";
import usePrevious from "./usePrevious";

export default function Counter() {
  const [currentCount, setCurrentCount] = useState(0);
  const previousCount = usePrevious(currentCount);

  const increment = () => setCurrentCount(prev => prev + 1);
  const decrement = () => setCurrentCount(prev => prev - 1);
  const reset = () => setCurrentCount(0);

  return (
    <div className="App">
      <h2>Current Count: {currentCount}</h2>
      <h2>Previous Count: {previousCount !== undefined ? previousCount : 'N/A'}</h2>
      <button onClick={decrement}>Decrement</button>
      <button onClick={reset}>Reset</button>
      <button onClick={increment}>Increment</button>
    </div>
  );
}

styles.css

.App {
  font-family: sans-serif;
  text-align: center;
  margin-top: 50px;
}

button {
  margin: 10px;
  padding: 10px 20px;
  font-size: 16px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  transition: background-color 0.2s ease;
}

button:hover {
  background-color: #f0f0f0;
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Accordion

Description
Build a React Accordion component that allows users to expand and collapse sections of content. When a section is clicked, it should toggle its visibility. If a new section is clicked, it should expand while the others collapse (i.e., only one section is open at a time).

Requirements
1. Display a list of accordion items, each with a title and content.
2. Clicking on a title expands its content and collapses any previously opened item.
3. If an already open inm is clicked, it should collapse.
4. The component should accept an array of items as props. Each item contains:
title: The heading of the accordion item. content: The details inside the accordion item.
5. The component should handle edge cases such as an empty list or invalid input by displaying a message “No items available”.

Constraints & Edge Cases
* The items prop should be an array of objects f title: string, content: string }.
* If items is empty, display a message like “No items available.”
* Optimize performance by using React’s useState and conditional rendering.

https://namastedev.com/practice/accordion

A

styles.css

/* General Accordion Styles */
.accordion {
    width: 100%;
    max-width: 400px;
    margin: auto;
    padding: 20px;
    border: 1px solid #ddd;
    border-radius: 8px;
    background-color: #f9f9f9;
}

/* Accordion Item Styles */
.accordion-item {
    margin-bottom: 10px;
    border: 1px solid #ddd;
    border-radius: 5px;
    background-color: #fff;
}

/* Accordion Title Button */
.accordion-title {
    width: 100%;
    padding: 15px;
    text-align: left;
    background-color: #f1f1f1;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    font-size: 16px;
    font-weight: bold;
    transition: background-color 0.3s ease;
}

.accordion-title:hover {
    background-color: #e0e0e0;
}

.accordion-title[aria-expanded="true"] {
    background-color: #d0d0d0;
}

.accordion-content {
    padding: 15px;
    background-color: #fafafa;
    border-top: 1px solid #ddd;
    font-size: 14px;
}

.accordion p {
    font-size: 16px;
    color: #666;
    text-align: center;
}

Accordion.js

import React, { useState } from "react";
import { FaChevronDown, FaChevronUp } from "react-icons/fa";
import "./styles.css";

function Accordion({ items }) {
    if (!Array.isArray(items) || items.length === 0) {
        return (
            <div className="accordion">
                <p>No items available</p>
            </div>
        );
    }
const [activeIndex, setActiveIndex] = useState(null);
    const toggleIndex = (index) => {
        setActiveIndex((prevIndex) => (prevIndex === index ? null : index));
    };

    return (
        <div className="accordion">
            {items.map((item, index) => {
                const isOpen = activeIndex === index;

                return (
                    <div key={index} className="accordion-item">
                        <button
                            className="accordion-title"
                            onClick={() => toggleIndex(index)}
                            aria-expanded={isOpen}
                        >
                            {item.title}
                            <span style={{ float: "right" }}>
                                {isOpen ? <FaChevronUp /> : <FaChevronDown />}
                            </span>
                        </button>

                        {isOpen && (
                            <div className="accordion-content">
                                {item.content}
                            </div>
                        )}
                    </div>
                );
            })}
        </div>
    );
}

export default Accordion;

App.js

import Accordion from "./Accordion"

export default function App() {

  const items = [
  {
    title: "JavaScript Basics",
    content: "Learn variables, functions, and loops in JavaScript."
  },
  {
    title: "React.js Overview",
    content: "Understand components, state, and props in React."
  },
  {
    title: "Node.js",
    content: "Basics of server-side development with Node.js."
  },
  {
    title: "Full-Stack Development",
    content: "Build full-stack apps with React and Node.js."
  },
];

return <Accordion items={items}/>
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Dark Mode

You have to build a simple Dark Mode Toggle component in React. The goal is to allow users to switch between light mode and dark mode by toggling a checkbox. The theme should visually update the background color, text and text color *
Things To Do
1. State Management
Add a useState hook to keep track of whether the app is in dark mode or light mode.
2. Toggle Function
Implement the togg leTheme function to update the state when the checkbox is toggled.
3. Dynamic Class Application
Apply the class dark-mode or light-mode to the parent β€Ή div> based on the value of state variable.
4. Text Label
Update the β€Ήspan className=”mode-text”> to show “Dark Mode” or
“Light Mode” depending on
the current theme.
Important Note
* Apply the class dark-mode to the parent < div> when dark mode is active.
* Apply the class light-mode when light mode is active.

https://namastedev.com/practice/dark-mode

A

style.css

body {
  margin: 0;
}

/* Light Mode */
.light-mode {
  background-color: #f0f0f0;
  color: #333;
}

/* Dark Mode */
.dark-mode {
  background-color: #121212;
  color: white;
}

.container {
  text-align: center;
  height: 100vh;
  width: 100vw;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

h1 {
  font-size: 32px;
  margin-bottom: 30px;
}

.toggle-container {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 20px;
}

.mode-text {
  font-size: 18px;
  font-weight: bold;
  color: inherit;
}

/* Toggle switch styles */
.switch {
  position: relative;
  display: inline-block;
  width: 60px;
  height: 34px;
}

.switch input {
  opacity: 0;
  width: 0;
  height: 0;
}

.slider {
  position: absolute;
  cursor: pointer;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #ccc;
  transition: 0.4s;
  border-radius: 50px;
}

.slider:before {
  position: absolute;
  content: "";
  height: 26px;
  width: 26px;
  border-radius: 50px;
  left: 4px;
  bottom: 4px;
  background-color: white;
  transition: 0.4s;
}

input:checked + .slider {
  background-color: #4caf50;
}

input:checked + .slider:before {
  transform: translateX(26px);
}

App.js

import DarkModeToggle from './DarkModeToggle'
export default function App() {
  return <DarkModeToggle/>
}

DarkModeToggle.js

import React, { useState } from 'react';
import './styles.css';

function DarkModeToggle() {
  const [isDarkMode, setIsDarkMode] = useState(false);

  const toggleTheme = () => {
    setIsDarkMode((prevMode) => !prevMode);
  };

  return (
    <div className={`container ${isDarkMode ? 'dark-mode' : 'light-mode'}`}>
      <h1>Dark Mode Toggle</h1>
      <div className="toggle-container">
        <label className="switch">
          <input
            type="checkbox"
            onChange={toggleTheme}
            checked={isDarkMode}
          />
          <span className="slider"></span>
        </label>
        <span className="mode-text">
          {isDarkMode ? 'Dark Mode' : 'Light Mode'}
        </span>
      </div>
    </div>
  );
}

export default DarkModeToggle;
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Sidebar

Description
Create a React sidebar component that can be toggled open or closed with a menu button. The sidebar appears on the right side of the screen and includes navigation items with hover effects.

Requirements
* The interface must include:
A sidebar positioned on the right side of the viewport.
A toggle button (with a menu icon) that is always visible and vertically centered on the right edge of the screen.
Use “Menu” icon form lucide-react
* Default Behavior:
The sidebar is hidden by defantlt.
The toggle button remains fixed and accessible at all times.
* Toggle Functionality:
Clicking the toggle button opens or closes the sidebar.
The sidebar should slide in and out from the right with a smooth transition effect.
* Sidebar Content:
When open, the sidebar displays a vertical list of navigation items:
Home
About
Services
Contact
Each navigation item should have a clear and smooth hover effect for better user interaction.

Data Test IDs (required for testing):
* data-testid=”sidebar” - sidebar container div
* data-testid=”btn-toggle” - toggle button
element
* data-testid=”icon-menu” - menu icon inside toggle button
* data-testid=”nav-menu” - container for nav items when sidebar is open
* data-testid=”nav-item-home” - nav item Home
* data-testid=”nav-item-about” - nav item About
* data-testid=”nav-item-services” - nav item
Services
* data-testid=”nav-item-contact” - nav item
Contact

https://namastedev.com/practice/sidebar

A

styles.css

/* Container for sidebar */
.sidebar {
  position: fixed;
  right: 0; /* changed from left: 0 */
  height: 100vh;
  width: 280px;
  background: linear-gradient(135deg, #4b6cb7, #182848);
  color: #f0f0f5;
  box-shadow: -2px 0 12px rgba(0, 0, 0, 0.3);
  padding-top: 60px;
  transform: translateX(100%);
  transition: transform 0.35s ease, box-shadow 0.3s ease;
  font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
  z-index: 1000;
}

/* Sidebar visible */
.sidebar.open {
  transform: translateX(0);
  box-shadow: -4px 0 20px rgba(0, 0, 0, 0.5);
}

/* Toggle button */
.toggle-btn {
  position: absolute;
  top: 15px;
  left: -60px;
  background-color: #4b6cb7;
  border: none;
  border-radius: 50%;
  padding: 12px;
  cursor: pointer;
  color: #f0f0f5;
  box-shadow: 0 4px 8px rgba(75, 108, 183, 0.6);
  transition: background-color 0.3s ease, transform 0.25s ease;
  display: flex;
  align-items: center;
  justify-content: center;
}

.toggle-btn:hover {
  background-color: #182848;
  transform: scale(1.1);
}

/* Navigation menu */
.nav-menu {
  width: 100%;
}

.nav-list {
  list-style: none;
  padding: 0 20px;
  margin: 0;
}

.nav-item {
  padding: 15px 20px;
  margin: 8px 0;
  border-radius: 8px;
  font-weight: 600;
  font-size: 1.1rem;
  cursor: pointer;
  color: #f0f0f5;
  transition: all 0.3s ease;
  user-select: none;
  position: relative;
  overflow: hidden;
}

.nav-item::after {
  content: "";
  position: absolute;
  bottom: 8px;
  left: 20px;
  height: 2px;
  width: 0%;
  background: #a8c0ff;
  transition: width 0.3s ease;
  border-radius: 2px;
}

.nav-item:hover::after {
  width: 60%;
}

.nav-item:hover {
  color: #ffffff;
  text-shadow: 0 0 5px #a8c0ff;
}

Sidebar.js

import React, { useState } from "react";
import { Menu } from "lucide-react";
import "./styles.css";

function Sidebar() {
  const [isOpen, setIsOpen] = useState(false);

  const toggleSidebar = () => {
    setIsOpen((prev) => !prev);
  };

  return (
    <div
      className={`sidebar ${isOpen ? "open" : ""}`}
      data-testid="sidebar"
    >
      <button
        className="toggle-btn"
        onClick={toggleSidebar}
        data-testid="btn-toggle"
      >
        <Menu size={24} data-testid="icon-menu" />
      </button>

      {isOpen && (
        <nav className="nav-menu" data-testid="nav-menu">
          <ul className="nav-list">
            <li className="nav-item" data-testid="nav-item-home">
              Home
            </li>
            <li className="nav-item" data-testid="nav-item-about">
              About
            </li>
            <li className="nav-item" data-testid="nav-item-services">
              Services
            </li>
            <li className="nav-item" data-testid="nav-item-contact">
              Contact
            </li>
          </ul>
        </nav>
      )}
    </div>
  );
}

export default Sidebar;

App.js

import Sidebar from './Sidebar.js'
export default function App() {
  return <Sidebar/>
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Mortgage Calculator

Description:
Create a Mortgage Calculator in React that allows users to input loan amount, interest rate, and loan term (years) to calculate the monthly mortgage payment.

Requirements
* Must have Input fields for:
Loan amount (in INR) with label=”Loan Amount” Annual interest rate (in %) with label=”Annual Interest Rate”
Loan term (in years) with id=”Loan Term”
* Show message “Invalid input” for inappropriate inputs
* Must have a button labelled “Calculate” to calculate the monthly payment
* Calculate monthly payment using the formula:
M = P x ((r (1 +r)^n)/(((1 + r)^n) - 1))
where:
M = monthly payment
P = loan principal (loan amount)
r = monthly interest rate = annual rate / 12 / 100
n = number of monthly payments = years * 12
* Display the calculated monthly payment.
* The result (monthly payment) must have aria-label=β€œresult”

Constraints & Edge Cases
* Inputs should be non-negative numbers.
* Interest rate cannot be zero or negative.
* Term should be greater than 0 years.
* Monthly payment should be displayed only if inputs are valid.

https://namastedev.com/practice/mortgage-calculator

A

styles.css

body {
  font-family: sans-serif;
  -webkit-font-smoothing: auto;
  -moz-font-smoothing: auto;
  -moz-osx-font-smoothing: grayscale;
  font-smoothing: auto;
  text-rendering: optimizeLegibility;
  font-smooth: always;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
}

h1 {
  font-size: 1.5rem;
}

MortageCalculator.js

import React, { useState } from "react";
import "./styles.css";

function MortgageCalculator() {
  const [amount, setAmount] = useState("");
  const [interest, setInterest] = useState("");
  const [term, setTerm] = useState("");
  const [result, setResult] = useState(null);
  const [error, setError] = useState("");

  const calculatePayment = () => {
    const P = parseFloat(amount);
    const annualRate = parseFloat(interest);
    const years = parseFloat(term);

    // Input validations
    if (
      isNaN(P) || P < 0 ||
      isNaN(annualRate) || annualRate <= 0 ||
      isNaN(years) || years <= 0
    ) {
      setError("Invalid input");
      setResult(null);
      return;
    }

    setError("");

    const r = annualRate / 12 / 100;
    const n = years * 12;

    const M = P * (r * Math.pow(1 + r, n)) / (Math.pow(1 + r, n) - 1);
    setResult(M.toFixed(2));
  };

  return (
    <div>
      <h1>Mortgage Calculator</h1>

      <div>
        <label>
          Loan Amount
          <input
            type="number"
            value={amount}
            onChange={(e) => setAmount(e.target.value)}
          />
        </label>
      </div>

      <div>
        <label>
          Annual Interest Rate
          <input
            type="number"
            value={interest}
            onChange={(e) => setInterest(e.target.value)}
          />
        </label>
      </div>

      <div>
        <label>
          Loan Term
          <input
            type="number"
            id="Loan Term"
            value={term}
            onChange={(e) => setTerm(e.target.value)}
          />
        </label>
      </div>

      <button onClick={calculatePayment}>Calculate</button>

      {error && <p style={{ color: "red" }}>{error}</p>}

      {result && (
        <p aria-label="result">
          Monthly Payment: β‚Ή{result}
        </p>
      )}
    </div>
  );
}

export default MortgageCalculator;

App.js

import MortgageCalculator from "./MortgageCalculator";

export default function App() {
  return <MortgageCalculator />;
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Even or Odd

Description:
Create a React component that allows users to input a number and checks whether the number is even or odd. The component displays the result with a 1-second loading delay and handles invalid inputs.
Requirements
* A user can enter a number in an input field.
The input box should have a placeholder “Enter a number”
* A button is provided to initiate the check.
* Upon clicking the button:
Any previous result should be cleared immediately.
A loading indicator should appear for 1 second to simulate processing.
In that one second a label “Checking…” should appear in the result-area.
After the delay, the result should display in the format:
“The number X is even.”
“The number X is odd.”
* If the input is empty or not a valid number:
Show a clear error message such as: “Please enter a valid number.”

Edge Cases & Constraints:
* Non-numeric input should display “Please enter a valid number.”
* Empty input should be handled gracefully.
* Leading/trailing spaces should be ignored.
* Large numbers should be processed correctly
* Loading message “Checking…” should be shown before result.
* The result display must only appear after loading completes.

Example Inputs & Outputs
// Example 1: Even number
Input: “4”
Output: “The number 4 is even.”
// Example 2: Odd number
Input: “5”
Output: “The number 5 is odd.”
// Example 3: Invalid input
Input: “abc”
Output: “Please enter a valid number.”

Data Test IDs (required for testing):
* data-testid=”number-input”: The input field for entering number
* data-testid=”check-button”: The button to trigger checking with the text “check”
* data-testid=”loading”: Element showing loading text
* data-testid=”result”: Element displaying the result or error message

https://namastedev.com/practice/even-or-odd

A

styles.css

body {
  margin: 0;
  padding: 0;
  font-family: "Poppins", sans-serif;
  background: linear-gradient(135deg, #e0c3fc, #8ec5fc);
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

/* Container */
.even-odd-container {
  background: rgba(255, 255, 255, 0.2);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-radius: 20px;
  padding: 2rem 3rem;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
  text-align: center;
  width: 360px;
  height: 250px;
}

.even-odd-container:hover {
  transform: scale(1.02);
}

/* Heading */
.title {
  font-size: 2rem;
  font-weight: 600;
  color: #040539;
  margin-bottom: 1.5rem;
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
}

/* Input */
.number-input {
  width: 90%;
  padding: 0.8rem 1rem;
  font-size: 0.8rem;
  border: none;
  border-radius: 12px;
  margin-bottom: 1.2rem;
  background-color: rgba(255, 255, 255, 0.3);
  color: #333;
  backdrop-filter: blur(6px);
  outline: none;
}

.number-input::placeholder {
  color: #555;
}

.number-input:focus {
  background-color: rgba(255, 255, 255, 0.6);
}

/* Button */
.check-button {
  padding: 0.75rem 2rem;
  font-size: 1rem;
  font-weight: 600;
  color: white;
  background: linear-gradient(135deg, #667eea, #764ba2);
  border: none;
  border-radius: 30px;
  cursor: pointer;
  transition: background 0.3s ease;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.2);
  margin-bottom: 1rem;
}

.check-button:hover {
  background: linear-gradient(135deg, #5a67d8, #6b46c1);
}

/* Result Area */
.result-area {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 2rem;
}

/* Loading Text */
.loading {
  font-size: 1rem;
  font-style: italic;
  color: #938cb4;
}

/* Final Result Text */
.result {
  margin-top: 1rem;
  font-size: 1.1rem;
  font-weight: 500;
  color: #0c013f;
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
}

EvenorOdd.js

import React, { useState } from "react";
import "./styles.css";

function EvenOrOddChecker() {
  const [inputValue, setInputValue] = useState("");
  const [result, setResult] = useState("");
  const [loading, setLoading] = useState(false);

  const handleCheck = () => {
    const trimmed = inputValue.trim();

    // Clear previous result immediately
    setResult("");
    setLoading(true);

    // Validate input
    if (trimmed === "" || isNaN(trimmed)) {
      setLoading(false);
      setResult("Please enter a valid number.");
      return;
    }

    // Simulate 1-second processing delay
    setTimeout(() => {
      setLoading(false);
      const number = Number(trimmed);
      const isEven = number % 2 === 0;
      setResult(`The number ${number} is ${isEven ? "even" : "odd"}.`);
    }, 1000);
  };

  return (
    <div className="even-odd-container">
      <h1 className="title">Even or Odd Checker</h1>

      <input
        className="number-input"
        type="text"
        placeholder="Enter a number"
        data-testid="number-input"
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
      />

      <button
        className="check-button"
        data-testid="check-button"
        onClick={handleCheck}
      >
        Check
      </button>

      <div className="result-area">
        {loading ? (
          <div className="loading" data-testid="loading">Checking...</div>
        ) : (
          result && (
            <div className="result" data-testid="result">{result}</div>
          )
        )}
      </div>
    </div>
  );
}

export default EvenOrOddChecker;

App.js

import EvenOrOdd from './EvenOrOdd'
export default function App() {
  return <EvenOrOdd/>
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Filter Recipes

Description:
You are tasked with creating a simple recipe filter and cart system. You will be given a list of recipes (with information like name, rating, cuisine, and image), and you need to build a component that allows users to filter recipes by rating, view the average rating of the filtered recipes, and add recipes to a shopping cart.

Requirements:
1. Recipe Filter:
You need to filter recipes based on a rating threshold.
Users should be able to select a minimum rating from a dropdown (with the options: 4. 0+, 4.3+, 4.5+, 4.7+, and 4.9).
Only recipes with a rating greater than or equal to the selected rating should be displayed.
2. Cart System:
Each recipe displayed should have an “Add to Cart” button. When clicked, the recipe should be added to the cart.
The cart should show the number of items added.
There is no need to show the cart details, only the count of items in the cart.
3. Average Rating Calculation:
You need to calculate the average rating of the filtered recipes. The average should be displayed on the page.
If there are no recipes in the filtered list, show the average rating as 0.00.

**Functional Requirements **
1. Recipe Filter
* Provide a dropdown filter labeled “Filter by Rating:” .
* The dropdown should include the following options:
4.0+, 4.3+, 4.5+, 4.7+, and 4.9.
* Only recipes with a rating greater than or equal to the selected rating should be displayed.
2. Cart System
* Each recipe should include a clearly labeled “Add to Cart” button.
* Clicking the button should add the recipe to a cart and update the item count.
* The total number of items in the cart should be displayed in the format: “Cart Items: 0”, “Cart Items: 1”, etc.
* Cart details (like recipe names, do not need to be shown-only the count is required.
3. Average Rating
* The component should display the average rating of the currently filtered recipes.
* The average should be shown in two decimal places, e.g., Average Rating: 4.87.
* If no recipes match the selected rating filter, display:
Average Rating: 0.00.

https://namastedev.com/practice/filter-recipes

A

styles.css

.app-container {
  padding: 2rem;
  font-family: Arial, sans-serif;
  text-align: center;
}

.controls {
  margin-bottom: 1rem;
}

.summary {
  margin: 1rem 0;
  font-size: 1.1rem;
}

.recipes-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1.5rem;
  margin-top: 1.5rem;
}

.recipe-card {
  background: #fdfdfd;
  padding: 1rem;
  border: 1px solid #ddd;
  border-radius: 12px;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.07);
}

.recipe-img {
  width: 100%;
  height: 140px;
  object-fit: cover;
  border-radius: 8px;
  margin-bottom: 0.75rem;
}

.recipe-card button {
  padding: 0.5rem 1rem;
  margin-top: 0.5rem;
  background-color: #5cb85c;
  border: none;
  border-radius: 6px;
  color: white;
  font-weight: bold;
  cursor: pointer;
}

.recipe-card button:hover {
  background-color: #4cae4c;
}

App.js

import "./styles.css";
import RecipeFilterApp from "./RecipeFilterApp.js";

export default function App() {
  return <RecipeFilterApp />;
}

RecipeFilterApp.js

import React, { useState } from "react";
import recipesData from "./recipesData";
import "./styles.css";

const ratingOptions = [4.0, 4.3, 4.5, 4.7, 4.9];

const RecipeFilterApp = () => {
  const [minRating, setMinRating] = useState(4.0);
  const [cartCount, setCartCount] = useState(0);

  const filteredRecipes = recipesData.filter(
    (recipe) => recipe.rating >= minRating
  );

  const averageRating = filteredRecipes.length
    ? (
        filteredRecipes.reduce((sum, recipe) => sum + recipe.rating, 0) /
        filteredRecipes.length
      ).toFixed(2)
    : "0.00";

  const handleAddToCart = () => {
    setCartCount((prev) => prev + 1);
  };

  return (
    <div className="app-container">
      <h1>🍽️ Recipe Explorer</h1>

      <div className="controls">
        <label htmlFor="rating-filter">Filter by Rating: </label>
        <select
          id="rating-filter"
          value={minRating}
          onChange={(e) => setMinRating(parseFloat(e.target.value))}
        >
          {ratingOptions.map((option) => (
            <option key={option} value={option}>
              {option}+
            </option>
          ))}
        </select>
      </div>

      <div className="summary">
        <p><strong>Cart Items:</strong> {cartCount}</p>
        <p><strong>Average Rating:</strong> {averageRating}</p>
      </div>

      <div className="recipes-grid">
        {filteredRecipes.map((recipe) => (
          <div key={recipe.id} className="recipe-card">
            <img src={recipe.image} alt={recipe.name} className="recipe-img" />
            <h3>{recipe.name}</h3>
            <p>Cuisine: {recipe.cuisine}</p>
            <p>Rating: {recipe.rating} ⭐ ({recipe.reviewCount} reviews)</p>
            <button onClick={handleAddToCart}>Add to Cart</button>
          </div>
        ))}
        {filteredRecipes.length === 0 && <p>No recipes found for this rating.</p>}
      </div>
    </div>
  );
};

export default RecipeFilterApp;

recipesData.js

export default recipesData = [
  {
    id: 1,
    name: "Classic Margherita Pizza",
    cuisine: "Italian",
    image: "https://cdn.dummyjson.com/recipe-images/1.webp",
    rating: 4.6,
    reviewCount: 98,
  },
  {
    id: 2,
    name: "Vegetarian Stir-Fry",
    cuisine: "Asian",
    image: "https://cdn.dummyjson.com/recipe-images/2.webp",
    rating: 4.7,
    reviewCount: 26,
  },
  {
    id: 3,
    name: "Chocolate Chip Cookies",
    cuisine: "American",
    image: "https://cdn.dummyjson.com/recipe-images/3.webp",
    rating: 4.9,
    reviewCount: 13,
  },
  {
    id: 4,
    name: "Chicken Alfredo Pasta",
    cuisine: "Italian",
    image: "https://cdn.dummyjson.com/recipe-images/4.webp",
    rating: 4.9,
    reviewCount: 82,
  },
  {
    id: 5,
    name: "Mango Salsa Chicken",
    cuisine: "Mexican",
    image: "https://cdn.dummyjson.com/recipe-images/5.webp",
    rating: 4.9,
    reviewCount: 63,
  },
  {
    id: 6,
    name: "Quinoa Salad with Avocado",
    cuisine: "Mediterranean",
    image: "https://cdn.dummyjson.com/recipe-images/6.webp",
    rating: 4.4,
    reviewCount: 59,
  },
  {
    id: 7,
    name: "Tomato Basil Bruschetta",
    cuisine: "Italian",
    image: "https://cdn.dummyjson.com/recipe-images/7.webp",
    rating: 4.7,
    reviewCount: 95,
  },
  {
    id: 8,
    name: "Beef and Broccoli Stir-Fry",
    cuisine: "Asian",
    image: "https://cdn.dummyjson.com/recipe-images/8.webp",
    rating: 4.7,
    reviewCount: 58,
  },
  {
    id: 9,
    name: "Caprese Salad",
    cuisine: "Italian",
    image: "https://cdn.dummyjson.com/recipe-images/9.webp",
    rating: 4.6,
    reviewCount: 82,
  },
  {
    id: 10,
    name: "Shrimp Scampi Pasta",
    cuisine: "Italian",
    image: "https://cdn.dummyjson.com/recipe-images/10.webp",
    rating: 4.3,
    reviewCount: 5,
  },
];
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Focus Input

Description:
You are tasked with building a simple React component that demonstrates how to programmatically focus an input element using the useRef hook.
Create a functional component called InputFocus that:
* Renders a text input and a button.
* When the button is clicked, the input should automatically receive focus.
* Uses the useRef hook to reference ine input element directly and call . focus () on it.

Requirements:
1. Use the useRef hook to get a reference to the input element.
2. The input must have placeholder “Type here”.
3. The button must be labelled “Focus input”.

Example Behavior:
* On page load, the input is not focused.
* When the user clicks the “Focus Input” button, the text cursor appears inside the Input field, ready for typing.

A

styles.css

body {
  font-family: sans-serif;
  -webkit-font-smoothing: auto;
  -moz-font-smoothing: auto;
  -moz-osx-font-smoothing: grayscale;
  font-smoothing: auto;
  text-rendering: optimizeLegibility;
  font-smooth: always;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
}

h1 {
  font-size: 1.5rem;
}

InputFocus.js

import React, { useRef } from 'react';

function InputFocus() {
  const inputRef = useRef(null); // Step 1: create the ref

  const handleFocus = () => {
    if (inputRef.current) {
      inputRef.current.focus(); // Step 4: focus the input
    }
  };

  return (
    <div style={{ padding: '20px', textAlign: 'center' }}>
      <input
        ref={inputRef} // Step 3: attach the ref
        type="text"
        placeholder="Type here"
        style={{ padding: '8px', fontSize: '16px', marginRight: '10px' }}
      />
      <button
        onClick={handleFocus} // Step 4: handle button click
        style={{ padding: '8px 12px' }}
      >
        Focus Input
      </button>
    </div>
  );
}

export default InputFocus;

App.js

import InputFocus from './InputFocus'
export default function App() {
  return <InputFocus/>
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Blog Post

Description:
You are building a blog Ul for a content platform. The platform stores a list of blog posts, each with a title, description (body). tags, views, and reactions (likes and dislikes).
Your task is to create a React application that displays this data in a clean, structured format using a reusable PostCard component for each blog post.

Functional Requirements:
1. Create a component named PostCard that accepts the following props:
title (string)
body (string)
tags (array of strings)
reactions (object with Likes angdis likes)
views (number)
2. Each card should:
Display the title and body.
Display the number of likes πŸ‘ dislikes πŸ‘Ž, and total views πŸ‘οΈ.
3. You are provided with the blog post data in a separate file named postData.js. Your application should import this data and display the posts accordingly.

https://namastedev.com/practice/blog-post

A

styles.css

body {
  font-family: sans-serif;
  background-color: #fafafa;
  color: #333;
}

h2 {
  text-align: center;
}

App.js

import "./styles.css";
import BlogPosts from "./BlogPosts.js";

export default function App() {
  return <BlogPosts />;
}

PostsData.js

// postsData.js
export default [
  {
    id: 1,
    title: "His mother had always taught him",
    body: "His mother had always taught him not to ever think of himself as better than others...",
    tags: ["history", "american", "crime"],
    reactions: { likes: 192, dislikes: 25 },
    views: 305,
    userId: 121,
  },
  {
    id: 2,
    title: "He was an expert but not in a discipline",
    body: "He was an expert but not in a discipline that anyone could fully appreciate...",
    tags: ["french", "fiction", "english"],
    reactions: { likes: 859, dislikes: 32 },
    views: 4884,
    userId: 91,
  },
  {
    id: 3,
    title: "Dave watched as the forest burned up on the hill.",
    body: "Dave watched as the forest burned up on the hill, only a few miles from her house. The car had been hastily packed and Marta was inside trying to round up the last of the pets. Dave went through his mental list of the most important papers and documents that they couldn't leave behind. He scolded himself for not having prepared these better in advance and hoped that he had remembered everything that was needed. He continued to wait for Marta to appear with the pets, but she still was nowhere to be seen.",
    tags: ["magical", "history", "french"],
    reactions: {
      likes: 1448,
      dislikes: 39,
    },
    views: 4152,
    userId: 16,
  },
  {
    id: 4,
    title: "All he wanted was a candy bar.",
    body: "All he wanted was a candy bar. It didn't seem like a difficult request to comprehend, but the clerk remained frozen and didn't seem to want to honor the request. It might have had something to do with the gun pointed at his face.",
    tags: ["mystery", "english", "american"],
    reactions: {
      likes: 359,
      dislikes: 18,
    },
    views: 4548,
    userId: 47,
  },
  {
    id: 5,
    title: "Hopes and dreams were dashed that day.",
    body: "Hopes and dreams were dashed that day. It should have been expected, but it still came as a shock. The warning signs had been ignored in favor of the possibility, however remote, that it could actually happen. That possibility had grown from hope to an undeniable belief it must be destiny. That was until it wasn't and the hopes and dreams came crashing down.",
    tags: ["crime", "mystery", "love"],
    reactions: {
      likes: 119,
      dislikes: 30,
    },
    views: 626,
    userId: 131,
  },
  {
    id: 6,
    title: "Dave wasn't exactly sure how he had ended up",
    body: "Dave wasn't exactly sure how he had ended up in this predicament. He ran through all the events that had lead to this current situation and it still didn't make sense. He wanted to spend some time to try and make sense of it all, but he had higher priorities at the moment. The first was how to get out of his current situation of being naked in a tree with snow falling all around and no way for him to get down.",
    tags: ["english", "classic", "american"],
    reactions: {
      likes: 15,
      dislikes: 8,
    },
    views: 38,
    userId: 98,
  },
  {
    id: 7,
    title: "This is important to remember.",
    body: "This is important to remember. Love isn't like pie. You don't need to divide it among all your friends and loved ones. No matter how much love you give, you can always give more. It doesn't run out, so don't try to hold back giving it as if it may one day run out. Give it freely and as much as you want.",
    tags: ["magical", "crime"],
    reactions: {
      likes: 127,
      dislikes: 26,
    },
    views: 168,
    userId: 70,
  },
  {
    id: 8,
    title: "One can cook on and with an open fire.",
    body: "One can cook on and with an open fire. These are some of the ways to cook with fire outside. Cooking meat using a spit is a great way to evenly cook meat. In order to keep meat from burning, it's best to slowly rotate it.",
    tags: ["american", "english"],
    reactions: {
      likes: 1271,
      dislikes: 36,
    },
    views: 2116,
    userId: 67,
  },
  {
    id: 9,
    title: "There are different types of secrets.",
    body: "There are different types of secrets. She had held onto plenty of them during her life, but this one was different. She found herself holding onto the worst type. It was the type of secret that could gnaw away at your insides if you didn't tell someone about it, but it could end up getting you killed if you did.",
    tags: ["american", "history", "magical"],
    reactions: {
      likes: 703,
      dislikes: 18,
    },
    views: 2235,
    userId: 82,
  },
  {
    id: 10,
    title: "They rushed out the door.",
    body: "They rushed out the door, grabbing anything and everything they could think of they might need. There was no time to double-check to make sure they weren't leaving something important behind. Everything was thrown into the car and they sped off. Thirty minutes later they were safe and that was when it dawned on them that they had forgotten the most important thing of all.",
    tags: ["fiction", "magical", "history"],
    reactions: {
      likes: 455,
      dislikes: 3,
    },
    views: 4504,
    userId: 144,
  },
];

BlogPosts.js

// BlogPosts.js
import React from "react";
import postsData from "./postsData";
import PostCard from "./PostCard";

export default function BlogPosts() {
  return (
    <div style={{ padding: "20px", maxWidth: "800px", margin: "0 auto" }}>
      <h2>Blog Posts</h2>
      {postsData.map((post) => (
        <PostCard
          key={post.id}
          title={post.title}
          body={post.body}
          tags={post.tags}
          reactions={post.reactions}
          views={post.views}
        />
      ))}
    </div>
  );
}

PostCard.js

// PostCard.js
//πŸ‘ likes | πŸ‘Ž dislikes | πŸ‘οΈ views
import React from "react";

const PostCard = ({ title, body, tags, reactions, views }) => {
  return (
    <div style={styles.card}>
      <h3>{title}</h3>
      <p>{body}</p>
      <div style={styles.tags}>
        {tags.map((tag, index) => (
          <span key={index} style={styles.tag}>
            #{tag}
          </span>
        ))}
      </div>
      <div style={styles.meta}>
        <span>πŸ‘ {reactions.likes}</span>
        <span>πŸ‘Ž {reactions.dislikes}</span>
        <span>πŸ‘οΈ {views}</span>
      </div>
    </div>
  );
};

const styles = {
  card: {
    border: "1px solid #ccc",
    padding: "16px",
    marginBottom: "16px",
    borderRadius: "8px",
    backgroundColor: "#ccc9c9",
  },
  meta: {
    display: "flex",
    gap: "16px",
    marginTop: "8px",
    fontWeight: "bold",
  },
  tags: {
    marginTop: "10px",
  },
  tag: {
    marginRight: "8px",
    color: "blue",
    padding: "4px 8px",
    borderRadius: "4px",
    fontSize: "12px",
  },
};

export default PostCard;
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Holy Grail

Description:
The Holy Grail layout is a classic web page structure that has been a common layout pattern since the early days of web design. It consists of a full-width header at the top, a full-width footer at the bottom, and a three-column content area in the center: a fixed-width left sidebar (commonly used for navigation), a flexible main content area in the center, and a fixed-width right sidebar (often used for ads or additional content).
This layout presents a real-world use case that combines semantic HTML5 elements with modern CSS layout techniques using Flexbox.
In this challenge, you will build a reusable HolyGrailLayout component using React functional components and CSS. The component must follow semantic
HTML5 structure:
* <header> - Appears at the top of the page, typically used for branding or navigation.
* <aside> - Represents side content such as navigation (left) or advertisements (right).
* <main> - Contains the primary content for the page.
* <footer> - Appears at the bottom of the page and typically includes footer links or legal information.

Requirements:
* Component Structure:
A single React component: HolyGrailLayout
Contains the following layout structure:
Header at the top (60px tall)
Footer at the bottom (100px tall)
Three-column body in between:
Left Sidebar (<aside>) - Fixed width: 100px
Center Column (<main>) - Flexible width
Right Sidebar (<aside>) - Fixed width: 100px
* Ul Behavior:
All columns should maintain the same height regardless of content A
The footer should stick to the bottom of the viewport, even if the page has little content The layout must be responsive and maintain proportions when resized

Styling Instructions
* You must use the given classNames “container” and
“columns” given in the default template to apply styling.

Expected Output:
A professional, full-height layout that demonstrates proper use of semantic HTML5 elements with modern CSS. The layout should visually reflect:
* A dark header at the top (60px height)
* A light-colored content section with three columns:
Left column for Navigation (100px wide)
Center column for Main Content (expands to fill space)
Right columisfor Sidebar (100px wide)
* A dark footer at the bottom (100px height) that remains pinned to the bottom of the screen
This should work across various screen sizes and ensure all columns match in height visually.

https://namastedev.com/practice/holy-grail

A

HolyGrail.jsx

import React from "react";
import "./HolyGrail.css";

export default function HolyGrail() {
  return (
    <div className="container">
      <header>Header</header>
      <div className="columns">
        <nav>Navigation</nav>
        <main>Main</main>
        <aside>Sidebar</aside>
      </div>
      <footer>Footer</footer>
    </div>
  );
}

HolyGrail.css

html,
body {
  margin: 0;
  height: 100%;
  font-family: sans-serif;
  font-size: 12px;
  font-weight: bold;
}

* {
  box-sizing: border-box;
}

/* Overall container should fill full height of the viewport */
.container {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* Header and Footer */
header {
  background-color: tomato;
  height: 60px;
}

footer {
  background-color: slategray;
  height: 100px;
}

/* Columns: nav, main, aside */
.columns {
  display: flex;
  flex: 1; /* Fill remaining space between header and footer */
}

/* Left Sidebar (nav) */
nav {
  background-color: coral;
  width: 100px;
}

/* Center Column */
main {
  background-color: moccasin;
  flex: 1; /* Take remaining horizontal space */
}

/* Right Sidebar */
aside {
  background-color: sandybrown;
  width: 100px;
}

/* Optional: Padding for each section */
header,
nav,
main,
aside,
footer {
  padding: 12px;
}

App.css

import HolyGrail from './HolyGrail.jsx'
export default function App() {
  return <HolyGrail/>
}
17
Q

User Profile

Description
Create a class-based React component called UserProfile that displays a user’s name and a button to toggle visibility of their bio.

Requirements
* Use a class component.
* The component should:
Display the user’s name.
Display the user’s image.
* Contains a “Show Bio” / “Hide Bio” button to toggle the bio visibility.
* When the button is clicked for the first time:
The user’s bio is displayed below the button.
The button text changes from “Show Bio” to “Hide Bio”.
* When the button is clicked again:
The bio is hidden.
The button text switches back to “Show Bio”.

Data to use

const user = {
  name: 'Jane Doe',
  bio: 'Frontend developer who loves React and coffee β˜•οΈ',
  image: 'https://do6gp1uxl3luu.cloudfront.net/question-webp/dummyUser.jpg'
};
A

styles.css

button {
  padding: 10px 16px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-size: 14px;
}

button:hover {
  background-color: #0056b3;
}

.user-profile {
  max-width: 400px;
    margin: 50px auto;
    border: 2px solid #ddd;
    border-radius: 8px; 
    background-color: #f9f9f9;
    text-align: center;
    padding: 20px;
    font-family: Arial, sans-serif;
}

.profile-img {
  width: 120px;
  height: 120px;
  object-fit: cover;
  border-radius: 50%;
  margin-bottom: 15px;
  box-shadow: 0 0 8px rgba(0, 0, 0, 0.1);
}

UserProfile.js

import React, { Component } from 'react';
import './styles.css';

const user = {
  name: 'Jane Doe',
  bio: 'Frontend developer who loves React and coffee β˜•οΈ',
  image: 'https://do6gp1uxl3luu.cloudfront.net/question-webp/dummyUser.jpg'
};

class UserProfile extends Component {
  constructor(props) {
    super(props);
    this.state = {
      showBio: false
    };
  }

  toggleBio = () => {
    this.setState((prevState) => ({
      showBio: !prevState.showBio
    }));
  };

  render() {
    const { showBio } = this.state;

    return (
      <div className="user-profile">
        <img src={user.image} alt={user.name} className="profile-img" />
        <h2>{user.name}</h2>
        <button onClick={this.toggleBio}>
          {showBio ? 'Hide Bio' : 'Show Bio'}
        </button>
        {showBio && <p>{user.bio}</p>}
      </div>
    );
  }
}

export default UserProfile;

App.js

import UserProfile from './UserProfile'
export default function App() {
  return <UserProfile/>
}
18
Q

Contact Form

Create a Contact Form Component that allows users to enter their name, email, and a message, and submit the form. Display a confirmation message after a successful submission.
Requirements
1. The form must contain three fields: name, email, and message and must have labels “Name :”, “Email :”, “Message:”.
2. All fields are required.
3. The email field must be validated to ensure proper format.
4. On submission, show a “Thank you, User” message, where User is the entered name.
5. If you try to submit the form with any of the fields empty, it will prevent submission and show an error message like:
* “Name is required” for the name field.
* “Email is required” for the email field.
* “Message is required” for the message field.
6. If the email is not in valid format show an error message, “Invalid emall format”,

Constraints & Edge Cases
* Constraint 1: Name, email, and message are mandatory fields.
* Constraint 2: Email must be in valid format.
* Edge Case 1: User submits without filling fields β†’ show error.
* Edge Case 2: User enters invalid email β†’ show specific email error.
* Edge Case 3: After successful submission, fields should reset.

https://namastedev.com/practice/contact-form

A

styles.css

body {
  font-family: sans-serif;
  -webkit-font-smoothing: auto;
  -moz-font-smoothing: auto;
  -moz-osx-font-smoothing: grayscale;
  font-smoothing: auto;
  text-rendering: optimizeLegibility;
  font-smooth: always;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
}

h1 {
  font-size: 1.5rem;
}

ContactForm.js

import React, { useState, useRef } from "react";
import './styles.css';

const isEmpty = (obj) => {
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            return false;
        }
    }
    return true;
};

function ContactForm() {
    const [formData, setFormData] = useState({
        name: '',
        email: '',
        message: ''
    });

    const [errors, setErrors] = useState({});
    const [submitted, setSubmitted] = useState(false);
    const submittedNameRef = useRef('');

    const validate = () => {
        const newErrors = {};
        const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

        if (!formData.name.trim()) {
            newErrors.name = 'Name is required';
        }

        if (!formData.email.trim()) {
            newErrors.email = 'Email is required';
        } else if (!emailRegex.test(formData.email)) {
            newErrors.email = 'Invalid email format';
        }

        if (!formData.message.trim()) {
            newErrors.message = 'Message is required';
        }

        return newErrors;
    };

    const handleChange = (e) => {
        setFormData({
            ...formData,
            [e.target.name]: e.target.value
        });

        // Clear errors while typing
        setErrors({
            ...errors,
            [e.target.name]: ''
        });

        // clear confirmation if any on typing
        setSubmitted(false);
    };

    const handleSubmit = (e) => {
        e.preventDefault();
        const validationErrors = validate();

        if (!isEmpty(validationErrors)) {
            setErrors(validationErrors);
            setSubmitted(false);
        } else {
            submittedNameRef.current = formData.name;
            setSubmitted(true);
            // clear input on submission
            setFormData({ name: '', email: '', message: '' });
            setErrors({});
        }
    };

    return (
        <div style={{ maxWidth: '500px', margin: '50px auto' }}>
            <h1>Contact Us</h1>
            {submitted && (
                <p style={{ color: 'green', fontWeight: 'bold' }}>
                    Thank you, {submittedNameRef.current || 'User'}!
                </p>
            )}
            <form onSubmit={handleSubmit} noValidate>
                <div style={{ marginBottom: '15px' }}>
                    <label>Name :</label><br />
                    <input
                        type="text"
                        name="name"
                        value={formData.name}
                        onChange={handleChange}
                        style={{ width: '100%', padding: '8px' }}
                    />
                    {errors.name && <p style={{ color: 'red' }}>{errors.name}</p>}
                </div>

                <div style={{ marginBottom: '15px' }}>
                    <label>Email :</label><br />
                    <input
                        type="text"
                        name="email"
                        value={formData.email}
                        onChange={handleChange}
                        style={{ width: '100%', padding: '8px' }}
                    />
                    {errors.email && <p style={{ color: 'red' }}>{errors.email}</p>}
                </div>

                <div style={{ marginBottom: '15px' }}>
                    <label>Message:</label><br />
                    <textarea
                        name="message"
                        value={formData.message}
                        onChange={handleChange}
                        rows="4"
                        style={{ width: '100%', padding: '8px' }}
                    />
                    {errors.message && <p style={{ color: 'red' }}>{errors.message}</p>}
                </div>

                <button type="submit" style={{ padding: '10px 16px', backgroundColor: '#007bff', color: 'white', border: 'none', borderRadius: '6px', cursor: 'pointer' }}>
                    Submit
                </button>
            </form>
        </div>
    );
}

export default ContactForm;

App.js

import ContactForm from "./ContactForm";

export default function App() {
    return <ContactForm />;
}
19
Q

Password Strength

Description
Build a password strength checker in React that evaluates and displays the strength level of a user’s password. The goal of this problem is to create a password strength checker that evaluates the strength of a given password based on specific criteria. The password is considered strong if it meets all or 4 of the following rules:
1. Length: At least & characters.
2. Uppercase Letters: At least one uppercase letter (A-Z).
3. Lowercase Letters: At least one lowercase letter (a-z).
4. Numbers: At least one digit (0-9).
5. Special Characters: At least one special character (e.g., @, #, $,%, etc.).

Strength Levels:
* Level 1: Password meets only 1 of the 5 criteria
* Level 2: Password meets 2 or 3 of the 5 criteria
* Level 3: Password meets 4 or 5 of the 5 criteria
* If the password does not meet any criteria, it’s considered a weak password and the function returns “ Weak Password “.

Important Instructions
* Define a helper function called
checkPasswordStrength inside the same file.
* Export that helper function so it can be tested separately
* The function checkPasswordStrength receives a password string as an argument.
* The function checkPasswordStrength and returns Level
1, Level 2, Level 3 or Weak Password based on the criteria.
* The Ul should have:
An input field for password A button to check strength
A strength result displayed after clicking

Example Inputs & Outputs
Example 1:
* Input: “’
* Output: “Weak Password”
* Explanation: The password is empty, so it doesn’t meet any criteria.
Example 2:
* Input: “abc123”
* Output: “Level 1”
* Explanation: The password contains lowercase letters and numbers but doesn’t meet the other criteria (uppercase, special character).
Example 3:
* Input: “abc123ABC”
* Output: “Level 2”
* Explanation: The password meets 3 criteria: length (>=8), lowercase, and numbers, but lacks a special character.
Example 4:
* Input: “Abc12345”
* Output: “Level 2”
* Explanation: The password meets 4 criteria: length, uppercase, lowercase, and numbers, but lacks a special character.
Example 5:
* Input: “Abc@1234”
* Output: “Level 3”
* Explanation: The password meets all 5 criteria: length (=8), uppercase, lowercase, numbers, and special character.

https://namastedev.com/practice/password-strength

A

styles.css

body {
  font-family: sans-serif;
  -webkit-font-smoothing: auto;
  -moz-font-smoothing: auto;
  -moz-osx-font-smoothing: grayscale;
  font-smoothing: auto;
  text-rendering: optimizeLegibility;
  font-smooth: always;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
}

h1 {
  font-size: 1.5rem;
}

PasswordStrength.jsx

import React, { useState } from 'react';
import './styles.css';

// βœ… Exported for testing
export const checkPasswordStrength = (password) => {
  let score = 0;

  const lengthCheck = password.length >= 8;
  const upperCheck = /[A-Z]/.test(password);
  const lowerCheck = /[a-z]/.test(password);
  const numberCheck = /[0-9]/.test(password);
  const specialCharCheck = /[!@#$%^&*(),.?":{}|<>]/.test(password);

  if (lengthCheck) score++;
  if (upperCheck) score++;
  if (lowerCheck) score++;
  if (numberCheck) score++;
  if (specialCharCheck) score++;

  if (score === 0) return "Weak Password";
  else if (score === 1) return "Level 1";
  else if (score === 2 || score === 3) return "Level 2";
  else return "Level 3";
};

const PasswordStrength = () => {
  const [password, setPassword] = useState('');
  const [strength, setStrength] = useState('');

  const handleCheck = () => {
    const result = checkPasswordStrength(password);
    setStrength(result);
  };

  return (
    <div style={{ maxWidth: '400px', margin: '50px auto', textAlign: 'center' }}>
      <h2>Password Strength Checker</h2>
      <input
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        placeholder="Enter password"
        style={{
          padding: '10px',
          width: '100%',
          marginBottom: '10px',
          fontSize: '16px'
        }}
      />
      <br />
      <button
        onClick={handleCheck}
        style={{
          padding: '10px 20px',
          fontSize: '14px',
          backgroundColor: '#007bff',
          color: 'white',
          border: 'none',
          borderRadius: '6px',
          cursor: 'pointer'
        }}
      >
        Check Strength
      </button>
      {strength && (
        <p style={{ marginTop: '20px', fontWeight: 'bold' }}>{strength}</p>
      )}
    </div>
  );
};

export default PasswordStrength;

App.js

import PasswordStrength from './PasswordStrength'
export default function App() {
  return <PasswordStrength/>
}
20
Q

Toggle Password

Description
Create a react component that allows users to input a password. It should toggle password visibility in a secure and accessible way along with a label indicating the visibility status. It should have live toggling using an eye icon.

Requirements
* The input must:
Securely accept user-entered text.
Have a placeholder: “Enter password”.
Be focusable and editable at all times.
Always show the placeholder text when empty.
* By default:
Password should be hidden (masked).
* Visibility toggle icon:
Uses lucide-react icons.
Shows Eye icon when the password is hidden.
Shows Eyeoff icon when the password is visible.
* On clicking the icon:
Toggle the visibility of the password between masked and unmasked.
Instantly update both:
The icon (Eye β†’ EyeOff).
The label (described below).
* A label must appear below the input field showing:
“Password Hidden” when the password is masked.
“Password Visible” when the password is unmasked.

Data Test IDs (Required for Testing)
* data-testid=”password-input”: The password input field
* data-testid=”toggle-icon”: Element wrapping the eye icon used to toggle password visibility
* data-testid=”visibility-label”: Text label showing whether password is visible or hidden

https://namastedev.com/practice/toggle-password

A

styles.css

body {
  margin: 0;
  font-family: "Poppins", sans-serif;
  background-color: #f0f0f0;
}

.container {
  text-align: center;
  height: 100vh;
  width: 100vw;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

h1 {
  font-size: 30px;
  margin-bottom: 20px;
  color: #000000;
}

.password-wrapper {
  position: relative;
  width: 290px;
}

input[type="password"],
input[type="text"] {
  width: 100%;
  padding: 10px 35px 10px 10px;
  font-size: 16px;
  border: 1px solid #ccc;
  border-radius: 6px;
  outline: none;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
  background-color: white;
}

.icon {
  position: absolute;
  right: -30px;
  top: 50%;
  transform: translateY(-50%);
  cursor: pointer;
  color: #888;
}

.icon:hover {
  color: #000;
}

.visibility-label {
  display: block;
  margin-top: 6px;
  font-size: 13px;
  color: #888;
  text-align: left;
  width: 280px;
}

App.js

import TogglePassword from './TogglePassword'
export default function App() {
  return <TogglePassword/>
}

TogglePassword.jsx

import React, { useState } from "react";
import { Eye, EyeOff } from "lucide-react";
import "./styles.css";

function TogglePassword() {
  const [visible, setVisible] = useState(false);
  const [password, setPassword] = useState("");

  const toggleVisibility = () => {
    setVisible((prev) => !prev);
  };

  return (
    <div className="container">
      <h1 className="title">Toggle Password</h1>
      <div className="password-wrapper">
        <input
          type={visible ? "text" : "password"}
          placeholder="Enter password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          data-testid="password-input"
        />
        <span
          className="icon"
          onClick={toggleVisibility}
          data-testid="toggle-icon"
        >
          {visible ? <EyeOff size={18} /> : <Eye size={18} />}
        </span>
      </div>
      <span className="visibility-label" data-testid="visibility-label">
        {visible ? "Password Visible" : "Password Hidden"}
      </span>
    </div>
  );
}

export default TogglePassword;
21
Q

Age Calculator

Description
Create a responsive Age Calculator component that calculates a user’s age in years, months, and days based on a selected or entered birthdate.

Requirements
* A label “Enter/Select a birthdate” indicating the user to either input manually or select a date from the datepicker.
* The interface must include:
An input field with the placeholder of the format (dd-mm-yyyy or mm-dd-yyyy)
The input should use the browser’s built-in datepicker to allow users to manually select day, month, and year.
A button “Calculate Age”
* A display area below the button which will show the results or the errors
* Behavior on clicking the Calculate Age button:
If valid:
Display the result in the format:
“X years, Y months, Z days”
If invalid:
Display an error message:
For future dates- “Birthdate cannot be in the future”
For empty input- “Please select a date”

Edge Cases & Constraints
* Input must be a valid past date
* Empty or future dates must show a user-friendly error
* The datepicker must open when clicked
* Age should be calculated using precise difference in years, months, and days
* The calculation must be accurate even across leap years
* Result must update immediately upon clicking
“Calculate”

Testing Requirements
Data Test IDs (Required for Testing):
* data-testid=”input-birthdate” - Date input field
* data-testid=”btn-calculate” - Calculate age button
* data-testid=”age-result” - Display area for result
* data-testid=”error-msg” - Display area for errors
* datatestid=”label-birthdate” -Label associated with the birthdate input

https://namastedev.com/practice/age-calculator

A

styles.css

.conatiner {
  max-width: 380px;
  margin: 3rem auto;
  padding: 2rem 2.5rem;
  background: #d6e8fa;
  border-radius: 12px;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08);
  font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
  color: #222;
  text-align: center;
}

.title {
  font-weight: 700;
  font-size: 1.9rem;
  color: #2c3e50;
  margin-bottom: 1.5rem;
  letter-spacing: 1.1px;
}

.label {
  display: block;
  text-align: left;
  font-weight: 600;
  font-size: 1rem;
  color: #34495e;
  margin-bottom: 0.6rem;
  letter-spacing: 0.7px;
}

.input-date {
  width: 90%;
  padding: 0.6rem 1rem;
  font-size: 1rem;
  border: 1.8px solid #bdc3c7;
  border-radius: 8px;
  box-shadow: inset 1px 1px 4px rgba(0, 0, 0, 0.05);
  color: #2c3e50;
  outline: none;
  margin-bottom: 1.5rem;
  font-weight: 500;
}

.btn-calc {
  width: 80%;
  padding: 0.75rem 1rem;
  font-size: 1.1rem;
  font-weight: 700;
  color: #ffffff;
  background-color: #34495e;
  border: none;
  border-radius: 10px;
  box-shadow: 0 4px 12px rgba(52, 73, 94, 0.5);
  cursor: pointer;
  user-select: none;
}

.error-msg {
  margin-top: 1.4rem;
  color: #e74c3c;
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: 0.6px;
}

.age-result {
  margin-top: 1.4rem;
  font-weight: 600;
  font-size: 1.15rem;
  color: #27ae60;
  letter-spacing: 0.8px;
}

AgeCalculator.js

import React, { useState } from "react";
import "./styles.css";

function AgeCalculator() {
  const [birthdate, setBirthdate] = useState("");
  const [error, setError] = useState("");
  const [result, setResult] = useState("");

  const calculateAge = () => {
    setError("");
    setResult("");

    if (!birthdate) {
      setError("Please select a date");
      return;
    }

    const birth = new Date(birthdate);
    const today = new Date();

    if (birth > today) {
      setError("Birthdate cannot be in the future");
      return;
    }

    let years = today.getFullYear() - birth.getFullYear();
    let months = today.getMonth() - birth.getMonth();
    let days = today.getDate() - birth.getDate();

    if (days < 0) {
      months--;
      const prevMonth = new Date(today.getFullYear(), today.getMonth(), 0);
      days += prevMonth.getDate();
    }

    if (months < 0) {
      years--;
      months += 12;
    }

    setResult(`${years} years, ${months} months, ${days} days`);
  };

  return (
    <div className="conatiner">
      <h2 className="title">Age Calculator</h2>
      <label className="label" htmlFor="birthdate" data-testid="label-birthdate">
        Enter/Select a birthdate
      </label>
      <input
        id="birthdate"
        type="date"
        className="input-date"
        data-testid="input-birthdate"
        value={birthdate}
        onChange={(e) => setBirthdate(e.target.value)}
      />
      <button className="btn-calc" data-testid="btn-calculate" onClick={calculateAge}>
        Calculate Age
      </button>
      {error && <p className="error-msg" data-testid="error-msg">{error}</p>}
      {result && <p className="age-result" data-testid="age-result">{result}</p>}
    </div>
  );
}

export default AgeCalculator;

App.js

import AgeCalculator from './AgeCalculator.js'
export default function App() {
  return <AgeCalculator/>
}
22
Q

Counter using React

Create a React counter with increment, decrement, and reset functionalities.
The component should have three buttons labeled:
* Increment
* Decrement
* Reset
This React component displays a counter that allows users to:
* Increase the count by 1 when clicking the “Increment” button.
* Decrease the count by 1 when clicking the “Decrement” button.
* Reset the count to zero when clicking the “Reset” button.
* Show the current counter value with the text “Counter”.

https://namastedev.com/practice/counter-using-react

A

styles.css

body {
  font-family: sans-serif;
  -webkit-font-smoothing: auto;
  -moz-font-smoothing: auto;
  -moz-osx-font-smoothing: grayscale;
  font-smoothing: auto;
  text-rendering: optimizeLegibility;
  font-smooth: always;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
}

h1 {
  font-size: 1.5rem;
}

Counter.js

// Counter.js
import React, { useReducer } from 'react';
import './styles.css'; // ensure styles are applied

// Reducer function for state transitions
const reducer = (state, action) => {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    case 'reset':
      return { count: 0 };
    default:
      return state;
  }
};

const Counter = () => {
  const [state, dispatch] = useReducer(reducer, { count: 0 });

  return (
    <div style={{ textAlign: 'center', paddingTop: '50px' }}>
      <h2>Counter: {state.count}</h2>
      <div>
        <button style={{margin: "0px 10px"}} onClick={() => dispatch({ type: 'increment' })}>Increment</button>
        <button style={{margin: "0px 10px"}} onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
        <button style={{margin: "0px 10px"}} onClick={() => dispatch({ type: 'reset' })}>Reset</button>
      </div>
    </div>
  );
};

export default Counter;
23
Q

Navbar

Description
Create a simple React application with a navigation bar and two pages using React Router v6. The app should include:
* A Navbar with links to Home and About pages
* Separate components for Home and About pages
* Proper routing such that clicking a link changes the content shown without refreshing the page

Requirements:
1. Use React Router v6 Use react-router-dom to define and manage your routes.
2. Navbar
Use the NavLink component from react-router-dom.
Should contain two links:
Home β†’ Navigates to /
About β†’ Navigates to / about
3. Home Page (Home. js)
Route: /
Content: Welcome to the Home Page
4. About Page (About. js)
Route: / about
Content: Welcome to the About Page
5. App Component (App. js)
Should use BrowserRouter, Routes, and Route from react-router-dom.
Render Navbar and show Home or About based on the current route.

https://namastedev.com/practice/navbar

A

styles.css

body {
  margin: 0;
  font-family: Arial, sans-serif;
  overflow: hidden;
}

.navbar {
  display: flex;
  justify-content: end;
  gap: 20px;
  background-color: #1e1e2f;
  padding: 15px 30px;
}

.nav-item {
  color: white;
  text-decoration: none;
  font-weight: 500;
}

.nav-item.active {
  border-bottom: 2px solid #00bcd4;
}

.page-container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background-color: #f0f8ff;
  text-align: center;
  font-family: Arial, sans-serif;
}

.page-container h2 {
  color: #333;
  font-size: 25px;
  font-weight: bold;
}

App.js

import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Navbar from './Navbar';
import Home from './Home';
import About from './About';

const App = () => {
  return (
    <Router>
      <Navbar />
      <div className="page-content">
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
        </Routes>
      </div>
    </Router>
  );
};

export default App;

Navbar.js

import React from 'react';
import { NavLink } from 'react-router-dom';
import './styles.css';

const Navbar = () => {
  return (
    <nav className="navbar">
      <NavLink to="/" className={({ isActive }) => isActive ? "nav-item active" : "nav-item"}>
        Home
      </NavLink>
      <NavLink to="/about" className={({ isActive }) => isActive ? "nav-item active" : "nav-item"}>
        About
      </NavLink>
    </nav>
  );
};

export default Navbar;

Home.js

import React from 'react';
import './styles.css';  

const Home = () => {
  return (
    <div className="page-container">
      <h2>Welcome to the Home Page</h2>
    </div>
  );
};

export default Home;

About.js

import React from 'react';
import './styles.css';

const About = () => {
  return (
    <div className="page-container">
      <h2>Welcome to the About Page</h2>
    </div>
  );
};

export default About;
24
Q

Tab Switcher

Create a React component named TabSwitcher that displays multiple tabs and allows users to switch between them. Each tab should display corresponding content when selected.

Features
* Displays multiple tab buttons with clear labels.
* Highlights the currently active tab visually.
* Updates the displayed content dynamically when a user clicks a tab.
* Maintains the active tab state internally using React hooks.
* Provides meaningful attributes to facilitate automated testing.

Functionality Requirements
Initial State
* The component should load with the “Home” tab active by default.
* The content area should display:
“Welcome to the Home tab!”
Tabs
The following tabs must be rendered as horizontal buttons:
* Home: Displays “Welcome to the Home tab!”
* Profile: Displays “This is your Profile.”
* Settings: Displays “Adjust your Settings here.”
Switching Tabs
* Clicking on a tab button switches the active tab.
* The content area updates immediately to reflect the selected tab’s content.
* The active tab button should have a distinct visual style (highlighted).
Active Tab Styling
* The active tab button should:
Use a different background color and text color.
* Non-active tabs should:
* Have default styling.
* Include a subtle hover effect.
Repeated Clicks on Active Tab
* Clicking an already active tab:
Should not change the state or content.
Should retain the current content and style.

Edge Cases & Constraints
* Gracefully handle:
Unexpected tab IDs.
Empty or malformed tab arrays.
* Must not cause page reloads or unexpected side effects.
* Must maintain state properly when tabs are clicked rapidly.
* Styling should clearly distinguish between active and inactive tabs.
* Component should be easily extendable to support additional tabs.

Examples of Input and Output
* Initial render
> Content: “Welcome to the Home tab!”
* Click on “Profile” tab
> Content: “This is your Profile.”
* Click on “Settings” tab
> Content: “Adjust your Settings here.”
* Click “Settings” tab again
> Content remains “Adjust your Settings here.”

Testing Requirements
* Verify all tab buttons render correctly.
* Verify default active tab is Home.
* Verify clicking each tab updates the content correctly.
* Verify the active tab button has the proper active styling.
* Verify clicking the same tab multiple times retains content and active style.
* Use data-testid attributes to reliably select elements during tests.

Data Test IDs for Testing
* tab-button-home β€” for the Home tab button
* tab-button-profile - for the Profile tab button
* tab-button-settings - for the Settings tab button
* tab-content - for the content display area

Solution Approach
* Use React functional components with the useState hook to track the currently active tab.
* Store tab data (id, label, content) in an array for easy mapping and rendering.
* Render tab buttons dynamically using Array.map(), assigning the active class conditionally based on the active tab state.
* Handle button clicks to update the active tab state, causing a re-render of the content.
* Display content by finding the active tab object from the array.
* Add meaningful data-testid attributes to support reliable automated testing.
* Style active/inactive tabs distinctly using CSS classes.
* Write tests using @testing-library/react to simulate user interaction and ensure Ul updates correctly.
* Use semantic HTML and ensure usability for keyboard navigation and screen readers.

https://namastedev.com/practice/tab-switcher

A

TabSwitcher.js

import React, { useState } from "react";

// Tab data β€” easily extendable later
const tabs = [
  { id: "home", label: "Home", content: "Welcome to the Home tab!" },
  { id: "profile", label: "Profile", content: "This is your Profile." },
  { id: "settings", label: "Settings", content: "Adjust your Settings here." },
];

export default function TabSwitcher() {
  // State to track the currently active tab (default: "home")
  const [activeTab, setActiveTab] = useState("home");

  // Handle tab click
  const handleTabClick = (tabId) => {
    // Prevent unnecessary state updates if clicking the already active tab
    if (tabId === activeTab) return;
    setActiveTab(tabId);
  };

  // Find the active tab data safely
  const activeTabData =
    tabs.find((tab) => tab.id === activeTab) || tabs[0] || {};

  return (
    <div className="tab-switcher">
      <h1>Tab Switcher</h1>

      {/* Tab Buttons */}
      <div className="tab-buttons">
        {tabs.map((tab) => (
          <button
            key={tab.id}
            className={tab.id === activeTab ? "active" : ""}
            data-testid={`tab-button-${tab.id}`}
            onClick={() => handleTabClick(tab.id)}
            aria-pressed={tab.id === activeTab}
            aria-label={`Switch to ${tab.label} tab`}
          >
            {tab.label}
          </button>
        ))}
      </div>

      {/* Tab Content */}
      <div className="tab-content" data-testid="tab-content">
        {activeTabData.content || "No content available."}
      </div>
    </div>
  );
}

App.js

import React from "react";
import TabSwitcher from "./TabSwitcher";
import "./styles.css";

export default function App() {
  return (
    <div className="App">
      <TabSwitcher />
    </div>
  );
}

styles.css

.tab-switcher {
  max-width: 720px;
  margin: 50px auto;
  padding: 30px 40px;
  background-color: #e6f0f3;
  border-radius: 14px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.1);
  font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
  color: #1f3a3a;
  user-select: none;
}

.tab-switcher h1 {
  font-size: 2.25rem;
  font-weight: 600;
  margin-bottom: 28px;
  color: #134140;
  text-align: center;
  letter-spacing: 1.2px;
}

.tab-buttons {
  display: flex;
  justify-content: center;
  gap: 18px;
  margin-bottom: 30px;
}

.tab-buttons button {
  background-color: #ffffff;
  border: 2px solid transparent;
  border-radius: 8px;
  padding: 12px 28px;
  font-size: 16px;
  font-weight: 600;
  color: #2c5d58;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 3px 8px rgba(47, 79, 79, 0.07);
}

.tab-buttons button:hover {
  background-color: #a1d2ce;
  color: #134140;
  box-shadow: 0 6px 14px rgba(47, 79, 79, 0.12);
  transform: translateY(-2px);
}

.tab-buttons button.active {
  background-color: #147b74;
  color: #e6f0f3;
  border-color: #0f5a56;
  box-shadow: 0 8px 20px rgba(20, 123, 116, 0.6);
  transform: translateY(-3px);
}

.tab-content {
  background-color: #ffffff;
  border-radius: 12px;
  padding: 36px 28px;
  font-size: 18px;
  line-height: 1.6;
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.08);
  color: #1f3a3a; /* dark slate */
  text-align: center;
  min-height: 100px;
  user-select: text;
}
25
# **Back To Top** Create a floating Back to Top button that appears when the user scrolls down the page and, when clicked, smoothly scrolls back to the top. **Things to do** * Add a Back to Top button to the page. * Keep it hidden when the scroll position is near the top. * Show it only when the user scrolls beyond a certain distance (e.g., 500px). * When clicked, smoothly scroll the page to the top. * Make sure the button is positioned so it's always visible on the screen when shown. **Note** * Ensure the page has enough content to allow scrolling (e.g., multiple paragraphs or elements) so that the Back to Top button can be tested. **Testing Instructions** Please use the following data-testid attributes in your React component: * back-to-top-btn β†’ for the Back to Top button ## Footnote https://namastedev.com/practice/back-to-top
BackToTop.js ``` import { useEffect, useState } from "react"; function BackToTop() { const [isVisible, setIsVisible] = useState(false); useEffect(() => { // Function to toggle button visibility based on scroll position const toggleVisibility = () => { if (window.scrollY > 500) { setIsVisible(true); } else { setIsVisible(false); } }; // Add event listener window.addEventListener("scroll", toggleVisibility); // Cleanup listener on unmount return () => { window.removeEventListener("scroll", toggleVisibility); }; }, []); // Smoothly scroll to top when button is clicked const scrollToTop = () => { window.scrollTo({ top: 0, behavior: "smooth", }); }; return (

Back To Top

{/* Add content to make the page scrollable */}
{[...Array(20)].map((_, index) => (

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus luctus urna sed urna ultricies ac tempor dui sagittis. In condimentum facilisis porta. Sed nec diam eu diam mattis viverra. Nulla fringilla, orci ac euismod semper, magna diam porttitor mauris, quis sollicitudin sapien justo in libero.

))}
{isVisible && ( )}
); } export default BackToTop; ``` App.js ``` import BackToTop from './BackToTop.js' export default function App() { return } ``` styles.css ``` .backToTop { margin-bottom: 2.5rem; text-align: center; } .backtotop-btn { position: fixed; bottom: 20px; right: 20px; font-size: 14px; padding: 10px 15px; cursor: pointer; } ```
26
# **Leap Year** Create a responsive Leap Year Checker component that lets a user input a year and check whether it is a leap year. **Requirements** * A label "Enter a year:" indicating the user to enter a year. * The interface must include: An input field (type="text") allowing the user to enter a year. A button "Check" that calculates leap-year status. * A display area below the button which will show: The result if valid ("YYYY is a Leap Year" or "YYYY is not a Leap Year") Error message if input is empty ("Please enter a year") * Input can contain extra whitespace, which must be trimmed. **Edge Cases & Constraints** * Input must not be empty. * Input must represent a valid integer year. * Whitespace before or after the year must not cause errors. * Leap-year logic: Year is leap if: Divisible by 400 OR Divisible by 4 but not by 100. * Error must show if input is empty or contains only whitespace. * Result must update immediately on clicking "Check". * Input should accept any integer (positive or negative), as the logic still holds. **Example Behaviors** ``` // Example 1: Valid leap year Input: "2020" Click: Check Result: "2020 is a Leap Year" // Example 2: Valid non-leap year Input: "2021" Click: Check Result: "2021 is not a Leap Year" // Example 3: Input contains whitespace Input: " 2028 Click: Check Result: "2028 is a Leap Year" // Example 4: Empty input Input: "" Click: Check Result: "Please enter a year" ``` **Data Test IDs (Required for Testing)** * data-testid="label-date" - Label for the year input * data-testid="year-input" - Input field for the year * data-testid="check-btn" - Button to trigger leap-year check * data-testid="result" - Display area for leap-year result * data-testid="error-msg" - Error message container for empty/invalid input ## Footnote https://namastedev.com/practice/leap-year
styles.css ``` body { background: linear-gradient(135deg, #e1e8ff, #c7d2ff); padding: 2rem; margin: 0; font-family: "Poppins", sans-serif; display: flex; align-items: center; justify-content: center; box-sizing: border-box; height: 100vh; } .container { background: #ffffffdd; padding: 2rem; border-radius: 1rem; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08); text-align: center; border: 2px solid #a0b0ff; transition: transform 0.3s ease, box-shadow 0.3s ease; } .container:hover { transform: translateY(-4px); box-shadow: 0 12px 28px rgba(0, 0, 0, 0.12); } h1 { font-size: 1.8rem; color: #033857; margin-bottom: 1rem; letter-spacing: 0.5px; } label { display: block; margin-bottom: 0.5rem; font-size: 1rem; color: #444; text-align: left; font-weight: 500; } input { width: 90%; padding: 0.9rem; font-size: 1rem; border: 2px solid #a0b0ff; border-radius: 0.5rem; transition: all 0.3s ease; background: #f9faff; color: #222; } input:focus { border-color: #4f46e5; box-shadow: 0 0 8px #4f46e566; background: #fff; outline: none; } button { width: 100%; padding: 0.9rem; margin-top: 1rem; font-size: 1.1rem; background: #4f46e5; color: white; border: none; border-radius: 0.5rem; cursor: pointer; transition: background 0.3s ease, box-shadow 0.3s ease; box-shadow: 0 4px 8px rgba(79, 70, 229, 0.3); } button:hover { background: #3730a3; box-shadow: 0 6px 14px rgba(79, 70, 229, 0.35); } button:active { transform: scale(0.97); } .result { margin-top: 1.2rem; padding: 1rem; font-size: 1.2rem; color: #1e293b; background: #edf2ff; border-radius: 0.5rem; opacity: 0; transform: translateY(10px); animation: slideFade 0.5s forwards ease; border-left: 5px solid #4f46e5; } .error { margin-top: 1.2rem; padding: 1rem; font-size: 1.2rem; } @keyframes slideFade { to { opacity: 1; transform: translateY(0); } } ``` App.js ``` import LeapYear from './LeapYear.js' export default function App() { return } ``` LeapYear.js ``` import React, { useState } from "react"; import "./styles.css"; export default function LeapYear() { const [year, setYear] = useState(""); const [result, setResult] = useState(""); const [error, setError] = useState(""); const handleCheck = () => { const trimmed = year.trim(); // Error: empty or whitespace-only input if (trimmed === "") { setResult(""); setError("Please enter a year"); return; } // Validate integer const parsedYear = Number(trimmed); if (!Number.isInteger(parsedYear)) { setResult(""); setError("Please enter a valid year"); return; } setError(""); // Leap-year logic const isLeap = parsedYear % 400 === 0 || (parsedYear % 4 === 0 && parsedYear % 100 !== 0); setResult( isLeap ? `${parsedYear} is a Leap Year` : `${parsedYear} is not a Leap Year` ); }; return (

Leap Year Checker

setYear(e.target.value)} /> {error && (
{error}
)} {result && (
{result}
)}
); } ```
27
# **Get Weekday** Create a responsive Get Weekday component that displays the corresponding day of the week when a user selects or enters a valid date. **Requirements** * A heading with text Get Weekday. * The interface must include: An input field with a browser datepicker (type="date") A button labeled "Find Day" A display area that will show the resulting day of the week * Behavior on clicking the Find Day button: If the date is valid: Display the result in the format: "That date falls on Monday." **Edge Cases & Constraints** * Dates from the past and future must work correctly * The datepicker must open when clicking the input * The displayed day must update immediately after clicking Find Day * Leap years and different time zones must not cause errors **Data Test IDs (Required for Testing):** * data-testid="date-input" - Input field for selecting the date * data-testid="find-day-btn" - Button to trigger the day lookup * data-testid="result" - Display area for the resulting day of the week ## Footnote https://namastedev.com/practice/get-weekday
styles.css ``` body { font-family: Arial, sans-serif; background: gainsboro; padding: 2rem; color: #333; min-height: 100vh; display: flex; align-items: center; justify-content: center; margin: 0; transition: background 0.5s ease; box-sizing: border-box; } .container { background: white; padding: 2rem; border-radius: 1rem; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1); text-align: center; animation: fadeIn 0.6s ease-out; } h1 { font-size: 1.6rem; margin-bottom: 1.5rem; color: #444; letter-spacing: 0.5px; } input { width: 100%; padding: 0.7rem; font-size: 1rem; border: 1px solid #ccc; border-radius: 0.5rem; transition: border 0.3s, box-shadow 0.3s; } input:focus { border-color: #4a90e2; box-shadow: 0 0 0 3px rgba(74, 144, 226, 0.2); outline: none; } button { width: 100%; padding: 0.7rem; background: #4a90e2; color: white; border: none; border-radius: 0.5rem; cursor: pointer; font-size: 1rem; margin-top: 1rem; transition: background 0.3s ease, transform 0.2s ease; } button:hover { background: #357ab7; transform: scale(1.03); } button:active { transform: scale(0.98); } .result { margin-top: 1rem; padding: 0.8rem; background: #e0f7ff; border-radius: 0.5rem; font-weight: bold; opacity: 0; transform: translateY(-10px); animation: slideFade 0.5s ease forwards; } /* Fade-in container animation */ @keyframes fadeIn { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } } /* Smooth slide & fade-in for result */ @keyframes slideFade { to { opacity: 1; transform: translateY(0); } } ``` App.js ``` import GetWeekday from './GetWeekday' export default function App() { return } ``` GetWeekday.js ``` import React, { useState } from "react"; import "./styles.css"; export default function GetWeekday() { const [selectedDate, setSelectedDate] = useState(""); const [result, setResult] = useState(""); const handleFindDay = () => { if (!selectedDate) { setResult(""); return; } // Use UTC to avoid timezone offsets altering the date const [year, month, day] = selectedDate.split("-").map(Number); const utcDate = new Date(Date.UTC(year, month - 1, day)); const weekday = utcDate.toLocaleDateString("en-US", { weekday: "long", timeZone: "UTC", }); setResult(`That date falls on ${weekday}.`); }; return (

Get Weekday

setSelectedDate(e.target.value)} /> {result && (
{result}
)}
); } ```
28
# **Confirmation Modal** Create a React modal component that displays a confirmation prompt to the user with options to either confirm or cancel an action. **Requirements** * A button labeled "Open Confirmation Modal" triggers the modal. * Upon clicking the button: A modal appears. The modal includes: A title "Confirm Action" A message "Are you sure you want to proceed?" Two buttons: "Confirm" and "Cancel" * On clicking "Confirm": The modal should close. A status message below appears: "Confirmed" * On clicking "Cancel": The modal should close. A status message below appears: "Cancelled" **Edge Cases & Constraints** * Modal should only be visible after the open button is clicked. * Status messages should update appropriately based on user action. * Ensure that only one modal appears at a time. **Data Test IDs (required for testing):** * data-testid="open-modal-button": Button to open the modal * data-testid="confirmation-modal": The modal container box * data-testid="modal-title": Title inside the modal * data-testid="modal-message": Message text inside the modal * data-testid="confirm-button": Confirm action button * data-testid="cancel-button": Cancel action button * data-testid="action-status": Text showing the result of the user's action ## Footnote https://namastedev.com/practice/confirmation-modal
styles.css ``` /* Modal backdrop with blur and soft background */ .modal-backdrop { position: fixed; top: 0; left: 0; width: 100%; height: 100%; backdrop-filter: blur(5px); background-color: rgba(0, 0, 0, 0.4); display: flex; justify-content: center; align-items: center; z-index: 999; } /* Modal box with modern elevation and animation */ .modal-box { background: #ffffff; padding: 2rem; border-radius: 16px; width: 90%; max-width: 400px; text-align: center; box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); animation: fadeIn 0.3s ease-out; font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; } /* Smooth entrance animation */ @keyframes fadeIn { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } } /* Modal title */ .modal-title { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.75rem; color: #222; } /* Modal message text */ .modal-message { font-size: 1rem; color: #444; margin-bottom: 1.5rem; } /* Modal buttons container */ .modal-buttons { display: flex; justify-content: space-between; gap: 1rem; } /* Confirm button */ .confirm-btn { flex: 1; padding: 0.6rem 1rem; background-color: #38b000; color: white; border: none; border-radius: 8px; font-size: 1rem; font-weight: 500; cursor: pointer; transition: background-color 0.2s ease; } .confirm-btn:hover { background-color: #2d8700; } /* Cancel button */ .cancel-btn { flex: 1; padding: 0.6rem 1rem; background-color: #ef233c; color: white; border: none; border-radius: 8px; font-size: 1rem; font-weight: 500; cursor: pointer; transition: background-color 0.2s ease; } .cancel-btn:hover { background-color: #c1121f; } /* Open modal button */ .open-modal-btn { margin: 2rem; padding: 0.7rem 1.5rem; background-color: #0077b6; color: white; border: none; border-radius: 8px; font-size: 1rem; cursor: pointer; transition: background-color 0.2s ease; } .open-modal-btn:hover { background-color: #023e8a; } /* Action status message below the modal */ .action-status { margin-top: 1.5rem; font-size: 1.1rem; font-weight: 500; color: #000000; } .modal-container { display: flex; flex-direction: column; align-items: center; margin-top: 200px; } ``` App.js ``` import ConfirmationModal from './ConfirmationModal' export default function App() { return } ``` ConfirmationModal.js ``` import React, { useState } from "react"; import "./styles.css"; function ConfirmationModal() { const [isOpen, setIsOpen] = useState(false); const [status, setStatus] = useState(""); const openModal = () => { setIsOpen(true); }; const handleConfirm = () => { setIsOpen(false); setStatus("Confirmed"); }; const handleCancel = () => { setIsOpen(false); setStatus("Cancelled"); }; return (
{/* Open Modal Button */} {/* Modal (only visible when isOpen = true) */} {isOpen && (

Confirm Action

Are you sure you want to proceed?

)} {/* Status Message */}
{status}
); } export default ConfirmationModal; ```
29
# **Character Counter** **Things to do** * Displays a live character count (A / B). Ex. 5/25 where 5 is character count and 25 is max length * Allow the user to set a custom character limit using a number input field (maxLength) * Display a warning message when the user reaches 90% of the limit. The error message must be "Limit exceeded by x characters", where x is the number of characters exceeded." * Display an error message when the user exceeds the character limit. The error message must be "You are close to the limit!" **Features to be Done** * The default max character length: 50 * Display the character count in the format: currentLength / maxLength. * Warning must be shown at: 90% of the limit (e.g., 45 of 50). **Testing Instructions** Please use the following data-testid attributes in your React component to help us run automated tests: * textarea β†’ for the text area input. * maxlength β†’ for the input where user enters maximum allowed length. * char-info β†’ for the character count display (A /B). * warning-text β†’ for the warning message shown near the limit. * error-text β†’ for the error message shown after exceeding the limit. ## Footnote https://namastedev.com/practice/character-counter
styles.css ``` .characterCount { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; } .container { padding: 10px; width: 500px; } .inputs { margin: 15px 0; } .inputs input { padding: 3px 5px; text-align: center; } .text { width: 250px; height: 60px; } ``` App.js ``` import CharacterCount from './CharacterCount' export default function App() { return } ``` CharacterCount.js ``` import { useState } from "react"; function CharacterCount() { const [text, setText] = useState(""); const [maxLength, setMaxLength] = useState(50); const handleTextChange = (e) => { setText(e.target.value); }; const handleMaxLengthChange = (e) => { const value = parseInt(e.target.value, 10); if (!isNaN(value)) { setMaxLength(value); if (text.length > value) { setText(text.slice(0, value)); // trim text if exceeds new max } } }; const charCount = text.length; const warningThreshold = Math.floor(maxLength * 0.9); const exceededBy = charCount - maxLength; return (

Character Count

Track your input length with live character warnings.

{charCount}/{maxLength}
{charCount >= warningThreshold && charCount <= maxLength && (

Limit exceeded by 0 characters

)} {charCount > maxLength && (

You are close to the limit!

)}
); } export default CharacterCount; ```
30
# **Color Explorer** You are tasked with building a Color Explorer - a React-based application that helps users explore colors by typing in natural language color names like "lavender"", "skyblue", or "darkorange". The app matches the user's input against a predefined color dictionary and displays the color name and its corresponding HEX code with a beautiful circular preview. **Your goal is to:** * Convert any valid CSS color name into its HEX code. * Display the color preview in a visually appealing circular shape. * Handle typos or unsupported color names with a helpful error. * Deliver a responsive, accessible, and easy-to-use interface. Requirements * An input field for the user to enter a color name. * A search button to trigger the conversion and display. * If valid: Show color name Show HEX code Show a circular color preview * If invalid: Show error message like: "Sorry, I couldn't recognize that color." **Supported Color Names** The app supports 140+ standard CSS color names listed in colorData.js file. Input is case-insensitive and whitespace is ignored: **Edge Cases & Constraints** * Input should be trimmed and converted to lowercase before matching. * Color names with extra spaces or different casing should still work (" Light Gray "). * Only exact matches from the dictionary provided in the colorData.js will be recognized. * If the input is not in the list, a clear error should appear and remove the previous result. **Data Test IDs (required for testing)** * data-testid="color-input": The input field for color name * data-testid="search-button": The button that triggers search * data-testid="color-name": The rendered color name * data-testid="color-hex": The rendered HEX code * data-testid="color-preview": The circle showing color preview * data-testid="error-msg": Error display when input is invalid * data-testid="color-box": Container for valid result ## Footnote https://namastedev.com/practice/color-explorer
styles.css ``` body { margin: 0; font-family: "Segoe UI", sans-serif; user-select: none; height: 100vh; display: flex; justify-content: center; align-items: center; } .container { max-width: 720px; margin: 50px auto; padding: 40px 50px; background-color: #f0f0f0; border-radius: 16px; box-shadow: 0 10px 26px rgba(0, 0, 0, 0.1); text-align: center; height:500px } .container h1 { `` font-size: 2.5rem; margin-bottom: 30px; color: #134040; letter-spacing: 1px; } .input-section { display: flex; justify-content: center; align-items: center; gap: 14px; margin-bottom: 25px; flex-wrap: wrap; } .input-section input { padding: 12px 16px; font-size: 16px; border: 2px solid lightgray; border-radius: 8px; width: 240px; background-color: #ffffff; transition: border 0.3s ease; } .input-section input:focus { border-color: gray; outline: none; } .input-section button { padding: 12px 18px; font-size: 16px; background-color: white; color: #ffffff; border: 2px solid lightgray; border-radius: 8px; cursor: pointer; font-weight: 600; transition: all 0.3s ease; box-shadow: 0 4px 12px rgba(20, 123, 116, 0.3); } .input-section button:hover { transform: translateY(-2px); } .color-box { background-color: #ffffff; padding: 30px 20px; border-radius: 14px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08); margin-top: 25px; transition: transform 0.3s ease; } .color-box:hover { transform: scale(1.02); } .preview { width: 120px; height: 120px; border-radius: 50%; margin: 0 auto 18px; border: 3px solid #ccc; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); } .color-box p { font-size: 18px; margin: 6px 0; } .error { color: #c0392b; font-weight: bold; margin-top: 20px; font-size: 16px; } ``` App.js ``` import ColorExplorer from './ColorExplorer' export default function App() { return } ``` colorData.js ``` const colors = { aliceblue: "#f0f8ff", antiquewhite: "#faebd7", aqua: "#00ffff", aquamarine: "#7fffd4", azure: "#f0ffff", beige: "#f5f5dc", bisque: "#ffe4c4", black: "#000000", blanchedalmond: "#ffebcd", blue: "#0000ff", blueviolet: "#8a2be2", brown: "#a52a2a", burlywood: "#deb887", cadetblue: "#5f9ea0", chartreuse: "#7fff00", chocolate: "#d2691e", coral: "#ff7f50", cornflowerblue: "#6495ed", cornsilk: "#fff8dc", crimson: "#dc143c", cyan: "#00ffff", darkblue: "#00008b", darkcyan: "#008b8b", darkgoldenrod: "#b8860b", darkgray: "#a9a9a9", darkgreen: "#006400", darkgrey: "#a9a9a9", darkkhaki: "#bdb76b", darkmagenta: "#8b008b", darkolivegreen: "#556b2f", darkorange: "#ff8c00", darkorchid: "#9932cc", darkred: "#8b0000", darksalmon: "#e9967a", darkseagreen: "#8fbc8f", darkslateblue: "#483d8b", darkslategray: "#2f4f4f", darkslategrey: "#2f4f4f", darkturquoise: "#00ced1", darkviolet: "#9400d3", deeppink: "#ff1493", deepskyblue: "#00bfff", dimgray: "#696969", dimgrey: "#696969", dodgerblue: "#1e90ff", firebrick: "#b22222", floralwhite: "#fffaf0", forestgreen: "#228b22", fuchsia: "#ff00ff", gainsboro: "#dcdcdc", ghostwhite: "#f8f8ff", gold: "#ffd700", goldenrod: "#daa520", gray: "#808080", green: "#008000", greenyellow: "#adff2f", grey: "#808080", honeydew: "#f0fff0", hotpink: "#ff69b4", indianred: "#cd5c5c", indigo: "#4b0082", ivory: "#fffff0", khaki: "#f0e68c", lavender: "#e6e6fa", lavenderblush: "#fff0f5", lawngreen: "#7cfc00", lemonchiffon: "#fffacd", lightblue: "#add8e6", lightcoral: "#f08080", lightcyan: "#e0ffff", lightgoldenrodyellow: "#fafad2", lightgray: "#d3d3d3", lightgreen: "#90ee90", lightgrey: "#d3d3d3", lightpink: "#ffb6c1", lightsalmon: "#ffa07a", lightseagreen: "#20b2aa", lightskyblue: "#87cefa", lightslategray: "#778899", lightslategrey: "#778899", lightsteelblue: "#b0c4de", lightyellow: "#ffffe0", lime: "#00ff00", limegreen: "#32cd32", linen: "#faf0e6", magenta: "#ff00ff", maroon: "#800000", mediumaquamarine: "#66cdaa", mediumblue: "#0000cd", mediumorchid: "#ba55d3", mediumpurple: "#9370db", mediumseagreen: "#3cb371", mediumslateblue: "#7b68ee", mediumspringgreen: "#00fa9a", mediumturquoise: "#48d1cc", mediumvioletred: "#c71585", midnightblue: "#191970", mintcream: "#f5fffa", mistyrose: "#ffe4e1", moccasin: "#ffe4b5", navajowhite: "#ffdead", navy: "#000080", oldlace: "#fdf5e6", olive: "#808000", olivedrab: "#6b8e23", orange: "#ffa500", orangered: "#ff4500", orchid: "#da70d6", palegoldenrod: "#eee8aa", palegreen: "#98fb98", paleturquoise: "#afeeee", palevioletred: "#db7093", papayawhip: "#ffefd5", peachpuff: "#ffdab9", peru: "#cd853f", pink: "#ffc0cb", plum: "#dda0dd", powderblue: "#b0e0e6", purple: "#800080", rebeccapurple: "#663399", red: "#ff0000", rosybrown: "#bc8f8f", royalblue: "#4169e1", saddlebrown: "#8b4513", salmon: "#fa8072", sandybrown: "#f4a460", seagreen: "#2e8b57", seashell: "#fff5ee", sienna: "#a0522d", silver: "#c0c0c0", skyblue: "#87ceeb", slateblue: "#6a5acd", slategray: "#708090", slategrey: "#708090", snow: "#fffafa", springgreen: "#00ff7f", steelblue: "#4682b4", tan: "#d2b48c", teal: "#008080", thistle: "#d8bfd8", tomato: "#ff6347", turquoise: "#40e0d0", violet: "#ee82ee", wheat: "#f5deb3", white: "#ffffff", whitesmoke: "#f5f5f5", yellow: "#ffff00", yellowgreen: "#9acd32", }; export const colorNameToHex = (name) => { return colors[name.replace(/\s+/g, "")]; }; ``` ColorExplorer.js ``` import React, { useState } from "react"; import { colorNameToHex } from "./colorData"; import "./styles.css"; const ColorExplorer = () => { const [inputValue, setInputValue] = useState(""); const [colorName, setColorName] = useState(""); const [colorHex, setColorHex] = useState(""); const [error, setError] = useState(""); const handleSearch = () => { const cleaned = inputValue.trim().toLowerCase().replace(/\s+/g, ""); const hex = colorNameToHex(cleaned); if (!hex) { setError("Sorry, I couldn't recognize that color."); setColorName(""); setColorHex(""); return; } setError(""); setColorName(cleaned); setColorHex(hex); }; return (

Color Explorer

setInputValue(e.target.value)} />
{error && (

{error}

)} {!error && colorHex && (

Name: {colorName}

Hex: {colorHex}

)}
); }; export default ColorExplorer; ```
31
# **Copy To Clipboard** Create a simple and user-friendly React component that allows users to copy a text input to the clipboard with a single click. **Requirements** * Includes a text input field for the user to enter any message. * A "Copy" button allows the user to copy the text from the input field to their clipboard. * When the text is successfully copied: A "Copied!" message should appear temporarily for 2 seconds. * If the input field is empty and the user clicks "Copy": An error message should be displayed indicating that the input cannot be empty. **Testing Requirements** Use the following data-testid attributes to make the component easily testable: * input-field β†’ applied to the β€Ήinput /β€Ί element. * copy-button β†’ applied to the "Copy" < button />. * copied-message β†’ applied to the temporary "Copied!" confirmation message. * error-message β†’ applied to the error message shown when input is empty. ## Footnote https://namastedev.com/practice/copy-to-clipboard
styles.css ``` .copyToClipboard { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; } .copyToClipboard > h1 { margin: 1rem 0; } .copyToClipboard > p { margin-bottom: 1rem; } .copyToClipboard-container { border: 1px solid black; display: flex; flex-direction: column; justify-content: space-around; align-items: center; padding: 1rem 1.5rem; } input[type="text"] { padding: 5px; margin: 0 10px; } .btn { padding: 5px; margin: 10px 0; width: 4rem; cursor: pointer; } .message { margin: 10px 0; color: green; } .errorMessage { color: red; margin: 10px 0; } .ex-para { display: flex; gap: 10px; } .ex-para > button { cursor: pointer; } .examples { display: flex; justify-content: flex-start; align-items: flex-start; flex-direction: column; gap: 10px; } ``` App.js ``` import CopyClipboard from './CopyClipboard' export default function App() { return } ``` CopyClipboard.js ``` import { useState } from "react"; function CopyClipboard() { const [text, setText] = useState(""); const [copied, setCopied] = useState(false); const [error, setError] = useState(""); async function handleCopy() { if (!text.trim()) { setError("Input cannot be empty"); setCopied(false); return; } try { await navigator.clipboard.writeText(text); setCopied(true); setError(""); setTimeout(() => { setCopied(false); }, 2000); // hide "Copied!" after 2 seconds } catch (err) { console.error("Copy failed", err); setError("Failed to copy text"); } } return (

Copy to Clipboard

Click the button to copy the text

{copied && (

Copied!

)} {error && (

{error}

)}
); } export default CopyClipboard; ```
32
# **Frequently Asked Questions** Create a React component that displays a list of frequently asked questions. Each question can be expanded or collapsed individually, revealing the corresponding answer. Only one question can be open at a time. The component uses icons to indicate the expanded or collapsed state of each question. **Requirements** * Use these 3 questions and answers: What is this app about? This app helps users track and improve their daily habits. * How do I reset my password? Click on 'Forgot Password' on the login screen and follow instructions. * Can I use this app offline? Yes, some features are available offline after the initial setup. **Functional Requirements** * The component must: Display a list of FAQ questions and their answers(individual container). Allow only one question to be expanded at a time. Collapse an expanded question if it is clicked again. * Each FAQ item must include: A question button that toggles its expanded state. An answer section that is conditionally rendered only when active. * A chevron icon from react-icons/fi: FiChevronDown when collapsed. FiChevronUp when expanded. * Clicking a question should: Expand its answer and show the FiChevronUp icon. Collapse the previously opened question (if any). Show FiChevronDown when the question is collapsed again. **Data Test IDs (Required for Testing)** * data-testid="faq-item-findex}" - Container for each individual FAQ item. * data-testid="faq-question-findex}" - Button element that toggles the visibility of the answer. * data-testid="icon-up-{index}" - Icon shown when the question is expanded. * data-testid="icon-down-findex}" - Icon shown when the question is collapsed. * data-testid="faq-answer-{index}" - Answer section, only rendered when the item is active. ## Footnote https://namastedev.com/practice/frequently-asked-questions
styles.css ``` .faq-container { max-width: 600px; margin: 2rem auto; padding: 1rem; font-family: sans-serif; } .faq-title { font-size: 1.8rem; margin-bottom: 1.5rem; text-align: center; } .faq-item { border-bottom: 1px solid #ddd; margin-bottom: 1rem; } .faq-question { background: none; border: none; width: 100%; font-size: 1.1rem; padding: 1rem; cursor: pointer; display: flex; justify-content: space-between; align-items: center; font-weight: 500; color: #333; } .faq-icon { font-size: 1.2rem; } .faq-answer { padding: 0.75rem 1rem 1rem; background-color: #f9f9f9; color: #555; font-size: 0.95rem; } ``` App.js ``` import FaqAccordion from './FaqAccordion' export default function App() { return } ``` FaqAccordion.js ``` import React, { useState } from "react"; import { FiChevronDown, FiChevronUp } from "react-icons/fi"; import "./styles.css"; const faqs = [ { question: "What is this app about?", answer: "This app helps users track and improve their daily habits.", }, { question: "How do I reset my password?", answer: "Click on 'Forgot Password' on the login screen and follow instructions.", }, { question: "Can I use this app offline?", answer: "Yes, some features are available offline after the initial setup.", }, ]; function FaqAccordion() { const [activeIndex, setActiveIndex] = useState(null); const toggleFAQ = (index) => { // Collapse if clicking the same question again setActiveIndex((prev) => (prev === index ? null : index)); }; return (

Frequently Asked Questions

{faqs.map((faq, index) => { const isOpen = activeIndex === index; return (
{isOpen && (
{faq.answer}
)}
); })}
); } export default FaqAccordion; ```
33
# **Asterisk Field Validation** Create a React component that allows users to input and validate required fields for Name and Location. It should display a red asterisk for mandatory fields, highlight validation errors when fields are left empty, and show a success message with submitted values when both fields are filled correctly. **Requirements** * The form must: Contain two input fields: Name and Location. Display labels for both fields with red asterisks (*) indicating they are required. Show placeholder text: "Enter your name" for the Name field. "Enter your location" for the Location field. * Validation behavior: On form submission: If either field is empty: Highlight the input with an error style. Show an inline error message eg. "Location is required" If both fields are filled: Show a success message containing the submitted name and location. * Success message: Appears only if both fields pass validation. Message format should be: Submitted Successfully! Name: [user input] Location: [user input] D**ata Test IDs (Required for Testing)** * data-testid="form": The main form element * data-testid="name-input": The Name input field * data-testid="location-input"; The Location input field * data-testid="submit-button": The Submit button * data-testid="name-error": The error message for the Name field * data-testid="location-error": The error message for the Location field * data-testid="success-message": The message shown on successful form submission ## Footnote https://namastedev.com/practice/asterisk-field-validation
styles.css ``` .container { max-width: 400px; margin: auto; padding: 2rem; font-family: Arial, sans-serif; } .title { font-size: 1.5rem; margin-bottom: 1rem; text-align: center; } .form { display: flex; flex-direction: column; gap: 1.5rem; } .input-group { display: flex; flex-direction: column; } .label { font-weight: bold; margin-bottom: 0.25rem; } .asterisk { color: red; } .input { padding: 0.5rem; border: 1px solid #ccc; border-radius: 4px; } .input-error { border-color: red; } .error { color: red; font-size: 0.875rem; margin-top: 0.25rem; } .submit-button { background-color: #1e90ff; color: white; padding: 0.6rem; border: none; border-radius: 4px; cursor: pointer; } .submit-button:hover { background-color: #1c86ee; } .success-message { background-color: #e6ffed; border: 1px solid #34c759; padding: 1rem; margin-top: 1.5rem; color: #2a7a42; white-space: pre-line; border-radius: 4px; font-weight: 500; } ``` App.js ``` import AsteriskFieldValidation from './AsteriskFieldValidation' export default function App() { return } ``` AsteriskFieldValidation.js ``` import React, { useState } from "react"; import "./styles.css"; function AsteriskFieldValidation() { const [name, setName] = useState(""); const [location, setLocation] = useState(""); const [errors, setErrors] = useState({}); const [submittedData, setSubmittedData] = useState(null); const handleSubmit = (e) => { e.preventDefault(); let newErrors = {}; if (!name.trim()) newErrors.name = "Name is required"; if (!location.trim()) newErrors.location = "Location is required"; setErrors(newErrors); if (Object.keys(newErrors).length === 0) { setSubmittedData({ name, location }); } else { setSubmittedData(null); } }; return (

Asterisk Field Validation

{/* Name Field */}
setName(e.target.value)} /> {errors.name && (
{errors.name}
)}
{/* Location Field */}
setLocation(e.target.value)} /> {errors.location && (
{errors.location}
)}
{/* Success Message */} {submittedData && (
Submitted Successfully! {"\n"}Name: {submittedData.name} {"\n"}Location: {submittedData.location}
)}
); } export default AsteriskFieldValidation; ```
34
# **Read More** Create a React component that displays a paragraph of text and allows users to expand or collapse it. The component should display a truncated version of the text by default, with a button to toggle between "Read More" and "Read Less". This improves readability and user experience, especially for long content blocks. **Requirements** * The component must: Display a short preview of a longer paragraph initially (e.g., first 100 characters followed by " ..."). Show the full text when toggled. Provide a button labeled "Read More" when the text is collapsed. Change the button label to "Read Less" when the full text is expanded. Toggle the text content and button label immediately on click. **Data Test IDs (Required for Testing)** * data-testid="readmore-text": The paragraph element displaying either truncated or full text. * data-testid=" readmore-button": The button used to toggle the text expansion. ## Footnote https://namastedev.com/practice/read-more
styles.css ``` /* styles.css */ .readmore-container { max-width: 600px; margin: 2rem auto; padding: 1.5rem; background-color: #f9f9f9; border-radius: 12px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.06); font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; } .readmore-text { font-size: 1rem; color: #333; line-height: 1.6; margin-bottom: 1rem; transition: all 0.3s ease-in-out; } .readmore-button { background-color: #007bff; color: white; border: none; padding: 0.6rem 1.2rem; font-size: 0.95rem; border-radius: 8px; cursor: pointer; transition: background-color 0.2s ease-in-out; } .readmore-button:hover { background-color: #0056b3; } ``` App.js ``` import ReadMoreToggle from './ReadMoreToggle' export default function App() { return } ``` ReadMoreToggle.js ``` import React, { useState } from "react"; import "./styles.css"; function ReadMoreToggle() { const [expanded, setExpanded] = useState(false); const text = `React is a popular JavaScript library developed by Facebook for building user interfaces, especially single-page applications. It allows developers to create reusable UI components that efficiently update and render as data changes. One of React’s key features is the virtual DOM, which improves performance by minimizing direct manipulation of the actual DOM.`; const preview = text.slice(0, 100) + "..."; return (

Read More Toggle

{expanded ? text : preview}

); } export default ReadMoreToggle; ```
35
# **Toggle button with custom hook** Create a React component that displays a toggle button which switches its label between "ON" and "OFF" each time it is clicked. The state should be managed using a custom hook called useToggle. **Requirements** * Use functional components only. * Implement a custom hook useToggle(initialValue) that returns: A boolean state A toggle function * Display "ON" or "OFF" on a button based on the current state. * On button click, toggle the state. * The initial state must be "OFF" **Edge Case & Constraints** 1. Initial value is false * Initial value of the hook should be false Example: const [value, toggle] = useToggle( false); expect (value). toBe(false); 2. Multiple toggles in a row * Toggling multiple times in a row should flip the state correctly. * Ensure true β†’ false β†’ true β†’ false works consistently. 3. Used in multiple components * If useToggle is reused in two components, toggling one should not affect the other. * Each instance should manage its own state independently. 4. Re-rendering the parent * Re-rendering the parent component should not reset the toggle state. * State should persist unless the component is unmounted. 5. Event handler integrity * The toggle function should be a stable function (same reference if not changed). **Test Cases** -data-testid="toggle-button" : Selects the button element ## Footnote https://namastedev.com/practice/toggle-button-with-custom-hook
styles.css ``` body { margin: 0; padding: 0; font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; background: linear-gradient(135deg, #f0f4f8, #d9e2ec); } button { padding: 1rem 2rem; font-size: 1.5rem; font-weight: bold; border: none; border-radius: 12px; cursor: pointer; background-color: #007bff; color: white; transition: all 0.3s ease-in-out; box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15); } button:hover { background-color: #0056b3; transform: scale(1.05); } button:active { transform: scale(0.97); box-shadow: 0 3px 6px rgba(0, 0, 0, 0.2); } ``` App.js ``` import { useState, useCallback } from "react"; // βœ… Custom hook implementation function useToggle(initialValue = false) { const [value, setValue] = useState(initialValue); // useCallback ensures stable reference (requirement #5) const toggle = useCallback(() => { setValue((prev) => !prev); }, []); return [value, toggle]; } export default function App() { // βœ… Use custom hook const [isOn, toggle] = useToggle(false); return ( ); } export { useToggle }; ```
36
# **Dynamic Greeting App** A modern React application that displays a real-time greeting message based on the current hour of the day and updates the local time every second. **Problem Description** Create a greeting app that: * Greets users based on the current hour (morning, afternoon, evening, night). * Continuously displays and updates the current time in real-time. * Changes the greeting as the time changes without needing a manual refresh. **Functionality Requirements** 1. Greeting Message: "Good Morning! β˜€οΈ" from 5 AM to 12 PM. "Good Afternoon! 🌀️" from 12 PM to 5 PM. "Good Evening! πŸŒ‡" from 5 PM to 9 PM. "Good Night! πŸŒ™βœ¨" from 9 PM to 5 AM. 2. Live Time Display: Displays the user's local time using toLocaleTimeString(). Time should update every second using setInterval. 3. Visual Layout: Styled with a dark background and a bright time card. Responsive and centered layout. 4. Testability: Use data-testid="greeting" for greeting element. Use data-testid="time" for time display. **Edge Cases & Constraints** * App should automatically transition between greetings at appropriate time thresholds. * Must work with 24-hour and 12-hour system times. * setInterval must be cleared on component unmount. * Ensure emojis and time logic don't overlap (each hour belongs to one specific greeting). * Greeting must change seamlessly without user interaction. **Examples** Example 1: System Time: 2025-05-27T08:30:00 Display Output: Good Morning! β˜€οΈ 08:30:00 AM Example 2: System Time: 2025-05-27T21:45:00 Display Output: Good Night! πŸŒ™βœ¨ 09:45:00 PM ## Footnote https://namastedev.com/practice/dynamic-greeting-app
styles.css ``` body { margin: 0; padding: 0; height: 100vh; background: #0d1117; /* Dark background */ display: flex; justify-content: center; align-items: center; font-family: Arial, sans-serif; } .modal-content { background: #ffffff10; backdrop-filter: blur(10px); border-radius: 12px; padding: 40px 60px; text-align: center; box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4); color: white; } .time { font-size: 2rem; margin-top: 15px; font-weight: bold; color: #00eaff; } .greeting { font-size: 2rem; font-weight: 600; } ``` App.js ``` import React from "react"; import Greeting from "./Greeting"; export default function App() { return ; } ``` Greeting.js ``` import React, { useState, useEffect } from "react"; import "./styles.css"; export default function Greeting() { const [time, setTime] = useState(new Date()); useEffect(() => { // Update every second const interval = setInterval(() => { setTime(new Date()); }, 1000); // Cleanup return () => clearInterval(interval); }, []); const hour = time.getHours(); // Greeting logic let greetingText = ""; if (hour >= 5 && hour < 12) { greetingText = "Good Morning! β˜€οΈ"; } else if (hour >= 12 && hour < 17) { greetingText = "Good Afternoon! 🌀️"; } else if (hour >= 17 && hour < 21) { greetingText = "Good Evening! πŸŒ‡"; } else { greetingText = "Good Night! πŸŒ™βœ¨"; } return (
{greetingText}
{time.toLocaleTimeString()}
); } ```