Skip to content

Commit 7111548

Browse files
fix: move getType outside component, use useId for modal, render all link occurrences
Co-authored-by: digitalnomad91 <2067771+digitalnomad91@users.noreply.github.com>
1 parent d137452 commit 7111548

2 files changed

Lines changed: 28 additions & 22 deletions

File tree

src/components/portfolio/PortfolioModal.tsx

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client'
22

3-
import React, { useEffect, useRef, useState } from 'react'
3+
import React, { useEffect, useId, useRef, useState } from 'react'
44
import Image from 'next/image'
55
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
66
import { faCheck, faTimes } from '@fortawesome/free-solid-svg-icons'
@@ -38,7 +38,8 @@ const PortfolioModal: React.FC<PortfolioModalProps> = ({
3838
}) => {
3939
const [openAccordion, setOpenAccordion] = useState<number | null>(null)
4040
const backdropRef = useRef<HTMLDivElement>(null)
41-
const titleId = useRef(`portfolio-modal-title-${Math.random().toString(36).slice(2)}`)
41+
const generatedId = useId()
42+
const titleId = `portfolio-modal-title-${generatedId}`
4243

4344
useEffect(() => {
4445
if (isOpen) {
@@ -65,24 +66,29 @@ const PortfolioModal: React.FC<PortfolioModalProps> = ({
6566
if (e.target === backdropRef.current) onClose()
6667
}
6768

68-
// Safely render description with an optional inline link
69+
// Safely render description with optional inline links for all occurrences of link.label
6970
const renderDescription = () => {
7071
if (!link || !description.includes(link.label)) {
7172
return description
7273
}
7374
const parts = description.split(link.label)
7475
return (
7576
<>
76-
{parts[0]}
77-
<a
78-
href={link.href}
79-
target="_blank"
80-
rel="noopener noreferrer"
81-
className="text-[#09afdf] hover:underline"
82-
>
83-
{link.label}
84-
</a>
85-
{parts.slice(1).join(link.label)}
77+
{parts.map((part, i) => (
78+
<React.Fragment key={i}>
79+
{part}
80+
{i < parts.length - 1 && (
81+
<a
82+
href={link.href}
83+
target="_blank"
84+
rel="noopener noreferrer"
85+
className="text-[#09afdf] hover:underline"
86+
>
87+
{link.label}
88+
</a>
89+
)}
90+
</React.Fragment>
91+
))}
8692
</>
8793
)
8894
}
@@ -92,7 +98,7 @@ const PortfolioModal: React.FC<PortfolioModalProps> = ({
9298
ref={backdropRef}
9399
role="dialog"
94100
aria-modal="true"
95-
aria-labelledby={titleId.current}
101+
aria-labelledby={titleId}
96102
className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 animate-fadeIn"
97103
onClick={handleBackdropClick}
98104
>
@@ -101,7 +107,7 @@ const PortfolioModal: React.FC<PortfolioModalProps> = ({
101107
>
102108
{/* Modal Header */}
103109
<div className="flex items-center justify-between px-5 py-3 border-b border-gray-200">
104-
<h4 id={titleId.current} className="text-lg font-semibold text-[#333]">{title}</h4>
110+
<h4 id={titleId} className="text-lg font-semibold text-[#333]">{title}</h4>
105111
<button
106112
onClick={onClose}
107113
className="text-gray-400 hover:text-gray-700 transition-colors text-xl leading-none p-1"

src/components/video-player.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ interface VideoPlayerProps {
77
posterSrc: string
88
}
99

10+
function getType(src: string): string | undefined {
11+
if (src.endsWith('.webm')) return 'video/webm'
12+
if (src.endsWith('.mp4')) return 'video/mp4'
13+
if (src.endsWith('.ogg') || src.endsWith('.ogv')) return 'video/ogg'
14+
return undefined
15+
}
16+
1017
const VideoPlayer: React.FC<VideoPlayerProps> = ({ mp4Src, webmSrc, posterSrc }) => {
1118
const videoRef = useRef<HTMLVideoElement>(null)
1219
const [isPlaying, setIsPlaying] = useState(false)
@@ -65,13 +72,6 @@ const VideoPlayer: React.FC<VideoPlayerProps> = ({ mp4Src, webmSrc, posterSrc })
6572
}
6673
}, [attemptPlay])
6774

68-
const getType = (src: string) => {
69-
if (src.endsWith('.webm')) return 'video/webm'
70-
if (src.endsWith('.mp4')) return 'video/mp4'
71-
if (src.endsWith('.ogg') || src.endsWith('.ogv')) return 'video/ogg'
72-
return undefined
73-
}
74-
7575
return (
7676
<div className="relative w-full h-full">
7777
{/* Poster/still image — always rendered underneath, visible until video plays */}

0 commit comments

Comments
 (0)