Skip to content

Conversation

@thienty1207
Copy link

@thienty1207 thienty1207 commented Nov 6, 2025

Summary by CodeRabbit

  • New Features

    • Added personal details section displaying contact information and links in the About area.
  • Updates

    • Portfolio rebranded with personalized name and logo.
    • Technology stack refreshed with Python, Golang, Rust, and PostgreSQL.
    • Work experience and project showcase updated.
    • Removed testimonials section.
    • Enhanced visual effects with improved parallax animations.

@coderabbitai
Copy link

coderabbitai bot commented Nov 6, 2025

Walkthrough

A portfolio site rebranding from Adrian's "3dfolio" to Ho Thien Ty's portfolio. Changes include migrating from react-tilt to react-parallax-tilt, removing testimonials, updating the tech stack (Python, Golang, Rust, PostgreSQL), restructuring the About section with personal details, and refreshing all personal content references.

Changes

Cohort / File(s) Summary
Metadata & Configuration
index.html, package.json
Updated favicon reference and page title to reflect new portfolio branding; changed package name from "3dfolio" to "frontend" and upgraded react-tilt to react-parallax-tilt v1.7.0
Asset & Constant Exports
src/assets/index.js, src/constants/index.js
Added new asset exports (python, golang, rust, postgresql, archlinux, plpsoft, realtimechat, birth, location, phone, email, linkedin, cv); overhauled technologies list, replaced multi-project lineup with single Real-time Chat project, updated experience to IT Intern role at Phuc Lam Phuong Software Technology Co., Ltd
Component Personalization
src/components/Hero.jsx, src/components/Navbar.jsx, src/components/Experience.jsx
Updated personal branding (name from Adrian to Ho Thien Ty); replaced logo reference with '/newlogo.svg'; updated hero subtitle to "Adaptable & quick learner"; minor text refinement in Experience component
Component Restructuring
src/components/About.jsx, src/components/Works.jsx
Redesigned About section replacing animated ServiceCard composition with staggered personal details grid; migrated Works component from react-tilt to react-parallax-tilt with updated property-based configuration
App Structure
src/App.jsx
Removed Feedbacks component import and render call from main application layout

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • react-parallax-tilt migration: Verify new tilt properties (tiltMaxAngleX, tiltMaxAngleY, scale, transitionSpeed) produce expected visual behavior compared to react-tilt
  • About component redesign: Ensure responsive grid layout, fade-up animations, and hover scaling work correctly across breakpoints
  • Constants overhaul: Cross-reference new technologies, projects, and experiences throughout the codebase to catch any orphaned imports or missing asset references

🐰 A portfolio reborn, with tilt and spin,
New colors, new tech—let Ho Thien begin!
From Adrian's past to futures anew,
Parallax dreams and a tech stack brew.

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'first up' is vague and generic, providing no meaningful information about the changeset's purpose or primary changes. Revise the title to be descriptive and specific, such as 'Update portfolio with new branding and personal details' or 'Replace Adrian portfolio content with Ho Thien Ty profile'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/constants/index.js (1)

50-67: Remove the unused services array.

The services array is exported from src/constants/index.js but is not imported by any component in the codebase. It's dead code and should be removed from both the array definition (lines 50-67) and the export statement (line 148).

🧹 Nitpick comments (4)
package.json (1)

2-2: Consider a more descriptive package name.

The name "frontend" is quite generic. Consider using something more specific like "hothientyportfolio" or "ty-portfolio" to better reflect the project's purpose.

src/components/Navbar.jsx (1)

6-6: Inconsistent asset handling: hardcoded logo path.

The logo path is hardcoded as '/newlogo.svg' instead of being imported from the assets module like other images (menu, close). This creates inconsistency and reduces maintainability.

Consider importing the logo from assets for consistency:

-import { menu, close } from "../assets";
+import { menu, close, logo } from "../assets";

Then use it in the component:

-<img src='/newlogo.svg' alt='logo' className='w-9 h-9 object-contain' />
+<img src={logo} alt='logo' className='w-9 h-9 object-contain' />

Note: Ensure the logo export in src/assets/index.js points to the correct newlogo.svg file, or update the asset file accordingly.

Also applies to: 45-45

src/components/About.jsx (2)

27-90: Improve alt text for accessibility.

The alt text for icons (e.g., alt='Birth', alt='Email') merely repeats the field name and doesn't add meaningful context for screen readers. Consider using more descriptive alternatives like alt='Date of birth icon' or alt='Email icon'.

Apply this diff to improve the alt text:

