DEV Community

Cover image for Neubrutalism React TypeScript Tailwind Portfolio Website
Codex
Codex

Posted on

Neubrutalism React TypeScript Tailwind Portfolio Website

πŸ—οΈ Neubrutalism React TypeScript Tailwind Portfolio Website πŸ—οΈ

Explore the bold and vibrant world of neubrutalism design with this responsive portfolio website! Built with cutting-edge tools like Vite, React, TypeScript, and Tailwind CSS, this project is a perfect showcase of modern web design principles and creativity.

Image description

πŸ’» What’s Inside?

  • Bold and Modern Home Page
  • Showcase Portfolio Page
  • Informative About Page
  • Functional Contact Form

✨ Why? If you’re into neubrutalism aesthetics or looking for inspiration for your next portfolio, this project is the perfect example of how to transform a Figma prototype into a fully functional website. Whether you're a developer or designer, this video has something for you!

πŸ‘€ Like, Share & Subscribe for more inspiring projects like this. Drop a comment and let us know what you think about the neubrutalism design trend! 🌟

Features of the Portfolio

1. Home Page

The Home page of the website showcases a modern and minimalistic approach, using bold colors and typography, staying true to the neubrutalism style. It includes an engaging Hero section, a showcase of tools used in the development, services, and a testimonials section to build trust and credibility.

Home.tsx

import React from 'react';
import { Hero, Tools, ServicesSection, PortfolioGrid, Testimonials, ContactSection } from '../components';
import { HomeProps } from '../interfaces/interfaces';

const Home: React.FC<HomeProps> = ({ tools, testimonials, portfolioItems, onContactClick }) => {
  return (
    <div>
      <Hero />
      <Tools tools={tools} />
      <ServicesSection />
      <PortfolioGrid items={portfolioItems} />
      <Testimonials testimonials={testimonials} />
      <ContactSection ={onContactClick} />
    </div>
  );
};

export default Home;
Enter fullscreen mode Exit fullscreen mode

2. Portfolio Page

The Portfolio Page is built to display your projects in a grid format, following a modular layout that can easily expand to show more content. The loadMoreItems functionality is implemented to dynamically load more portfolio items.

Portfolio.tsx

import React, { useState } from 'react';
import { Button, CardComponent } from '../components';
import { PortfolioProps } from '../interfaces/interfaces';

const Portfolio: React.FC<PortfolioProps> = ({ portfolioItems }) => {
  const [visibleItems, setVisibleItems] = useState<number>(6); 

  const loadMoreItems = () => {
    setVisibleItems(prevVisibleItems => prevVisibleItems + 3);
  };

  return (
    <div className="min-h-screen text-black font-sans">
      <main className="container mx-auto px-4 py-16">
        <h1 className="text-5xl font-bold mb-12 text-center">My Projects</h1>
        <div className="grid grid-cols-1 md:grid-cols-2 gap-16 lg:px-16">
          {portfolioItems.slice(0, visibleItems).map((item, index) => (
            <CardComponent key={item.id} item={item} index={index} />
          ))}
        </div>

        {visibleItems < portfolioItems.length && (
          <div className="mt-16 text-center">
            <Button ={loadMoreItems} bgColor="bg-purple-400">See More</Button>
          </div>
        )}
      </main>
    </div>
  );
};

export default Portfolio;
Enter fullscreen mode Exit fullscreen mode

3. About Page

The About Page is where you can introduce yourself, your skills, and some fun facts. It uses a profile card that can be expanded with relevant information. The design is simple, focusing on typography and color contrasts to maintain the neubrutalism aesthetic.

About.tsx

import { useNavigate } from 'react-router-dom';
import { skills, funFacts, iconColors } from '../data/dataItems';
import { SectionWithBorderProps } from '../interfaces/interfaces';
import { Button, ProfileImage } from '../components';
import { Zap } from '../icons';

const About: React.FC = () => {
  return (
    <div className="min-h-screen text-black font-sans">
      <main className="container mx-auto px-4 py-16">
        <SectionWithBorder title="About Me">
          <div className="flex flex-col md:flex-row gap-8">
            <ProfileCard />
            <ProfileDescription />
          </div>
        </SectionWithBorder>

        <SectionWithBorder title="Fun Facts About Me">
          <ul className="list-disc list-inside space-y-2">
            {funFacts.map((fact, index) => (
              <li key={index}>{fact}</li>
            ))}
          </ul>
        </SectionWithBorder>
      </main>
    </div>
  );
};

