Skip to content

Conversation

@gocanto
Copy link
Contributor

@gocanto gocanto commented Nov 13, 2025

Summary by CodeRabbit

  • New Features

    • Unified fade animations for loading/content transitions across many pages
    • Inline share icons in post headers and improved post header layout
    • Social links now show loading skeletons before content
  • Style

    • Updated icon styling and accessibility attributes for consistency
    • Improved loading skeleton visuals and smoother content swaps
  • Bug Fixes

    • Enhanced code-block highlighting with dark-mode support and more reliable initialization
  • Tests

    • Updated tests to cover tag normalization and highlighting initialization mocks

@coderabbitai
Copy link

coderabbitai bot commented Nov 13, 2025

Caution

Review failed

The pull request is closed.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

This PR centralizes fade transition CSS into a global stylesheet, removes scoped fade rules from a component, applies fade transitions across many pages/partials to animate skeleton↔content swaps, enhances RecommendationPartial with highlight.js-based syntax highlighting and dark-mode CSS switching, and adds social-links loading state and icon styling in SideNavPartial.

Changes

Cohort / File(s) Summary
Global fade CSS & icon utility
src/components/AccessibleDialog.vue, src/css/support/blog.css
Removes scoped fade transition CSS from AccessibleDialog.vue; adds global fade-* transition classes and blog-side-nav-icon utility in blog.css.
Page-level transitions
src/pages/AboutPage.vue, src/pages/HomePage.vue, src/pages/ProjectsPage.vue, src/pages/ResumePage.vue, src/pages/PostPage.vue, src/pages/TagPostsPage.vue
Wraps skeleton/content branches in Transition/TransitionGroup named "fade" with mode="out-in", appear, and explicit keys; PostPage restructures header (title, tags, inline share icons) and consolidates content under the new header.
Partial transitions & lists
src/partials/ArticlesListPartial.vue, src/partials/FeaturedProjectsPartial.vue, src/partials/TalksPartial.vue
Encloses loading/list/empty branches in transition/transition-group containers named "fade" and assigns keys to animate between states.
RecommendationPartial — highlighting & layout
src/partials/RecommendationPartial.vue
Adds recommendationsContainer ref; restructures item markup (avatar + flex text); integrates highlight.js initialization, dark-mode CSS switching via watchEffect, onMounted, and watch; applies syntax highlighting to recommendation code blocks; uses DOMPurify/markdown utilities.
SideNavPartial — social loading & icons
src/partials/SideNavPartial.vue
Adds isLoadingSocialLinks, socialSkeletonCount, shouldDisplaySocialSection; moves social links fetch into onMounted with loading lifecycle and finally-reset; renders skeleton placeholders while loading; SVG icons updated to use blog-side-nav-icon and ARIA/viewBox attributes.
Tag utilities
src/support/tags.ts
Adds private static formatParam(tag: string) to trim/lowercase tags and updates routeFor(tag) to use the normalized param.
Tests — mocks & expectations updated
tests/partials/EducationPartial.test.ts, tests/partials/RecommendationPartial.test.ts, tests/pages/PostPage.test.ts, tests/pages/ProjectsPage.test.ts, tests/support/tags.test.ts
Exposes/mocks initializeHighlighter in @/support/markdown.ts mocks; updates tests to expect lowercased tag params, empty-state messages, and new normalization behavior.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant User
    participant Page
    participant Fetch
    participant DOM
    participant CSS
    participant Highlighter
    participant SideFetch

    User->>Page: navigate / load
    Page->>DOM: render skeleton (key="skeleton")
    DOM->>CSS: apply fade-enter (fade-enter-from -> fade-enter-active)
    Page->>Fetch: request page data
    Note right of SideFetch: social links lifecycle
    Page->>SideFetch: fetch social links (onMounted)
    SideFetch-->>Page: social links or empty
    Page->>DOM: update social section (skeleton -> links)
    Fetch-->>Page: data arrives
    Page->>DOM: swap key -> "content"
    DOM->>CSS: fade skeleton out, fade content in
    Page->>Highlighter: initializeHighlighter (if content contains code)
    Highlighter-->>DOM: highlight code blocks
    DOM->>User: content with transitions and highlighted code
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Areas to review closely:
    • src/partials/RecommendationPartial.vue — highlight.js init timing, recommendationsContainer scoping, DOMPurify usage, and dark-mode CSS switching.
    • src/partials/SideNavPartial.vue — social links fetch lifecycle, skeleton rendering count, and accessibility attributes on SVGs.
    • src/pages/PostPage.vue — tag RouterLink param normalization, transition key correctness, and share icon wiring.