-          <img src={birth} alt='Birth' className='w-6 h-6 object-contain' />
+          <img src={birth} alt='Date of birth icon' className='w-6 h-6 object-contain' />
           <div>
             <p className='text-secondary text-[14px]'>Date of birth</p>
             <p className='text-white text-[16px]'>12/07/2003</p>
           </div>
         </motion.div>
 
         {/* Email */}
         <motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
-          <img src={email} alt='Email' className='w-6 h-6 object-contain' />
+          <img src={email} alt='Email icon' className='w-6 h-6 object-contain' />
           <div>
             <p className='text-secondary text-[14px]'>Email</p>
             <a href='mailto:[email protected]' className='text-white text-[16px] hover:text-[#66ffa6]'>
               [email protected]
             </a>
           </div>
         </motion.div>
 
         {/* Location (đổi vị trí với Phone) */}
         <motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
-          <img src={location} alt='Location' className='w-6 h-6 object-contain' />
+          <img src={location} alt='Location icon' className='w-6 h-6 object-contain' />
           <div>
             <p className='text-secondary text-[14px]'>Location</p>
             <p className='text-white text-[16px]'>Chau Doc, An Giang</p>
           </div>
         </motion.div>
 
         {/* LinkedIn */}
         <motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
-          <img src={linkedin} alt='LinkedIn' className='w-6 h-6 object-contain' />
+          <img src={linkedin} alt='LinkedIn icon' className='w-6 h-6 object-contain' />
           <div>
             <p className='text-secondary text-[14px]'>LinkedIn</p>
             <a href='https://linkedin.com/in/htty' target='_blank' rel='noreferrer' className='text-white text-[16px] hover:text-[#66ffa6]'>
               linkedin.com/in/htty
             </a>
           </div>
         </motion.div>
 
         {/* Phone */}
         <motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
-          <img src={phone} alt='Phone' className='w-6 h-6 object-contain' />
+          <img src={phone} alt='Phone icon' className='w-6 h-6 object-contain' />
           <div>
             <p className='text-secondary text-[14px]'>Phone</p>
             <p className='text-white text-[16px]'>+84 399623947</p>
           </div>
         </motion.div>
 
         {/* CV item */}
         <motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
-          <img src={cv} alt='CV' className='w-6 h-6 object-contain' />
+          <img src={cv} alt='CV icon' className='w-6 h-6 object-contain' />

27-47: Use English for code comments.

Comments are written in Vietnamese (e.g., lines 27, 47: "đổi vị trí với Phone"). For international collaboration and code maintainability, consider using English for all code comments.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9985e4b and 711b399.

⛔ Files ignored due to path filters (15)
  • package-lock.json is excluded by !**/package-lock.json
  • public/newlogo.svg is excluded by !**/*.svg
  • src/assets/CV.png is excluded by !**/*.png
  • src/assets/birth.png is excluded by !**/*.png
  • src/assets/company/plpsoft.png is excluded by !**/*.png
  • src/assets/email.png is excluded by !**/*.png
  • src/assets/linkedin.png is excluded by !**/*.png
  • src/assets/location.png is excluded by !**/*.png
  • src/assets/phone.png is excluded by !**/*.png
  • src/assets/realtimechat.png is excluded by !**/*.png
  • src/assets/tech/archlinux.png is excluded by !**/*.png
  • src/assets/tech/golang.png is excluded by !**/*.png
  • src/assets/tech/postgresql.png is excluded by !**/*.png
  • src/assets/tech/python.png is excluded by !**/*.png
  • src/assets/tech/rust.png is excluded by !**/*.png