const SectionWithBorder: React.FC<SectionWithBorderProps> = ({ title, children }) => {
  return (
    <div className="relative p-1 mb-12 border-4 border-black">
      <div className="relative z-10 bg-white p-8">
        <h1 className="text-4xl font-bold mb-6">{title}</h1>
        {children}
      </div>
    </div>
  );
};

const ProfileCard: React.FC = () => {
  return (
    <div className="md:w-1/3">
      <div className="relative w-full aspect-square mb-4">
        <ProfileImage />
      </div>
      <h2 className="text-2xl font-bold mb-2">Zainab</h2>
      <p className="text-lg mb-4">UI/UX Designer & Developer</p>
      <div className="flex space-x-4">
        {iconColors.map((icon, index) => (
          <div key={index} className={`${icon.bgColor} rounded-full border-2 border-black p-2 transition-colors`}>
            <Zap className="w-6 h-6" />
          </div>
        ))}
      </div>
    </div>
  );
};

const ProfileDescription: React.FC = () => {
  const navigate = useNavigate();

  const handleButtonClick = () => {
    navigate('/portfolio');
  };

  return (
    <div className="md:w-2/3">
      <p className="text-lg mb-6">
        Hey there! I'm Zainab, a passionate UI/UX designer and developer with a knack for creating engaging digital experiences...
      </p>
      <h3 className="text-2xl font-bold mb-4">My Skills</h3>
      <div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
        {skills.map(({ icon: Icon, text, bgColor }, index) => (
          <div key={index} className={`flex items-center space-x-2 ${bgColor} p-3 border-4 border-black`}>
            <Icon className="w-6 h-6" />
            <span>{text}</span>
          </div>
        ))}
      </div>
      <div className="flex justify-center sm:justify-center md:justify-start">
        <Button ={handleButtonClick} bgColor="bg-blue-400" textColor="text-white">
          Check Out My Work
        </Button>
      </div>
    </div>
  );
};

export default About;
Enter fullscreen mode Exit fullscreen mode

4. Contact Form Modal

The Contact Form is accessible through a button on the Home page. It opens in a modal overlay with a clean and simple layout.

App.tsx (Contact Modal)

import { useState, useEffect } from 'react';
import { Routes, Route, useLocation } from 'react-router-dom';
import { Navbar, Footer, ContactForm } from './components';
import { tools, testimonials, portfolioItems } from './data/dataItems';
import { X } from './icons';

export default function App() {
  const location = useLocation();
  const [contactFormOpen, setContactFormOpen] = useState(false);
  const [portfolioItemsState] = useState(portfolioItems);

  const handleButtonClick = () => {
    setContactFormOpen(true);
  };

  useEffect(() => {
    window.scrollTo(0, 0);
  }, [location.pathname]);

  return (
    <div className="app-container overflow-hidden">
      <Navbar setContactFormOpen={handleButtonClick} />
      <Routes>
        <Route path="/" element={<Home tools={tools} testimonials={testimonials} portfolioItems={portfolioItemsState} onContactClick={handleButtonClick} />} />
        <Route path="/portfolio" element={<Portfolio portfolioItems={portfolioItemsState} />} />
        <Route path="/about" element={<About />} />
      </Routes>
      <Footer />

      {contactFormOpen && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
          <div className="bg-white p-8 border-4 border-black shadow-[16px_16px_0px_0px_#303030] max-w-md w-full">
            <button ={() => setContactFormOpen(false)} className="float-right">
              <X className="w-6 h-6" />
            </button>
            <h2 className="text-3xl font-bold mb-4">Send us a message</h2>
            <ContactForm ={() => setContactFormOpen(false)} />
          </div>
        </div>
      )}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

With the Neubrutalism aesthetic, this project emphasizes strong contrast, bold typography, and clear separation between sections. It’s a modern design philosophy that’s perfect for portfolio websites, especially if you want to stand out with creative, minimalist elements.

If you'd like to check out the full project, download here

🎨 Design Inspiration: Figma Prototype

Video --> https://youtu.be/kNqqrcUOdrU

Top comments (0)