Creating a Next.JS Link that opens a new tab for internal URLs while avoiding redirection to external URLs

Currently, I am working on a project component for my homepage that showcases a specific project. The goal is to have the entire component redirect to the project page when clicked, except when the user clicks on the GitHub icon. In that scenario, I want the GitHub link to open in a new tab without redirecting from the original project page. Below is the code snippet for the component:

"use client";
import Image from "next/image";
import Link from "next/link";

type ProjectType = {
  img: string;
  title: string;
  slug: string;
  desc: string;
  overview: string;
  role: string;
  impact: string;
  tags: Array<string>;
  startDate: Date;
  endDate: Date;
  github?: string;
  paper?: string;
  link?: string;
  area: string;
};

function Tag({ tag }: { tag: string }) {
  return (
    <div className=" duration-500 ease-in-out text-center text-sm rounded-full p-2 mr-4 mb-4 w-1/5 text-primary-white bg-primary-white bg-opacity-50 group-hover:bg-primary-color group-hover:bg-opacity-100 ">
      {tag}
    </div>
  );
}

export default function ProjectFeatured({
  project,
  idx,
}: {
  project: ProjectType;
  idx: number;
}) {
  const options = { month: "short" as const, year: "numeric" as const };
  const isEven = idx % 2 == 0;
  const classNameString =
    "group w-full h-full p-12 rounded-3xl text-primary-white flex flex-col space-y-8 sm:space-y-0 sm:space-x-8 duration-500 ease-in-out hover:bg-primary-hover " +
    (isEven ? "sm:flex-row" : "sm:flex-row-reverse sm:space-x-reverse");

  return (
    <Link href={"/projects/" + project.slug}>
      <div className={classNameString}>
        {/* Image */}
        <div className="flex w-1/2 items-center justify-center">
          <Image
            className="object-cover h-full rounded-xl"
            src={project.img}
            alt="Project Image"
            width={1000}
            height={1000}
            draggable={false}
          />
        </div>
        {/* Text */}
        <div className="flex flex-col w-3/4 justify-between space-y-12">
          {/* Title and desc */}
          <div className="flex flex-col space-y-4">
            {/* Title */}
            <div>
              <div className="text-xxl">{project.title}</div>
              {/* <Image/> */}
            </div>
            {/* Desc */}
            <div>{project.desc}</div>
          </div>
          {/* Tags and links */}
          <div className="flex flex-col space-y-4">
            {/* Tags */}
            <div className="flex flex-row flex-wrap">
              {project.tags.map((tag, idx) => (
                <Tag tag={tag} key={idx} />
              ))}
            </div>
            {/* Links */}
            <div className="flex flex-row space-x-2 ">
              {project.github ? (
                <a href={project.github} target="_blank" rel="noreferrer noopener" className="w-full">
                  <Image
                    className=" hover:animate-shrinkWiggle"
                    src={"svgs/github.svg"}
                    alt="Github Icon"
                    width={20}
                    height={20}
                  />
                </a>
              ) : (
                <div />
              )}
            </div>
          </div>
        </div>
      </div>
    </Link>
  );
}

I experimented with removing the target="_blank" attribute, but this method caused the GitHub icon to navigate to the GitHub page instead of opening it in a new tab like intended.

Answer №1

If you're looking to enhance the functionality of the inner Link component (the Github link), one solution could be to include an onClick handler and observe the results.

<Link className="w-full" href={project.github} target="_blank" 
  onClick={(event) => event.stopPropagation()} // <--- Give this a try
>
 // ...
</Link>

For more details, consider checking out:

Answer №2

If you wish to open Github in a new tab, you can just use a regular <a> tag like this:

<a className="w-full" href={project.github} target="_blank">
    <Image/>
</a>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Disabling dates in the second datetimepicker depending on following days selected in the first one

I have implemented the bootstrap date picker and I am using two textboxes for searching by date range. I want the second textbox to display the days after the date selected in the first textbox. Any suggestions would be appreciated. Here is the HTML code: ...

While in the process of developing a React application, I have encountered the following challenge

PS F:\Programming Tutorials Videos\R Practice> npx create-react-app custom-hook npm ERR! code ENOTFOUND npm ERR! syscall getaddrinfo npm ERR! errno ENOTFOUND npm ERR! network request to https://registry.npmjs.org/create-react-app failed, reaso ...

I'm having trouble getting the conditional ngClass to function properly in my specific scenario

<li ng-class="{selected: 'checked==true'}" ng-repeat="item in data"> <span>item.name</span> <input ng-model="checked"/> </li> Is there a way to dynamically add the 'selected' class only after clicking on t ...