Possibly related PRs

Poem

🐰 I hopped through code with nimble paws,

Fade and skeletons now yield to laws;
Tiny icons find their styled place,
Code glows bright in dark-mode's embrace;
A joyful hop — transitions trace. ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Enhance UX - II' is too vague and generic to clearly convey what specific improvements were made. Consider using a more descriptive title that highlights a primary change, such as 'Add fade transitions and improve component animations' or 'Refactor page transitions with new CSS helpers'.
✅ 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.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0ea6209 and be806f2.

📒 Files selected for processing (9)
  • src/pages/ProjectsPage.vue (3 hunks)
  • src/partials/FeaturedProjectsPartial.vue (1 hunks)
  • src/partials/TalksPartial.vue (1 hunks)
  • src/support/tags.ts (2 hunks)
  • tests/pages/PostPage.test.ts (3 hunks)
  • tests/pages/ProjectsPage.test.ts (2 hunks)
  • tests/partials/EducationPartial.test.ts (1 hunks)
  • tests/partials/RecommendationPartial.test.ts (1 hunks)
  • tests/support/tags.test.ts (1 hunks)

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.

@gocanto gocanto changed the title Chore/formatting chore: Enhance UX - II Nov 13, 2025
@gocanto gocanto marked this pull request as ready for review November 13, 2025 09:19
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: 4

🧹 Nitpick comments (2)
src/partials/RecommendationPartial.vue (2)

75-100: Remove redundant initialization call.

The initializeHighlighter is called both in the watcher with immediate: true (line 83) and in onMounted (line 99). Since the watcher runs immediately on component mount, the onMounted call is redundant.

Apply this diff to remove the redundant initialization:

-onMounted(async () => {
-	await initializeHighlighter(highlight);
-});

67-73: Consider preloading highlight.js styles to prevent FOUC.

Dynamic imports of CSS stylesheets can cause a flash of unstyled content (FOUC) when switching between light and dark modes. Consider preloading both stylesheets or using a different approach to theme switching.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c3821c5 and 5f53d17.