📒 Files selected for processing (10)
  • index.html (1 hunks)
  • package.json (2 hunks)
  • src/App.jsx (2 hunks)
  • src/assets/index.js (2 hunks)
  • src/components/About.jsx (1 hunks)
  • src/components/Experience.jsx (1 hunks)
  • src/components/Hero.jsx (1 hunks)
  • src/components/Navbar.jsx (2 hunks)
  • src/components/Works.jsx (2 hunks)
  • src/constants/index.js (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/components/Hero.jsx (1)
src/styles.js (1)
  • styles (1-15)
src/components/About.jsx (1)
src/styles.js (1)
  • styles (1-15)
🔇 Additional comments (11)
index.html (1)

5-7: LGTM! Metadata updates are consistent with the rebranding.

The favicon and page title changes align with the portfolio rebranding to "Ho Thien Ty".

package.json (1)

20-20: Dependency migration looks good.

The migration from react-tilt to react-parallax-tilt is properly reflected here and the usage is updated in src/components/Works.jsx.

src/assets/index.js (1)

23-27: LGTM! Asset additions are properly structured.

All new imports have corresponding exports, and the additions follow the existing pattern consistently.

Also applies to: 33-33, 38-44, 68-72, 77-77, 81-87

src/components/Experience.jsx (1)

64-64: LGTM! Minor text improvement.

The contraction makes the text more natural and conversational.

src/App.jsx (1)

3-3: LGTM! Clean removal of Feedbacks component.

The Feedbacks/Testimonials section has been cleanly removed from both the imports and the render. The comment indicates this is intentional.

Also applies to: 17-17

src/components/Hero.jsx (1)

19-23: LGTM! Hero section updated with new branding.

The name and subtext updates are consistent with the portfolio rebranding.

src/components/Navbar.jsx (1)

47-47: LGTM! Brand text updated.

The navbar branding is now consistent with the portfolio rebranding.

src/components/Works.jsx (1)

21-26: The react-parallax-tilt API usage is correct.

The props tiltMaxAngleX, tiltMaxAngleY, scale, and transitionSpeed are all confirmed valid props in the official react-parallax-tilt v1.7.x API. The migration mapping from react-tilt is accurate:

  • max: 45tiltMaxAngleX={45} and tiltMaxAngleY={45}
  • speed: 450transitionSpeed={450}

No issues found.

src/constants/index.js (3)

120-146: LGTM!

The project entry is well-structured with appropriate tags, description, and source code link.


93-118: The testimonials array is actively used and not unused placeholder data.

Verification shows that src/components/Feedbacks.jsx actively imports and uses the testimonials array (line 7: import { testimonials } from "../constants" and line 58: testimonials.map((testimonial, index) => ...)). The Feedbacks component is functional and rendering the testimonial data. The original review comment's premise—that testimonials are "no longer used" or that "the testimonials component" was removed—is incorrect.

Likely an incorrect or invalid review comment.


1-33: ****

The review comment is based on an incorrect premise. The verification confirms that ALL 19 imports are actively used and exported from src/assets/index.js, making them necessary imports in src/constants/index.js. These assets are being re-exported as part of the module's public API and are referenced throughout the codebase and documentation. No changes are needed.

Likely an incorrect or invalid review comment.

Comment on lines +23 to +91
<motion.div
variants={staggerContainer(0.2, 0)}
className='mt-10 grid sm:grid-cols-2 gap-6'
>
{/* Birth (đổi vị trí với Phone) */}
<motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
<img src={birth} alt='Birth' className='w-6 h-6 object-contain' />
<div>
<p className='text-secondary text-[14px]'>Date of birth</p>
<p className='text-white text-[16px]'>12/07/2003</p>
</div>
</motion.div>

{/* Email */}
<motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
<img src={email} alt='Email' className='w-6 h-6 object-contain' />
<div>
<p className='text-secondary text-[14px]'>Email</p>
<a href='mailto:[email protected]' className='text-white text-[16px] hover:text-[#66ffa6]'>
[email protected]
</a>
</div>
</motion.div>

<div className='mt-20 flex flex-wrap gap-10'>
{services.map((service, index) => (
<ServiceCard key={service.title} index={index} {...service} />
))}
</div>
{/* Location (đổi vị trí với Phone) */}
<motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
<img src={location} alt='Location' className='w-6 h-6 object-contain' />
<div>
<p className='text-secondary text-[14px]'>Location</p>
<p className='text-white text-[16px]'>Chau Doc, An Giang</p>
</div>
</motion.div>

{/* LinkedIn */}
<motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
<img src={linkedin} alt='LinkedIn' className='w-6 h-6 object-contain' />
<div>
<p className='text-secondary text-[14px]'>LinkedIn</p>
<a href='https://linkedin.com/in/htty' target='_blank' rel='noreferrer' className='text-white text-[16px] hover:text-[#66ffa6]'>
linkedin.com/in/htty
</a>
</div>
</motion.div>

{/* Phone */}
<motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
<img src={phone} alt='Phone' className='w-6 h-6 object-contain' />
<div>
<p className='text-secondary text-[14px]'>Phone</p>
<p className='text-white text-[16px]'>+84 399623947</p>
</div>
</motion.div>

{/* CV item */}
<motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
<img src={cv} alt='CV' className='w-6 h-6 object-contain' />
<div>
<p className='text-secondary text-[14px]'>CV</p>
<a
href='https://drive.google.com/file/d/1VKtMubxBp8E_iKZzRoKDP_Ldmdsrurnd/view?usp=drive_link'
target='_blank'
rel='noreferrer'
className='text-white text-[16px] hover:text-[#66ffa6]'
>
View CV
</a>
</div>
</motion.div>
</motion.div>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix animation timing to enable stagger effect.

All personal detail blocks use fadeIn("up", "spring", 0, 0.75) with a delay of 0, which prevents the staggerContainer(0.2, 0) from producing a staggered animation. For a proper stagger effect, each child should have an incrementing delay or rely on the parent's stagger behavior.

Apply this diff to fix the stagger timing:

       <motion.div
-        variants={staggerContainer(0.2, 0)}
+        variants={staggerContainer()}
+        initial="hidden"
+        whileInView="show"
         className='mt-10 grid sm:grid-cols-2 gap-6'
       >
         {/* Birth (đổi vị trí với Phone) */}
-        <motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
+        <motion.div variants={fadeIn("up", "spring", 0.1, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
           <img src={birth} alt='Birth' className='w-6 h-6 object-contain' />
           <div>
             <p className='text-secondary text-[14px]'>Date of birth</p>
             <p className='text-white text-[16px]'>12/07/2003</p>
           </div>
         </motion.div>
 
         {/* Email */}
-        <motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
+        <motion.div variants={fadeIn("up", "spring", 0.2, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
           <img src={email} alt='Email' className='w-6 h-6 object-contain' />
           <div>
             <p className='text-secondary text-[14px]'>Email</p>
             <a href='mailto:[email protected]' className='text-white text-[16px] hover:text-[#66ffa6]'>
               [email protected]
             </a>
           </div>
         </motion.div>
 
         {/* Location (đổi vị trí với Phone) */}
-        <motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
+        <motion.div variants={fadeIn("up", "spring", 0.3, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
           <img src={location} alt='Location' className='w-6 h-6 object-contain' />
           <div>
             <p className='text-secondary text-[14px]'>Location</p>
             <p className='text-white text-[16px]'>Chau Doc, An Giang</p>
           </div>
         </motion.div>
 
         {/* LinkedIn */}
-        <motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
+        <motion.div variants={fadeIn("up", "spring", 0.4, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
           <img src={linkedin} alt='LinkedIn' className='w-6 h-6 object-contain' />
           <div>
             <p className='text-secondary text-[14px]'>LinkedIn</p>
             <a href='https://linkedin.com/in/htty' target='_blank' rel='noreferrer' className='text-white text-[16px] hover:text-[#66ffa6]'>
               linkedin.com/in/htty
             </a>
           </div>
         </motion.div>
 
         {/* Phone */}
-        <motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
+        <motion.div variants={fadeIn("up", "spring", 0.5, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
           <img src={phone} alt='Phone' className='w-6 h-6 object-contain' />
           <div>
             <p className='text-secondary text-[14px]'>Phone</p>
             <p className='text-white text-[16px]'>+84 399623947</p>
           </div>
         </motion.div>
 
         {/* CV item */}
-        <motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
+        <motion.div variants={fadeIn("up", "spring", 0.6, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
           <img src={cv} alt='CV' className='w-6 h-6 object-contain' />
           <div>
             <p className='text-secondary text-[14px]'>CV</p>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<motion.div
variants={staggerContainer(0.2, 0)}
className='mt-10 grid sm:grid-cols-2 gap-6'
>
{/* Birth (đổi vị trí với Phone) */}
<motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
<img src={birth} alt='Birth' className='w-6 h-6 object-contain' />
<div>
<p className='text-secondary text-[14px]'>Date of birth</p>
<p className='text-white text-[16px]'>12/07/2003</p>
</div>
</motion.div>
{/* Email */}
<motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
<img src={email} alt='Email' className='w-6 h-6 object-contain' />
<div>
<p className='text-secondary text-[14px]'>Email</p>
<a href='mailto:[email protected]' className='text-white text-[16px] hover:text-[#66ffa6]'>
tytybill123@gmail.com
</a>
</div>
</motion.div>
<div className='mt-20 flex flex-wrap gap-10'>
{services.map((service, index) => (
<ServiceCard key={service.title} index={index} {...service} />
))}
</div>
{/* Location (đổi vị trí với Phone) */}
<motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
<img src={location} alt='Location' className='w-6 h-6 object-contain' />
<div>
<p className='text-secondary text-[14px]'>Location</p>
<p className='text-white text-[16px]'>Chau Doc, An Giang</p>
</div>
</motion.div>
{/* LinkedIn */}
<motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
<img src={linkedin} alt='LinkedIn' className='w-6 h-6 object-contain' />
<div>
<p className='text-secondary text-[14px]'>LinkedIn</p>
<a href='https://linkedin.com/in/htty' target='_blank' rel='noreferrer' className='text-white text-[16px] hover:text-[#66ffa6]'>
linkedin.com/in/htty
</a>
</div>
</motion.div>
{/* Phone */}
<motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
<img src={phone} alt='Phone' className='w-6 h-6 object-contain' />
<div>
<p className='text-secondary text-[14px]'>Phone</p>
<p className='text-white text-[16px]'>+84 399623947</p>
</div>
</motion.div>
{/* CV item */}
<motion.div variants={fadeIn("up", "spring", 0, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
<img src={cv} alt='CV' className='w-6 h-6 object-contain' />
<div>
<p className='text-secondary text-[14px]'>CV</p>
<a
href='https://drive.google.com/file/d/1VKtMubxBp8E_iKZzRoKDP_Ldmdsrurnd/view?usp=drive_link'
target='_blank'
rel='noreferrer'
className='text-white text-[16px] hover:text-[#66ffa6]'
>
View CV
</a>
</div>
</motion.div>
</motion.div>
<motion.div
variants={staggerContainer()}
initial="hidden"
whileInView="show"
className='mt-10 grid sm:grid-cols-2 gap-6'
>
{/* Birth (đổi vị trí với Phone) */}
<motion.div variants={fadeIn("up", "spring", 0.1, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
<img src={birth} alt='Birth' className='w-6 h-6 object-contain' />
<div>
<p className='text-secondary text-[14px]'>Date of birth</p>
<p className='text-white text-[16px]'>12/07/2003</p>
</div>
</motion.div>
{/* Email */}
<motion.div variants={fadeIn("up", "spring", 0.2, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
<img src={email} alt='Email' className='w-6 h-6 object-contain' />
<div>
<p className='text-secondary text-[14px]'>Email</p>
<a href='mailto:[email protected]' className='text-white text-[16px] hover:text-[#66ffa6]'>
tytybill123@gmail.com
</a>
</div>
</motion.div>
{/* Location (đổi vị trí với Phone) */}
<motion.div variants={fadeIn("up", "spring", 0.3, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
<img src={location} alt='Location' className='w-6 h-6 object-contain' />
<div>
<p className='text-secondary text-[14px]'>Location</p>
<p className='text-white text-[16px]'>Chau Doc, An Giang</p>
</div>
</motion.div>
{/* LinkedIn */}
<motion.div variants={fadeIn("up", "spring", 0.4, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
<img src={linkedin} alt='LinkedIn' className='w-6 h-6 object-contain' />
<div>
<p className='text-secondary text-[14px]'>LinkedIn</p>
<a href='https://linkedin.com/in/htty' target='_blank' rel='noreferrer' className='text-white text-[16px] hover:text-[#66ffa6]'>
linkedin.com/in/htty
</a>
</div>
</motion.div>
{/* Phone */}
<motion.div variants={fadeIn("up", "spring", 0.5, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
<img src={phone} alt='Phone' className='w-6 h-6 object-contain' />
<div>
<p className='text-secondary text-[14px]'>Phone</p>
<p className='text-white text-[16px]'>+84 399623947</p>
</div>
</motion.div>
{/* CV item */}
<motion.div variants={fadeIn("up", "spring", 0.6, 0.75)} whileHover={{ scale: 1.05 }} className='flex items-center gap-3'>
<img src={cv} alt='CV' className='w-6 h-6 object-contain' />
<div>
<p className='text-secondary text-[14px]'>CV</p>
<a
href='https://drive.google.com/file/d/1VKtMubxBp8E_iKZzRoKDP_Ldmdsrurnd/view?usp=drive_link'
target='_blank'
rel='noreferrer'
className='text-white text-[16px] hover:text-[#66ffa6]'
>
View CV
</a>
</div>
</motion.div>
</motion.div>
🤖 Prompt for AI Agents
In src/components/About.jsx lines 23-91, the child motion.divs all call
fadeIn("up", "spring", 0, 0.75) which sets an explicit delay of 0 and overrides
the parent's staggerContainer, preventing staggered entry; remove the explicit
per-child delay (omit the third argument or pass undefined) in each fadeIn call
so the parent staggerContainer(0.2, 0) can control stagger timing, keeping the
direction/type and duration intact.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant