Skip to content

Desktop css - #30

Merged
lxm7 merged 7 commits into
mainfrom
desktop-css
Jan 23, 2026
Merged

lxm7 merged 7 commits into
mainfrom
desktop-css

Conversation

@lxm7

@lxm7 lxm7 commented Jan 23, 2026

Copy link
Copy Markdown
Owner

No description provided.

@socket-security

socket-security Bot commented Jan 23, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​radix-ui/​react-accordion@​1.2.12991007193100
Added@​radix-ui/​react-slider@​1.3.6991007293100

View full report

@claude

claude Bot commented Jan 23, 2026

Copy link
Copy Markdown

PR Review: Desktop CSS Enhancements

Overview

This PR represents a significant refactoring of the ArticleAnalyser component, introducing a modular component architecture, centralized state management with Zustand, and enhanced filtering capabilities. The changes show good architectural improvements but have several areas that need attention.


✅ Strengths

1. Excellent Component Decomposition

The refactor from a monolithic 1467-line component to focused, single-responsibility modules is outstanding:

  • ArticleTreeMap.tsx - D3 treemap visualization
  • DesktopGridView.tsx - Grid layout for desktop
  • CardMobileView.tsx / WBAMobileView.tsx - Mobile views
  • FilterSidebar.tsx - Unified filtering UI
  • utils.ts / hooks.ts - Shared logic

This improves maintainability, testability, and developer experience significantly.

2. Smart State Management

Using Zustand for centralized state is the right choice:

  • useFilterStore - Centralized filtering logic with the useFilteredPosts selector hook
  • useViewStore - Persisted view preferences to localStorage
  • useZoomStore - Zoom level management

The useFilteredPosts selector with React.useMemo is well-optimized.

3. Good TypeScript Practices

  • Clear interfaces (PostWithMetrics, HierarchyNode, etc.)
  • Type safety with union types (ViewType, SizeMetric, TimeFilter)
  • Deprecated type marking (MobileViewType)

4. Accessibility Improvements

  • Proper semantic HTML with <header>, <nav>, <label>
  • ARIA labels on toggle buttons (aria-label="Close sidebar")
  • Keyboard-navigable checkboxes and radio buttons

⚠️ Issues & Concerns

1. Critical: Missing Input Sanitization (Security)

Location: src/stores/useFilterStore.ts:183-189

The search query is not sanitized before being used in filtering:

if (searchQuery.trim()) {
  const query = searchQuery.toLowerCase();
  result = result.filter(
    (post) =>
      post.title.toLowerCase().includes(query) ||
      post.shortDescription?.toLowerCase().includes(query)
  );
}

Risk: While this is client-side filtering, if the search query is ever used in server-side operations, logging, or analytics (like the window.gtag calls in hooks.ts:31), it could lead to XSS or injection attacks.

Recommendation: Add input sanitization utility:

const sanitizeSearchQuery = (query: string): string => {
  return query.replace(/[<>\"']/g, '').trim();
};

2. Performance: Potential Re-render Issues

Location: src/stores/useFilterStore.ts:141-212

The useFilteredPosts hook runs complex filtering logic (including Gaussian weight calculations) on every filter change. While memoized, this could cause performance issues with large datasets.

Issues:

  • Time filter calculates dates on every render
  • Content balance applies expensive Gaussian calculations when not needed (line 194-208)
  • No pagination or virtualization

Recommendations:

  • Consider moving date calculations outside the filter function
  • Add early returns for expensive operations
  • Implement virtualization for large post lists (e.g., react-window or @tanstack/react-virtual)
  • Add pagination to limit initial render

3. Hard-coded Category Scores (Maintainability)

Location: src/stores/useFilterStore.ts:59-99

The CATEGORY_SCORES object has 40+ hard-coded category-to-score mappings. This creates several issues:

Problems:

  • Categories not in the list default to 50 (line 112)
  • No validation that categories match the actual data
  • Difficult to maintain as categories change
  • Magic numbers without explanation

Recommendations:

  • Move to a configuration file or database
  • Add validation/warning for unmapped categories
  • Document the scoring methodology
  • Consider auto-generating scores based on category metadata

4. Type Safety: Loose Image Handling

Location: src/components/ArticleAnalyser/utils.ts:32-40

export const getImageUrl = (post: Post): string => {
  if (post.heroImage && typeof post.heroImage === 'object') {
    const media = post.heroImage as MediaType;
    if (media.url) {
      return `${getClientSideURL()}${media.url}`;
    }
  }
  return '/images/future1.webp';
}

Issues:

  • Type assertion as MediaType bypasses type checking
  • No validation that the URL is safe
  • Silent fallback could mask data issues

Recommendations:

export const getImageUrl = (post: Post): string => {
  if (post.heroImage && typeof post.heroImage === 'object' && 'url' in post.heroImage) {
    const media = post.heroImage as MediaType;
    if (media.url && typeof media.url === 'string') {
      // Validate URL starts with expected path
      const url = media.url.startsWith('/') ? media.url : `/${media.url}`;
      return `${getClientSideURL()}${url}`;
    }
  }
  return '/images/future1.webp';
}

5. Console Logging in Production

Location: src/components/ArticleAnalyser/DesktopGridView.tsx:46

<Hero onNewIdea={() => console.log('New idea essay clicked')} />

Issue: Console logs should not be in production code.

Fix:

<Hero onNewIdea={() => {
  // TODO: Implement new idea essay handler
}} />

6. Commented-Out Code

Location: src/components/Header/Header.tsx:32-69

Large block of commented navigation code should be removed or moved to a feature flag if planned for future use.


7. Missing Error Boundaries

The new component tree has no error boundaries. If any child component throws (e.g., D3 rendering errors in ArticleTreeMap), the entire app could crash.

Recommendation:
Add error boundaries around major component sections:

<ErrorBoundary fallback={<ErrorFallback />}>
  <ArticleTreeMap posts={posts} />
</ErrorBoundary>

8. Analytics Type Safety

Location: src/components/ArticleAnalyser/hooks.ts:31-36

window.gtag?.('event', 'article_click', {
  event_category: post.category_titles?.[0] || 'Uncategorized',
  event_label: post.title,
  event_link: `/posts/${post.slug}`,
  transport_type: 'beacon',
});

Issues:

  • window.gtag has no TypeScript definition
  • Event structure not validated
  • Potential for sending unsanitized post titles to analytics

Fix:

// Add to global.d.ts
declare global {
  interface Window {
    gtag?: (command: string, action: string, params: Record<string, any>) => void;
  }
}

9. Magic Numbers

Locations:

  • src/components/ArticleAnalyser/ArticleTreeMap.tsx:18 - TARGET_NODE_COUNT = 40
  • src/stores/useFilterStore.ts:127 - tolerance: number = 30
  • src/stores/useFilterStore.ts:206 - threshold = 0.1

These should be exported constants with documentation.


10. Potential Hydration Mismatch

Location: src/components/ArticleAnalyser/utils.ts:79-88

The enrichPostsWithMetrics function uses seededRandom to generate deterministic metrics, but the comment says "consistent across SSR and client". However, if the post list order differs between server and client, the metrics will mismatch.

Recommendation:
Ensure post ordering is consistent or use post IDs for seeding (which you do, so this should be fine - just verify in testing).


🧪 Test Coverage

Critical Gap: No tests found for the new components or stores.

This refactor touches core functionality and should have:

  • Unit tests for useFilterStore filtering logic
  • Unit tests for useFilteredPosts selector
  • Tests for the Gaussian weight calculation
  • Component tests for FilterSidebar, DesktopGridView, etc.
  • Integration tests for view switching and filtering

Recommendation: Add tests before merging, especially for the complex filtering logic.


🎨 Code Style

Minor Issues:

  1. Inconsistent TODO comments:

    • DesktopGridView.tsx:89 has a TODO for image sizes
    • Header.tsx has commented code instead of TODO
  2. Image priority prop:

    • DesktopGridView.tsx:88 uses priority on all images in a grid, which defeats the purpose of lazy loading

📋 Recommendations Summary

Must Fix (Before Merge):

  1. ✅ Add input sanitization for search queries
  2. ✅ Remove console.log in production code
  3. ✅ Fix window.gtag TypeScript definitions
  4. ✅ Remove commented code or add feature flag
  5. ✅ Add basic tests for filtering logic

Should Fix (Soon):

  1. ⚠️ Add error boundaries
  2. ⚠️ Implement virtualization for performance
  3. ⚠️ Move category scores to configuration
  4. ⚠️ Improve type safety in getImageUrl
  5. ⚠️ Extract magic numbers to constants

Nice to Have:

  1. 📝 Add JSDoc comments for complex functions (Gaussian calculations)
  2. 📝 Document the content balance scoring methodology
  3. 🎨 Remove priority from non-critical images
  4. 🎨 Consistent TODO format

🎯 Overall Assessment

Score: 7/10

This is a solid refactoring with excellent architectural improvements. The modular structure, state management, and TypeScript usage are all well done. However, the lack of tests, security considerations, and potential performance issues with large datasets prevent this from being production-ready without the recommended fixes.

Recommendation: Request changes for the "Must Fix" items, then approve once addressed.

Great work on the refactor! 🚀

@lxm7
lxm7 merged commit e419846 into main Jan 23, 2026
4 checks passed
@claude

claude Bot commented Jan 23, 2026

Copy link
Copy Markdown

Pull Request Review: Desktop CSS

Overview

This PR represents a substantial refactor of the ArticleAnalyser component, introducing a desktop-optimized view with improved filtering, state management, and UI components. The changes include ~2,556 additions and ~1,708 deletions across 28 files.

Strengths

Architecture & Code Quality

  1. Excellent component decomposition - The massive ArticleAnalyser/index.tsx (previously 1,467 lines) has been properly broken down into focused components
  2. Centralized state management - Great use of Zustand stores with memoization
  3. Performance optimizations - Proper use of React.useMemo, throttled zoom events, canvas optimizations
  4. Accessibility improvements - SR-only content for SEO, proper ARIA labels

Security

  1. Input sanitization - Search query sanitization to prevent XSS (useFilterStore.ts:11-13)

Issues & Concerns

Critical

  1. Disabled ESLint rules without justification (ArticleTreeMap.tsx lines: 248, 266, 290, 533, 568, 647, 653)
  2. Global gtag usage without type safety (ArticleTreeMap.tsx:631) - Add check for window.gtag existence
  3. XSS risk in tooltip (ArticleTreeMap.tsx:602-616) - Direct innerHTML assignment with user content

Performance

  1. Canvas redraw on every hover - Full canvas clear/redraw for single node highlight (line 652)
  2. Semantic zoom recalculation - limitArticlesToTargetDensity could be expensive with large datasets
  3. Multiple ref updates in effects - Could cause stale closures

Code Quality

  1. Magic numbers throughout - TARGET_NODE_COUNT=40, tolerance=30, etc. Extract to named constants
  2. Commented-out code (Header.tsx:33-69) - Remove or add feature flag
  3. Type assertions without validation (ArticleTreeMap.tsx:702-703)

Potential Bugs

  1. Race condition in navigation - isNavigating never reset if navigation fails (ArticleTreeMap.tsx:629-637)
  2. Zoom state sync issues - Manual sync between D3 and Zustand could conflict
  3. Dimension initialization race - Use ResizeObserver instead of resize event

Testing

  1. No tests for new components - 0 test files added despite complex filtering logic

Recommendations Summary

High Priority

  • Fix ESLint disable comments or justify them
  • Add type safety for window.gtag
  • Replace innerHTML in tooltip with safe DOM manipulation
  • Add error boundaries around complex components
  • Fix isNavigating state management

Medium Priority

  • Add unit tests for filtering logic and utils
  • Optimize canvas rendering (dirty rectangles, hover layer)
  • Extract magic numbers to constants
  • Memoize expensive zoom calculations

Low Priority

  • Remove commented code in Header.tsx
  • Create CSS custom property for header height
  • Add JSDoc comments for complex functions

Conclusion

This is a solid refactor with significant improvements in code organization, state management, and UX. Main areas for improvement: testing coverage, ESLint suppressions, canvas performance, and innerHTML security issue.

Recommendation: Approve with requested changes for high-priority items.

Overall Score: 7.5/10

  • Code Quality: 8/10
  • Performance: 7/10
  • Security: 8/10
  • Testing: 3/10
  • Architecture: 9/10

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