⛔ Files ignored due to path filters (1)
  • public/images/recommendation/grant-riggle.jpeg is excluded by !**/*.jpeg
📒 Files selected for processing (14)
  • src/components/AccessibleDialog.vue (0 hunks)
  • src/css/support/blog.css (2 hunks)
  • src/pages/AboutPage.vue (2 hunks)
  • src/pages/HomePage.vue (1 hunks)
  • src/pages/PostPage.vue (1 hunks)
  • src/pages/ProjectsPage.vue (2 hunks)
  • src/pages/ResumePage.vue (2 hunks)
  • src/pages/TagPostsPage.vue (1 hunks)
  • src/partials/ArticlesListPartial.vue (1 hunks)
  • src/partials/FeaturedProjectsPartial.vue (1 hunks)
  • src/partials/RecommendationPartial.vue (2 hunks)
  • src/partials/SideNavPartial.vue (7 hunks)
  • src/partials/TalksPartial.vue (1 hunks)
  • src/support/tags.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • src/components/AccessibleDialog.vue
🧰 Additional context used
🪛 GitHub Actions: Unit Tests
src/partials/RecommendationPartial.vue

[error] 99-99: Vitest: No "initializeHighlighter" export is defined on the "@/support/markdown.ts" mock. Did you forget to return it from "vi.mock"?

🪛 GitHub Check: vitest
src/partials/RecommendationPartial.vue

[failure] 83-83: Unhandled error
Error: [vitest] No "initializeHighlighter" export is defined on the "@/support/markdown.ts" mock. Did you forget to return it from "vi.mock"?
If you need to partially mock a module, you can use "importOriginal" helper inside:

vi.mock(import("@/support/markdown.ts"), async (importOriginal) => {
const actual = await importOriginal()
return {
...actual,
// your mocked methods
}
})

❯ VitestMocker.createError node_modules/vitest/dist/chunks/execute.B7h3T_Hc.js:284:17
❯ Object.get node_modules/vitest/dist/chunks/execute.B7h3T_Hc.js:330:16
❯ immediate src/partials/RecommendationPartial.vue:83:9
❯ processTicksAndRejections node:internal/process/task_queues:105:5

This error originated in "tests/partials/RecommendationPartial.test.ts" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.


[failure] 99-99: Unhandled error
Error: [vitest] No "initializeHighlighter" export is defined on the "@/support/markdown.ts" mock. Did you forget to return it from "vi.mock"?
If you need to partially mock a module, you can use "importOriginal" helper inside:

vi.mock(import("@/support/markdown.ts"), async (importOriginal) => {
const actual = await importOriginal()
return {
...actual,
// your mocked methods
}
})

❯ VitestMocker.createError node_modules/vitest/dist/chunks/execute.B7h3T_Hc.js:284:17
❯ Object.get node_modules/vitest/dist/chunks/execute.B7h3T_Hc.js:330:16
❯ src/partials/RecommendationPartial.vue:99:8
❯ node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:2861:40
❯ callWithErrorHandling node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:19
❯ callWithAsyncErrorHandling node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:207:17
❯ hook.__weh.hook.__weh node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:2841:19
❯ flushPostFlushCbs node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:382:28
❯ render node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:6018:7
❯ mount node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3984:13

This error originated in "tests/partials/RecommendationPartial.test.ts" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.


[failure] 83-83: Unhandled error
Error: [vitest] No "initializeHighlighter" export is defined on the "@/support/markdown.ts" mock. Did you forget to return it from "vi.mock"?
If you need to partially mock a module, you can use "importOriginal" helper inside:

vi.mock(import("@/support/markdown.ts"), async (importOriginal) => {
const actual = await importOriginal()
return {
...actual,
// your mocked methods
}
})

❯ VitestMocker.createError node_modules/vitest/dist/chunks/execute.B7h3T_Hc.js:284:17
❯ Object.get node_modules/vitest/dist/chunks/execute.B7h3T_Hc.js:330:16
❯ immediate src/partials/RecommendationPartial.vue:83:9
❯ processTicksAndRejections node:internal/process/task_queues:105:5

This error originated in "tests/partials/RecommendationPartial.test.ts" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.


[failure] 99-99: Unhandled error
Error: [vitest] No "initializeHighlighter" export is defined on the "@/support/markdown.ts" mock. Did you forget to return it from "vi.mock"?
If you need to partially mock a module, you can use "importOriginal" helper inside:

vi.mock(import("@/support/markdown.ts"), async (importOriginal) => {
const actual = await importOriginal()
return {
...actual,
// your mocked methods
}
})

❯ VitestMocker.createError node_modules/vitest/dist/chunks/execute.B7h3T_Hc.js:284:17
❯ Object.get node_modules/vitest/dist/chunks/execute.B7h3T_Hc.js:330:16
❯ src/partials/RecommendationPartial.vue:99:8
❯ node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:2861:40
❯ callWithErrorHandling node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:19
❯ callWithAsyncErrorHandling node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:207:17
❯ hook.__weh.hook.__weh node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:2841:19
❯ flushPostFlushCbs node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:382:28
❯ render node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:6018:7
❯ mount node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3984:13

This error originated in "tests/partials/RecommendationPartial.test.ts" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.

🔇 Additional comments (9)
src/partials/RecommendationPartial.vue (1)

7-30: Layout refactoring looks good.

The new two-column layout structure with avatar and content areas improves maintainability. The use of post-markdown class for consistent styling is a good pattern.

src/pages/AboutPage.vue (2)

55-62: LGTM!

The transition wrapper for the "Let's Connect" section is properly configured with stable keys and appropriate mode settings. This provides a smooth user experience when loading profile data.


74-77: LGTM!

The skills widget transition follows the same pattern as the rest of the application and correctly handles the loading-to-content state change.

src/css/support/blog.css (2)

24-26: LGTM!

The new icon utility class is straightforward and follows Tailwind conventions.


213-222: LGTM!

The fade transition classes are implemented correctly with standard opacity transitions. This provides a consistent animation pattern across all components using the fade transition.

src/partials/ArticlesListPartial.vue (1)

25-33: LGTM!

The transition wrapper correctly uses <transition> (not transition-group) for conditional rendering with proper keys. The three-state pattern (loading, list, empty) is well-structured.

src/pages/HomePage.vue (1)

29-32: LGTM!

The skills widget transition is properly implemented with stable keys and follows the established pattern across the application.

src/pages/ResumePage.vue (2)

33-51: LGTM!

The main content transition wrapper is well-structured with appropriate keys for skeleton and content states. The computed shouldShowSkeleton property makes the condition clear and maintainable.


64-67: LGTM!

The skills widget transition follows the established pattern and correctly handles the loading state.

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: 5

Caution

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

⚠️ Outside diff range comments (1)
src/pages/PostPage.vue (1)

211-216: Encode share URLs/titles

xURLFor and the LinkedIn share link build query strings with raw post.title and fullURLFor(post). Titles or URLs containing spaces or & will break the share links. Please URL-encode both parameters before concatenation.

Apply this diff:

-const xURLFor = (post: PostResponse) => {
-	return `https://x.com/intent/tweet?url=${fullURLFor(post)}&text=${post.title}`;
-};
+const xURLFor = (post: PostResponse) => {
+	const shareUrl = encodeURIComponent(fullURLFor(post));
+	const shareText = encodeURIComponent(post.title);
+	return `https://x.com/intent/tweet?url=${shareUrl}&text=${shareText}`;
+};

-const fullURLFor = (post: PostResponse) => siteUrlFor(`/post/${post.slug}`);
+const fullURLFor = (post: PostResponse) => siteUrlFor(`/post/${post.slug}`);

And in the template:

-:href="`https://www.linkedin.com/sharing/share-offsite/?url=${fullURLFor(post)}`"
+:href="`https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(fullURLFor(post))}`"
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c3821c5 and 5f53d17.

⛔ Files ignored due to path filters (1)
  • public/images/recommendation/grant-riggle.jpeg is excluded by !**/*.jpeg
📒 Files selected for processing (14)
  • src/components/AccessibleDialog.vue (0 hunks)
  • src/css/support/blog.css (2 hunks)
  • src/pages/AboutPage.vue (2 hunks)
  • src/pages/HomePage.vue (1 hunks)
  • src/pages/PostPage.vue (1 hunks)
  • src/pages/ProjectsPage.vue (2 hunks)
  • src/pages/ResumePage.vue (2 hunks)
  • src/pages/TagPostsPage.vue (1 hunks)
  • src/partials/ArticlesListPartial.vue (1 hunks)
  • src/partials/FeaturedProjectsPartial.vue (1 hunks)
  • src/partials/RecommendationPartial.vue (2 hunks)
  • src/partials/SideNavPartial.vue (7 hunks)
  • src/partials/TalksPartial.vue (1 hunks)
  • src/support/tags.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • src/components/AccessibleDialog.vue
🧰 Additional context used
🪛 GitHub Actions: Unit Tests
src/partials/RecommendationPartial.vue

[error] 99-99: [vitest] No "initializeHighlighter" export is defined on the "@/support/markdown.ts" mock. Did you forget to return it from "vi.mock"?


[error] 83-83: [vitest] No "initializeHighlighter" export is defined on the "@/support/markdown.ts" mock. Did you forget to return it from "vi.mock"?

🪛 GitHub Check: vitest
src/partials/RecommendationPartial.vue

[failure] 83-83: Unhandled error
Error: [vitest] No "initializeHighlighter" export is defined on the "@/support/markdown.ts" mock. Did you forget to return it from "vi.mock"?
If you need to partially mock a module, you can use "importOriginal" helper inside:

vi.mock(import("@/support/markdown.ts"), async (importOriginal) => {
const actual = await importOriginal()
return {
...actual,
// your mocked methods
}
})

❯ VitestMocker.createError node_modules/vitest/dist/chunks/execute.B7h3T_Hc.js:284:17
❯ Object.get node_modules/vitest/dist/chunks/execute.B7h3T_Hc.js:330:16
❯ immediate src/partials/RecommendationPartial.vue:83:9
❯ processTicksAndRejections node:internal/process/task_queues:105:5

This error originated in "tests/partials/RecommendationPartial.test.ts" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.


[failure] 99-99: Unhandled error
Error: [vitest] No "initializeHighlighter" export is defined on the "@/support/markdown.ts" mock. Did you forget to return it from "vi.mock"?
If you need to partially mock a module, you can use "importOriginal" helper inside:

vi.mock(import("@/support/markdown.ts"), async (importOriginal) => {
const actual = await importOriginal()
return {
...actual,
// your mocked methods
}
})

❯ VitestMocker.createError node_modules/vitest/dist/chunks/execute.B7h3T_Hc.js:284:17
❯ Object.get node_modules/vitest/dist/chunks/execute.B7h3T_Hc.js:330:16
❯ src/partials/RecommendationPartial.vue:99:8
❯ node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:2861:40
❯ callWithErrorHandling node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:19
❯ callWithAsyncErrorHandling node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:207:17
❯ hook.__weh.hook.__weh node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:2841:19
❯ flushPostFlushCbs node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:382:28
❯ render node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:6018:7
❯ mount node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3984:13

This error originated in "tests/partials/RecommendationPartial.test.ts" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.


[failure] 83-83: Unhandled error
Error: [vitest] No "initializeHighlighter" export is defined on the "@/support/markdown.ts" mock. Did you forget to return it from "vi.mock"?
If you need to partially mock a module, you can use "importOriginal" helper inside:

vi.mock(import("@/support/markdown.ts"), async (importOriginal) => {
const actual = await importOriginal()
return {
...actual,
// your mocked methods
}
})

❯ VitestMocker.createError node_modules/vitest/dist/chunks/execute.B7h3T_Hc.js:284:17
❯ Object.get node_modules/vitest/dist/chunks/execute.B7h3T_Hc.js:330:16
❯ immediate src/partials/RecommendationPartial.vue:83:9
❯ processTicksAndRejections node:internal/process/task_queues:105:5

This error originated in "tests/partials/RecommendationPartial.test.ts" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.


[failure] 99-99: Unhandled error
Error: [vitest] No "initializeHighlighter" export is defined on the "@/support/markdown.ts" mock. Did you forget to return it from "vi.mock"?
If you need to partially mock a module, you can use "importOriginal" helper inside:

vi.mock(import("@/support/markdown.ts"), async (importOriginal) => {
const actual = await importOriginal()
return {
...actual,
// your mocked methods
}
})

❯ VitestMocker.createError node_modules/vitest/dist/chunks/execute.B7h3T_Hc.js:284:17
❯ Object.get node_modules/vitest/dist/chunks/execute.B7h3T_Hc.js:330:16
❯ src/partials/RecommendationPartial.vue:99:8
❯ node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:2861:40
❯ callWithErrorHandling node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:19
❯ callWithAsyncErrorHandling node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:207:17
❯ hook.__weh.hook.__weh node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:2841:19
❯ flushPostFlushCbs node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:382:28
❯ render node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:6018:7
❯ mount node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3984:13

This error originated in "tests/partials/RecommendationPartial.test.ts" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.

🔇 Additional comments (10)
src/support/tags.ts (1)

38-43: Good normalization approach.

