Skip to content

feat(xp): add interactive code-editor ui for experiences#31

Open
caiokf wants to merge 1 commit intomainfrom
ui-explorer-code-editor-experiences
Open

feat(xp): add interactive code-editor ui for experiences#31
caiokf wants to merge 1 commit intomainfrom
ui-explorer-code-editor-experiences

Conversation

@caiokf
Copy link
Owner

@caiokf caiokf commented Dec 14, 2025

code-editor

Replace the vertical timeline with a file-explorer and code-editor styled view for career experiences to provide a more interactive, developer-oriented presentation. This change adds a sidebar file-tree, editor tabs, breadcrumb, line-numbered code block rendering of each experience (including JSDoc-style comments, export object, tags and stack), a logo watermark, and an editor status bar. It also introduces state for active tabs, tab closing, and adjustments to utility functions and styles (spacing, responsive tweaks, syntax classes) to support the new UI layout.

Summary by CodeRabbit

  • New Features
    • Redesigned Experience section with a code editor UI featuring tabbed navigation
    • Added a file explorer sidebar displaying career experiences as selectable files
    • Experiences now render as code snippets with syntax highlighting
    • Introduced tab close functionality for better navigation
    • Added a "+ N more..." control to reveal additional experiences

✏️ Tip: You can customize this high-level summary in your review settings.

Replace the vertical timeline with a file-explorer and code-editor styled view for career experiences to provide a more interactive, developer-oriented presentation. This change adds a sidebar file-tree, editor tabs, breadcrumb, line-numbered code block rendering of each experience (including JSDoc-style comments, export object, tags and stack), a logo watermark, and an editor status bar. It also introduces state for active tabs, tab closing, and adjustments to utility functions and styles (spacing, responsive tweaks, syntax classes) to support the new UI layout.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 14, 2025

Walkthrough

The ExperiencePage component's timeline-based UI is replaced with a code editor interface featuring tabs for experiences, a file explorer sidebar, dynamic TypeScript-like code rendering with inline syntax highlighting, and revised logo handling. Multiple helper utilities for date formatting and via-logo mapping are removed.

Changes

Cohort / File(s) Summary
Code Editor UI Redesign
src/pages/ExperiencePage.vue
Replaced timeline-based experience rendering with an in-page code editor UI, including editor header with tabs, breadcrumb navigation, and code content area displaying experiences as TypeScript object literals with progressive line generation and syntax highlighting.
File Explorer Sidebar
src/pages/ExperiencePage.vue
Added file explorer sidebar listing career experiences as selectable files with active tab highlighting and "+ N more..." control for showing additional entries.
Tab & State Management
src/pages/ExperiencePage.vue
Introduced activeTab ref and closeTab() function to manage tab selection and closure with edge-case guards; added visibleExperiences state for explorer visibility control.
Dynamic Experience Rendering
src/pages/ExperiencePage.vue
Implemented conditional rendering of experience highlights, tags, technologies (via parseTechnologies helper), and optional website field within code blocks; added conditional sections for via and endDate presence.
Utilities & Helpers Removal
src/pages/ExperiencePage.vue
Removed formatDateRange, formatMonth, yearsOfExperience, viaLogos mapping, and getViaLogo helper; replaced logo rendering with conditional watermark approach and viaNames mapping for display names.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Key areas for attention: The new tab management logic in closeTab() and edge-case handling (ensure decrement logic doesn't cause index out-of-bounds); conditional rendering blocks for via, endDate, and website fields; the parseTechnologies logic and inline syntax highlighting implementation; thorough verification that all removed helper functions are properly replaced/deprecated throughout the component.

Poem

🐰 Hops with glee through code so neat,
Timeline gone—editor's a treat!
Tabs and tabs in folders bright,
TypeScript dreams rendered just right.
Experience glows in syntax's might!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(xp): add interactive code-editor ui for experiences' clearly and concisely describes the main change: replacing the timeline UI with a new code-editor style interface for displaying experiences.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ui-explorer-code-editor-experiences

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

Copy link
Contributor

@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

🧹 Nitpick comments (4)
src/pages/ExperiencePage.vue (4)

302-330: Repeated parseTechnologies calls for same data.

parseTechnologies(visibleExperiences[activeTab].technologies) is called multiple times in the template for line number calculations and iteration. Consider computing it once:

+ const activeTechnologies = computed(() => {
+   const active = visibleExperiences.value[activeTab.value];
+   return active ? parseTechnologies(active.technologies) : [];
+ });

Then use activeTechnologies in the template instead of repeated parseTechnologies(...) calls.


136-149: Complex inline line number calculations are fragile and duplicated.

Line numbers are computed inline with expressions like (via ? X : Y) + highlights.length + techIndex. This pattern is repeated throughout the template, making it error-prone when adding/removing fields.

Consider a computed property that pre-calculates line offsets:

const lineOffsets = computed(() => {
  const exp = visibleExperiences.value[activeTab.value];
  if (!exp) return { export: 6, company: 7, /* ... */ };
  const base = 6 + exp.highlights.length;
  const viaOffset = exp.via ? 1 : 0;
  return {
    export: base,
    company: base + 1,
    position: base + 2,
    via: exp.via ? base + 3 : null,
    periodStart: base + 3 + viaOffset,
    // ... etc
  };
});

65-72: Breadcrumb handles undefined safely but may display ".ts" alone.

The optional chaining visibleExperiences[activeTab]?.slug prevents crashes, but if activeTab is out of bounds, the breadcrumb would render as ".ts". Consider wrapping the breadcrumb in a v-if consistent with the editor content guard at line 75.


388-389: Unnecessary interpolation for static values.

Ln {{ 1 }}, Col {{ 1 }} uses Vue interpolation for constant values. Simplify to plain text:

- <span class="status-item"
-   >Ln {{ 1 }}, Col {{ 1 }}</span
- >
+ <span class="status-item">Ln 1, Col 1</span>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9570d4e and 21f0c5c.

📒 Files selected for processing (1)
  • src/pages/ExperiencePage.vue (8 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.vue

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.vue: Indent content inside <script> and <style> tags in Vue files (configured via vueIndentScriptAndStyle: true in .prettierrc)
Use Vue 3 Composition API with <script setup> syntax for Vue components
D3 integration should use imperative DOM manipulation within Vue lifecycle hooks, kept separate from Vue reactivity

Files:

  • src/pages/ExperiencePage.vue
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use constants: IDEAL_BLIP_WIDTH = 22px, NEW_GROUP_BLIP_WIDTH = 88px, EXISTING_GROUP_BLIP_WIDTH = 124px

Files:

  • src/pages/ExperiencePage.vue
🧠 Learnings (1)
📚 Learning: 2025-12-14T01:59:00.938Z
Learnt from: CR
Repo: caiokf/homepage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-14T01:59:00.938Z
Learning: Applies to **/*.{ts,tsx,vue} : Use constants: `IDEAL_BLIP_WIDTH = 22px`, `NEW_GROUP_BLIP_WIDTH = 88px`, `EXISTING_GROUP_BLIP_WIDTH = 124px`

Applied to files:

  • src/pages/ExperiencePage.vue
🔇 Additional comments (3)
src/pages/ExperiencePage.vue (3)

18-27: File tree and tabs are properly synchronized.

Both the file explorer buttons and editor tabs correctly bind to activeTab for selection state and click handlers. This keeps the two UI elements in sync.

Also applies to: 50-61


400-403: Vue 3 Composition API usage is correct.

The component properly uses <script setup> with ref and computed for reactive state management, following Vue 3 best practices and the coding guidelines.


500-931: Styles are well-organized with proper scoping.

The scoped CSS uses consistent design tokens, handles responsive breakpoints appropriately, and provides clear syntax highlighting classes for the code-editor aesthetic.

Comment on lines +442 to +447
function closeTab(index: number) {
if (visibleExperiences.value.length <= 1) return;
if (activeTab.value >= index && activeTab.value > 0) {
activeTab.value--;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

closeTab adjusts selection but doesn't actually close the tab.

The function decrements activeTab when appropriate but never removes the tab from visibleExperiences. The closed tab remains visible in the UI. If tab closing is intended, you need to track closed tabs separately (since visibleExperiences is derived from config). If closing isn't meant to be functional, consider removing the close button to avoid user confusion.

+ const closedTabs = ref<Set<number>>(new Set());
+
  function closeTab(index: number) {
    if (visibleExperiences.value.length <= 1) return;
+   closedTabs.value.add(index);
    if (activeTab.value >= index && activeTab.value > 0) {
      activeTab.value--;
    }
  }

Then filter visibleExperiences or the rendered tabs based on closedTabs.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/pages/ExperiencePage.vue around lines 442-447, closeTab currently only
adjusts activeTab but never removes the closed tab from the UI; either remove
the close button from the template if closing is not intended, or implement real
closing by tracking closed tabs (e.g., a reactive Set or array of closed
experience ids): update closeTab to add the target experience id to closedTabs,
adjust activeTab to a valid index if needed, and change the computed/templated
visibleExperiences rendering to filter out any experiences whose id is in
closedTabs so the tab actually disappears from the UI.

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