Customizing external elements with React's inline styling feature

Trying to use React to style elements generated by a third-party library has been a challenge. In the snippet below, I was able to achieve the desired styling using CSS, but now I am looking to accomplish the same using JavaScript. This way, users can defi ...

Retrieving information from a JSON file using JavaScript

My code snippet looks like this: { "badge_sets":{ "1979-revolution_1":{ "versions":{ "1":{ "image_url":"https://static-cdn.jtvnw.net/badges/v1/7833bb6e-d20d-48ff-a58d-67f ...

The styles from bootstrap.css are not displaying in the browser

Currently in the process of setting up my angular 2 project alongside gulp by following this helpful tutorial: I've added bootstrap to the package.json, but unfortunately, it's not reflecting in the browser. I can see it in the node_modules and ...

Tips for transferring data from a controller to $scope in the MVC architecture with AngularJS

I'm a beginner when it comes to AngularJS, currently working with an MVC5 application. I have set up a module and controller in the Angular JS for this application. Within my customer controller in MVC5, I have an action called "View" where I need to ...

A function designed to detect errors based on the parameters supplied as arguments

In order to ensure secure access to my restful API, I am looking to implement an authentication function called "access". I would like the function to have the following structure whenever a user interacts with the server: access(id , token ,function(err) ...

Navigating the route with quickness

Upon accessing the localhost, I encountered an issue with the code snippet below: When I try to access it, I receive an error message saying "Cannot GET /". var express = require('express'); var router = express.Router(); /* GET home page. */ r ...

dynamically filter a set of string elements

Is there a way to dynamically filter a list of strings? I have come across examples using ng-repeat, but it seems that it does not work with angular 7: it does not load any strings, only works with ngFor <div class="input-group"> <div class="i ...

ParcelJS takes a unique approach by not bundling imported JavaScript libraries

My NodeJS app, which is a Cloudflare Worker, seems to be having trouble with bundling the 'ping-monitor' dependency. In my main typescript file (index.ts), I import the handler module and the first line reads: const Monitor = import('ping-m ...

Strange occurrences observed on array mapping post-state alteration

Greetings to all during these challenging times! Currently, I am delving into Firebase and ReactJS and have encountered a peculiar issue involving state updates in React and the array map functionality in JavaScript. Below is the code snippet showcasing my ...

Receiving an undefined input while making a post request to the Node.js API with React and Axios

I'm facing an issue while attempting to make a post request to an API that I have developed using MySQL and Node.js with React and Axios. The problem arises when I send the data, as the response returned is 'undefined'. Interestingly, when I ...

"Enhance your web application with dynamic drop-down selection using Spring, Ajax

In my JSP file, I have a script that populates the list of states based on the selected country. The script fetches data from the controller and is supposed to display the list of states. However, after calling the controller method, the alert "received da ...

Can you explain how to break down secured routes, users, and posts all within a single .create() function in Mongoose/JavaScript

I am seeking guidance on utilizing the .create() method within a protected route while implementing deconstructed JavaScript. In the absence of the protected route, I can deconstruct my schema and utilize req.body in .create(...) as shown below. const { ti ...

Is it considered good practice to utilize Vue.js for managing global shared state and implementing for loops outside of components?

Just getting started with Vue.JS and experimenting with creating two lists of books (read and unread) from a shared object in the global data state. This is my approach - working demo (works like a charm! However, I'm wondering if this is considered ...

Encountering a blank page issue with react-router-dom v6 Routes

I am attempting to route a page to the root, but it keeps showing up as a blank page regardless of which JavaScript file I use. It seems like React Router DOM has been updated and no longer uses Switch. I haven't used React since last year, so I' ...

The argument labeled as 'shop' does not fit the criteria for the parameter 'items' or 'cart'

I've been doing some research but haven't had any luck finding a solution. I'm fairly new to Angular and currently working on a webstore project. I followed a tutorial, but encountered an error along the way. import { select, Store } from & ...

Achieve a scrolling effect for just a specific section of an HTML page

Hey there! I'm currently working on adding scrolling text along the side of a webpage for a specific section. My goal is to have three different sections, each with text that stops scrolling when you reach it and then transitions to the next section o ...

Ensuring a radio button is pre-selected by default in React by passing in a prop

Assume I have a React function similar to this function Stars({handleStarClick, starClicked}) { if (starClicked === 3) { document.getElementById('star3').checked = true } return ( <div className="rate"> ...