Using a dedicated helper to normalize tag parameters before routing ensures consistent URL formatting and prevents case-sensitivity issues in navigation.

src/partials/ArticlesListPartial.vue (1)

25-33: LGTM! Clean transition implementation.

The fade transition is properly configured with explicit keys for each state (skeleton, list, empty), mode="out-in" to prevent layout shifts, and appear for initial animation. This provides a smooth UX when toggling between loading and loaded states.

src/css/support/blog.css (2)

24-26: LGTM! Clean utility class.

The blog-side-nav-icon utility provides consistent sizing for side navigation icons.


213-222: LGTM! Standard fade transition implementation.

The fade transition classes provide smooth 0.3s opacity animations that are properly utilized across multiple components in this PR. The implementation follows Vue transition naming conventions correctly.

src/pages/HomePage.vue (1)

29-32: LGTM! Proper transition implementation.

The fade transition correctly wraps the skills widget with explicit keys and mode="out-in" to ensure smooth animation between skeleton and loaded states.

src/pages/ResumePage.vue (2)

33-51: LGTM! Well-structured content transition.

The main resume content is properly wrapped in a fade transition with explicit keys for skeleton and content states, ensuring smooth animation during data loading.


64-67: LGTM! Consistent sidebar transition.

The sidebar skills widget follows the same transition pattern used throughout the codebase, providing a consistent UX.

src/pages/ProjectsPage.vue (1)

57-60: LGTM! Consistent sidebar transition.

The sidebar skills widget follows the same transition pattern, providing consistent UX across pages.

src/pages/AboutPage.vue (2)

55-62: LGTM! Clean transition for connect section.

The "Let's Connect" paragraph is properly wrapped in a fade transition with explicit keys, ensuring smooth animation between loading and loaded states.


74-77: LGTM! Consistent sidebar transition.

The sidebar follows the same transition pattern used across other pages, maintaining UX consistency.

@gocanto gocanto marked this pull request as draft November 13, 2025 09:25
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

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: 0

🧹 Nitpick comments (2)
tests/partials/RecommendationPartial.test.ts (1)

8-10: Mock should return a resolved Promise to match the real signature.

The real initializeHighlighter function is async and returns Promise<void> (see src/support/markdown.ts). The mock currently returns undefined by default, which may work but is imprecise. If the component awaits this function, returning a proper Promise prevents potential timing or type issues.

Apply this diff to return a resolved Promise:

-const initializeHighlighter = vi.hoisted(() => vi.fn());
+const initializeHighlighter = vi.hoisted(() => vi.fn(() => Promise.resolve()));
tests/partials/EducationPartial.test.ts (1)

8-10: Mock should return a resolved Promise to match the real signature.

The real initializeHighlighter function is async and returns Promise<void> (see src/support/markdown.ts). The mock currently returns undefined by default, which may work but is imprecise. If the component awaits this function, returning a proper Promise prevents potential timing or type issues.

Apply this diff to return a resolved Promise:

-const initializeHighlighter = vi.hoisted(() => vi.fn());
+const initializeHighlighter = vi.hoisted(() => vi.fn(() => Promise.resolve()));
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5f53d17 and 0ea6209.

📒 Files selected for processing (2)
  • tests/partials/EducationPartial.test.ts (1 hunks)
  • tests/partials/RecommendationPartial.test.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
tests/partials/EducationPartial.test.ts (1)
src/support/markdown.ts (1)
  • initializeHighlighter (80-110)
tests/partials/RecommendationPartial.test.ts (1)
src/support/markdown.ts (1)
  • initializeHighlighter (80-110)

@gocanto gocanto marked this pull request as ready for review November 13, 2025 09:45
@gocanto gocanto marked this pull request as draft November 13, 2025 09:52
@gocanto gocanto marked this pull request as ready for review November 13, 2025 09:54
@gocanto gocanto merged commit 2f49d6b into main Nov 13, 2025
9 checks passed
@gocanto gocanto deleted the chore/formatting branch November 13, 2025 09:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants