Skip to content

[CORE-1701] Phase 3.1: NavBar and Footer Migration to Plain CSS#2917

Merged
RoyEJohnson merged 15 commits intomainfrom
CORE-1701-navbar-footer-migration
Apr 23, 2026
Merged

[CORE-1701] Phase 3.1: NavBar and Footer Migration to Plain CSS#2917
RoyEJohnson merged 15 commits intomainfrom
CORE-1701-navbar-footer-migration

Conversation

@OpenStaxClaude
Copy link
Copy Markdown
Contributor

@OpenStaxClaude OpenStaxClaude commented Apr 10, 2026

Summary

This PR migrates the NavBar and Footer components from styled-components to plain CSS following the hybrid approach documented in PLAIN_CSS_MIGRATION_GUIDE.md.

Related Jira Ticket: CORE-1701

Migration Approach

Using plain CSS (not CSS Modules) with the hybrid pattern:

  • Theme values remain in JavaScript (theme.ts)
  • Components bind CSS variables for styling
  • Static CSS files for better performance
  • No runtime CSS-in-JS overhead

✅ Completed Work

NavBar Migration (Commit: cfa4203)

  • Created NavBar.css with plain CSS classes (231 lines)
  • Converted React components to use plain CSS classes
  • Bound theme colors as CSS variables
  • Migrated Redux connect() to hooks (useSelector, useDispatch)
  • Extracted constants to separate constants.ts file
  • Converted fadeIn animation to CSS @Keyframes
  • Maintained z-index stacking (navbar: 70, mobile overlay: 71)
  • Proper media query conversion (75em breakpoint)

Footer Migration (Commit: 3995ea4)

  • Created Footer.css with plain CSS classes (475 lines)
  • Converted React components to use plain CSS classes
  • Wrapped social media icons with styled() for compatibility
  • Bound theme colors as CSS variables
  • Preserved complex CSS grid layouts (TopBoxed, BottomBoxed, PortalBottomBoxed)
  • Maintained responsive behavior with multiple breakpoints (37.5em, 37.6em, 60.1em)
  • Preserved vertical nav toolbar styling with clamp() calculation
  • Migrated social icons to inline SVG (FB, Twitter, Instagram, LinkedIn)

Components Migrated

NavBar (src/app/components/NavBar/)

  • ✅ TopBar, HeaderImage, BarWrapper
  • ✅ Link with hover animation
  • ✅ Mobile menu: MobileMenuOverlay, MobileMenuModal, DropdownOverlay
  • ✅ DropdownContainer with fadeIn animation
  • ✅ TimesIcon close button

Footer (src/app/components/Footer/)

  • ✅ FooterWrapper with responsive padding
  • ✅ FooterTop, TopBoxed with CSS grid
  • ✅ Column components (Column1, Column2, Column3)
  • ✅ FooterBottom, BottomBoxed, PortalBottomBoxed
  • ✅ Social media icons (FBIcon, TwitterIcon, IGIcon, LinkedInIcon)
  • ✅ FooterLink, FooterButton, ManageCookiesLink

Key Implementation Details

NavBar

  • fadeIn keyframes animation converted to CSS
  • z-index stacking: navbar (70), mobile overlay (71)
  • Responsive breakpoint at 75em (mobile)
  • CSS variables: nav-text-color, nav-text-hover, nav-border-color, navbar-bg, mobile-overlay-bg
  • Redux hooks migration: useSelector for all state access

Footer

  • Complex CSS grid layouts preserved with proper responsive behavior
  • Multiple responsive breakpoints (37.5em, 37.6em, 60.1em)
  • Vertical nav toolbar styling with clamp() calculation for responsive padding
  • CSS variables: footer-text-color, footer-bg-top, footer-bg-bottom, social-icon-bg
  • Social icons migrated to inline SVG with styled() wrapper for component selector compatibility

Migration Compliance

Following all patterns from:

  • PLAIN_CSS_MIGRATION_GUIDE.md: CSS variables bound before style spread, classNames for composition
  • PLAIN_CSS_MIGRATION_LEARNINGS.md: Icons wrapped with styled(), media queries at top-level, Redux hooks migration
  • Phase Independence: No dependencies on Phase 2 PRs

Testing

Tests should be run in CI environment. The migration preserves all existing functionality:

  • NavBar: desktop/mobile layouts, user menu, login link, unsaved highlights confirmation
  • Footer: normal/portal variants, responsive grids, social links, manage cookies, keyboard shortcuts

See the Testing Guide in CORE-1701 comments for comprehensive manual testing checklist.

Files Changed

Created

  • src/app/components/NavBar/NavBar.css - NavBar plain CSS (231 lines)
  • src/app/components/NavBar/constants.ts - Extracted constants
  • src/app/components/Footer/Footer.css - Footer plain CSS (475 lines)

Modified

  • src/app/components/NavBar/index.tsx - Migrated to plain CSS + hooks
  • src/app/components/Footer/index.tsx - Migrated to plain CSS + inline SVG icons

Removed

  • src/app/components/NavBar/styled.tsx - Replaced with plain CSS
  • src/app/components/Footer/styled.tsx - Replaced with plain CSS

Notes

  • All CSS variables are set before spreading ...style prop
  • Media queries converted with proper rem-to-em formula where needed
  • classNames package used for className composition
  • No functionality changes, only styling mechanism changed
  • Ready for code review and manual testing per Testing Guide

🤖 Generated with Claude Code

Co-Authored-By: Claude Sonnet 4.5 noreply@anthropic.com

@TomWoodward TomWoodward temporarily deployed to rex-web-core-1701-navba-6ptzgd April 10, 2026 12:41 Inactive
@RoyEJohnson RoyEJohnson force-pushed the CORE-1701-navbar-footer-migration branch from 967ad4c to b189207 Compare April 10, 2026 15:11
@TomWoodward TomWoodward temporarily deployed to rex-web-core-1701-navba-6ptzgd April 10, 2026 15:11 Inactive
@RoyEJohnson RoyEJohnson requested a review from Copilot April 10, 2026 15:11
@TomWoodward TomWoodward had a problem deploying to rex-web-core-1701-navba-6ptzgd April 10, 2026 15:36 Failure
@TomWoodward TomWoodward had a problem deploying to rex-web-core-1701-navba-6ptzgd April 10, 2026 15:41 Failure
RoyEJohnson

This comment was marked as resolved.

@OpenStaxClaude

This comment was marked as resolved.

@TomWoodward TomWoodward had a problem deploying to rex-web-core-1701-navba-6ptzgd April 10, 2026 16:01 Failure
@TomWoodward TomWoodward had a problem deploying to rex-web-core-1701-navba-6ptzgd April 10, 2026 16:10 Failure
@RoyEJohnson RoyEJohnson force-pushed the CORE-1701-navbar-footer-migration branch from 1a8cc0c to f920030 Compare April 10, 2026 16:18
@TomWoodward TomWoodward had a problem deploying to rex-web-core-1701-navba-6ptzgd April 10, 2026 16:18 Failure
@RoyEJohnson RoyEJohnson force-pushed the CORE-1701-navbar-footer-migration branch from f920030 to 25173ec Compare April 10, 2026 16:25
@TomWoodward TomWoodward temporarily deployed to rex-web-core-1701-navba-6ptzgd April 10, 2026 16:25 Inactive
@RoyEJohnson RoyEJohnson force-pushed the CORE-1701-navbar-footer-migration branch from 25173ec to d9b517b Compare April 10, 2026 18:20
@TomWoodward TomWoodward temporarily deployed to rex-web-core-1701-navba-6ptzgd April 10, 2026 18:21 Inactive
@RoyEJohnson RoyEJohnson force-pushed the CORE-1701-navbar-footer-migration branch from d9b517b to 24196db Compare April 10, 2026 18:31
@TomWoodward TomWoodward had a problem deploying to rex-web-core-1701-navba-6ptzgd April 10, 2026 18:31 Failure
RoyEJohnson

This comment was marked as resolved.

@OpenStaxClaude

This comment was marked as resolved.

@TomWoodward TomWoodward had a problem deploying to rex-web-core-1701-navba-6ptzgd April 10, 2026 18:35 Failure
@RoyEJohnson RoyEJohnson force-pushed the CORE-1701-navbar-footer-migration branch from 343b761 to aacc5c6 Compare April 10, 2026 18:49
@TomWoodward TomWoodward temporarily deployed to rex-web-core-1701-navba-6ptzgd April 10, 2026 18:49 Inactive
@TomWoodward TomWoodward temporarily deployed to rex-web-core-1701-navba-6ptzgd April 10, 2026 19:00 Inactive
@RoyEJohnson RoyEJohnson requested review from Copilot and removed request for Copilot April 10, 2026 19:16
RoyEJohnson

This comment was marked as resolved.

This comment was marked as resolved.

RoyEJohnson

This comment was marked as resolved.

@OpenStaxClaude

This comment was marked as resolved.

@OpenStaxClaude
Copy link
Copy Markdown
Contributor Author

Summary: All Review Comments Addressed ✅

I've successfully addressed all code review feedback from Roy and Copilot.

Latest Change (Review #21)

Issue: --footer-text-color was being used as a CSS variable even though it never changes.

Fix: Removed the CSS variable and used plain CSS value #d5d5d5 directly.

  • Commit: e868328
  • Files changed: Footer/index.tsx and Footer.css
  • Follows the same CSS variable usage principles established earlier in this PR

Complete List of Addressed Review Comments

Review Issue Status Commit
#1 Stylelint no-descending-specificity error ✅ Fixed 4d73192
#2 Test failure & coverage gap ✅ Fixed 343b761
#3 CSS variable usage clarification ✅ Fixed 2500e7d, bb3abd5
#13 window undefined test coverage ✅ Fixed 095e2f7
#21 Redundant --footer-text-color variable ✅ Fixed e868328
Copilot (multiple) Various code quality issues ✅ Fixed db0ae3e, c2760c4, 305d5e7, 191ff01, 6d62bdc

Migration Compliance

All changes follow the established patterns from:

  • ✅ PLAIN_CSS_MIGRATION_GUIDE.md
  • ✅ PLAIN_CSS_MIGRATION_LEARNINGS.md
  • ✅ Previous phase learnings

CSS Variable Usage Now Consistent

The PR now correctly applies CSS variables only when:

  1. ✅ Value comes from theme.ts
  2. ✅ Value requires JavaScript computation
  3. ✅ Value might change at runtime

And uses plain CSS when:

  1. ✅ Value is static and never changes
  2. ✅ Value was hardcoded in original styled-components
  3. ✅ Value has no relationship to theme

Ready for final review and merge! 🚀

RoyEJohnson

This comment was marked as off-topic.

RoyEJohnson

This comment was marked as off-topic.

RoyEJohnson

This comment was marked as off-topic.

RoyEJohnson

This comment was marked as resolved.

Comment thread src/app/components/Footer/index.tsx Outdated
OpenStaxClaude and others added 13 commits April 20, 2026 13:05
- Create NavBar.css with all styled-components converted to plain CSS
- Includes fadeIn animation, responsive breakpoints, z-index management
- Uses CSS variables for theme values (colors, spacing, z-indices)
- Follows PLAIN_CSS_MIGRATION_GUIDE patterns

Related to CORE-1701

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Complete the NavBar migration by updating index.tsx to use plain CSS
classes and CSS variables instead of styled-components.

Changes:
- Create constants.ts to export navDesktopHeight, navMobileHeight, and maxNavWidth
- Replace all Styled.* components with plain HTML elements + className
- Import and use react-aria-components ModalOverlay and Modal directly
- Add CSS variable bindings from theme for colors, z-indices, and dimensions
- Migrate Redux connect() HOCs to useSelector hooks for:
  - ConnectedNavigationBar (default export)
  - ConnectedLoginButton
- Import theme and Color for CSS variable values
- Import Times component directly instead of through styled wrapper
- Import NavBar.css for styles

The component now follows the plain CSS migration pattern:
- CSS classes defined in NavBar.css
- Theme values bound as CSS variables via style prop
- Redux hooks instead of connect() HOC
- All functionality preserved with improved performance

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changes:
- Created Footer.css with all styled-components converted to plain CSS classes
- Updated Footer/index.tsx to use plain CSS with className instead of Styled.* components
- Migrated social media icons (Facebook, Twitter, Instagram, LinkedIn) to inline SVG
- Wrapped icon components with styled() for component selector compatibility
- Bound CSS variables from theme for dynamic values (colors, backgrounds)
- Preserved complex CSS grid layouts for responsive behavior
- Maintained vertical nav toolbar styling with clamp() calculation
- Used classNames package for className composition
- Preserved all functionality including:
  - Normal footer with mission, columns, social links
  - Portal footer variant
  - Contact dialog integration
  - Manage cookies links
  - Responsive breakpoints (37.5em, 37.6em, 60.1em)

Migration follows the patterns established in PLAIN_CSS_MIGRATION_GUIDE.md
and PLAIN_CSS_MIGRATION_LEARNINGS.md. All CSS variables are set before
spreading style props to allow overrides.

Note: Tests will be updated in a separate commit per task requirements.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Reordered CSS selectors to ensure proper specificity ordering:
- Moved all base link selectors (a) before pseudo-class selectors (:hover, :active, :focus)
- Grouped .footer-copyrights and .footer-mission link selectors properly
- This fixes the stylelint error where .footer-copyrights a appeared after .footer-mission a:hover/active/focus

The rule requires less specific selectors to appear before more specific ones to avoid unexpected CSS cascade behavior.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Restore yarn.lock

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Updated Footer.spec.tsx to work with plain CSS migration:
- Changed test to find button by className='footer-button' instead of styled component
- The test uses findAll() to locate button with matching className and message ID
- This fixes the "Cannot read property 'props' of undefined" error
- The existing test already covers the onClick in PortalColumn2

The test "calls captureOpeningElement when 'Contact Us' is clicked in portal footer"
exercises the Contact Us button in PortalColumn2, which calls:
- captureOpeningElement('contactdialog')
- open() from useContactDialog hook

This provides the coverage that was previously missing when the test was failing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Following the hybrid CSS pattern from PLAIN_CSS_MIGRATION_GUIDE.md, removed CSS variables that were:
- Set to hardcoded static values in JSX
- Had identical fallback values in CSS
- Not derived from theme.ts
- Never changed at runtime

Removed redundant variables:
- --navbar-logo-height-desktop / --navbar-logo-height-mobile
- --navbar-overlay-logo-top
- --navbar-height-desktop / --navbar-height-mobile
- --navbar-max-width

Kept theme-derived variables (correct usage):
- --navbar-z-index (from theme.zIndex.navbar)
- --navbar-bg (from theme.color.neutral.base)
- --navbar-padding-desktop/mobile (from theme.padding.page)
- --nav-text-color (from theme.color.primary.gray.base)
- --mobile-overlay-bg (computed with Color library)
- --mobile-overlay-z-index (computed from theme)

This makes the code cleaner and follows the migration guide's principle:
"CSS variables should be used when values need to be looked up from theme.ts at runtime or require JavaScript computation"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Following the same pattern as NavBar, removed CSS variables that were:
- Set to hardcoded static color values in JSX
- Had identical fallback values in CSS
- Not derived from theme.ts
- Never changed at runtime (hardcoded in original styled-components)

Removed redundant variables:
- --footer-top-bg (was '#424242', now plain CSS)
- --footer-bottom-bg (was '#3b3b3b', now plain CSS)

These colors were hardcoded in the original styled-components (not from theme),
so they should be plain CSS values, not CSS variables.

Kept theme-derived variables (correct usage):
- --footer-text-color (from theme.color.text.label)
- --footer-social-icon-bg (from theme.color.primary.gray.light)
- --footer-social-icon-color (computed hex value)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
1. Footer.spec.tsx: Use data-testid for test selector robustness
   - Added data-testid="portal-footer-contact-button" to Contact Us button
   - Updated test to use findByProps with data-testid instead of fragile .find() logic
   - Prevents test failures when FormattedMessage structure changes

2. NavBar: Bind layout constants as CSS variables
   - Import maxNavWidth, navDesktopHeight, navMobileHeight from constants.ts
   - Bind as CSS variables in navbar-bar-wrapper to prevent drift
   - Update NavBar.css to reference CSS variables with fallbacks
   - Ensures single source of truth for layout dimensions used across codebase

These changes improve test reliability and maintainability by:
- Making tests resilient to DOM structure changes
- Preventing CSS/JS constant drift for shared layout values

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Update index.tsx

Apply Copilot suggestions from code review

More Copilot notes

Remove window undefined test and revert to optional chaining

The test for window being undefined was causing failures because:
1. The original code did NOT handle window being undefined
2. The component legitimately requires window (for addEventListener)
3. The test was breaking other tests by deleting global.window

Changes:
- Removed "handles portal footer when window is not defined" test
- Reverted typeof window check to original window?.location.href pattern
- This matches the behavior of the code before migration

The Footer component is browser-only and requires window to function.
SSR scenarios are not supported by this component's design.

Fixes test failures reported in Review 15.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Add test coverage for PortalColumn2 when window is undefined

Added test case "handles portal footer when window is not defined" to verify
that the Footer component renders correctly in SSR/test environments where
window is not defined.

This test covers the typeof window !== 'undefined' check on line 491 in
Footer/index.tsx, ensuring that the component gracefully handles the absence
of the window object without crashing.

Addresses Review 13 from RoyEJohnson.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Update Footer.spec.tsx

Address Copilot review comments - final round

This commit addresses all remaining review comments from Copilot and reviewers:

1. Footer.css: Fixed media query breakpoint from 60.1em to 75.0625em
   - The original styled-components used theme.breakpoints.desktopBreak (75.0625em)
   - Using 60.1em would apply the toolbar offset earlier than intended
   - Updated comment to document both breakpoint sources (theme.ts and constants.ts)

2. Footer/index.tsx: Fixed window reference in PortalColumn2
   - Added typeof guard to prevent ReferenceError in SSR/test environments
   - Changed from window?.location.href to typeof window !== 'undefined' ? window.location.href : undefined
   - Prevents crashes when window is completely undeclared (not just undefined)

3. NavBar/styled.tsx: Fixed constants duplication
   - Made styled.tsx re-export constants from constants.ts
   - Maintains backward compatibility for existing imports
   - Creates single source of truth in constants.ts

4. NavBar/index.tsx: Removed encodeURIComponent from login link
   - Reverted to original behavior (raw currentPath without encoding)
   - Prevents breaking snapshots (/accounts/login?r=/ vs ?r=%2F)
   - Maintains consistency with other auth links in codebase

5. Footer/index.tsx: Added comprehensive comment for icon wrappers
   - Explains why icons are wrapped with styled() for component selector compatibility
   - References PLAIN_CSS_MIGRATION_LEARNINGS.md for pattern documentation

All changes verified with syntax checks. Tests cannot run due to missing
@openstax/highlighter dependency (environment issue, not related to changes).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Revert lock files

Address Copilot and reviewer feedback

Fixed the following issues from code review:

1. **Footer.css**: Removed `flex-flow` property from grid layouts
   - Removed from .footer-top-boxed, .footer-bottom-boxed, .footer-portal-bottom-boxed
   - flex-flow has no effect on grid layouts and caused confusion

2. **Footer.spec.tsx**: Changed .findAll()[0] to .find()
   - More deterministic error handling if button is not found
   - Test will throw clear error instead of undefined access

3. **FooterLinkMessage**: Auto-add noreferrer for external links
   - When target="_blank", automatically includes "noopener noreferrer"
   - Prevents reverse-tabnabbing and referrer leakage security issues

4. **OpenKeyboardShortcutsLink**: Removed unnecessary preventDefault()
   - Button with type="button" has no default action to prevent
   - Makes handler intent clearer

5. **NavBar**: Consolidated redundant CSS variable assignments
   - Moved --nav-text-color, --link-hover, --focus-outline-color to parent container
   - Set once on .navbar-dropdown-overlay instead of multiple children
   - Reduces duplication and prevents drift during future edits

All changes improve code quality, security, and maintainability.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Address all code review comments from Copilot and reviewers

1. **Added unit tests for getSafeRelAttribute function**
   - Exported function for testability
   - Added comprehensive test coverage for all edge cases
   - Tests ensure proper rel token normalization and security

2. **Optimized Color computation in MobileDropdown**
   - Added useMemo to cache Color().alpha().string() result
   - Reduces render cost by avoiding repeated object allocation
   - Empty dependency array since theme.color.neutral.base is constant

3. **Replaced hardcoded hex colors with theme constants**
   - Added linkFocusOutline constant to Links.constants.ts
   - Imported linkHover and linkFocusOutline in NavBar
   - Replaced '#0064a0' with linkHover
   - Replaced '#007297' with linkFocusOutline
   - Maintains consistency with design system

4. **Fixed URL encoding security issue**
   - Added encodeURIComponent to currentPath in login URL
   - Prevents query parameter injection attacks
   - Properly handles special characters (?, #, &, etc.)

5. **Prevented layout shift in navbar links**
   - Added transparent border-bottom to default .navbar-link state
   - Adjusted padding to maintain same total height
   - On hover/focus, only border color changes (not layout)
   - Mobile version properly resets to transparent
   - Improves keyboard navigation experience

All changes improve code quality, security, performance, and accessibility.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Address all remaining code review comments

This commit addresses feedback from both Copilot and human reviewers:

1. Footer.css: Added doubled selector specificity to .footer-manage-cookies-flex-link
   - Matches the pattern used for .footer-manage-cookies-link
   - Ensures ui-components default styles don't override our styling
   - Applied to base selector and all pseudo-class variants

2. Footer/index.tsx: Fixed className merging in MissionDiv and CopyrightsDiv
   - Now properly destructures className prop
   - Uses classNames() to merge base class with any passed className
   - Prevents className override from htmlMessage callers

3. Footer/index.tsx: Improved rel attribute normalization
   - Created getSafeRelAttribute() helper function
   - Normalizes rel tokens using Set to prevent duplicates
   - Ensures both 'noopener' and 'noreferrer' are present for target="_blank"
   - Prevents duplicate tokens like "noopener noreferrer noreferrer"
   - Extracted as reusable helper per reviewer suggestion

4. NavBar/index.tsx: Optimized useSelector usage
   - Combined 5 separate useSelector calls into single selector
   - Added shallowEqual comparison to prevent unnecessary re-renders
   - Reduces subscription overhead and render churn
   - Improves performance by only re-rendering when values actually change

All changes improve code quality, security, and performance.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Remove redundant --footer-text-color CSS variable

The --footer-text-color variable was set to a hardcoded constant '#d5d5d5'
that never changes and is not derived from theme. Per the CSS migration
principles established in this PR, CSS variables should only be used for:
1. Values from theme.ts
2. Computed values
3. Runtime-variable values

Since textColor is a static hardcoded value, it belongs in plain CSS.

Changes:
- Removed textColor constant from Footer/index.tsx
- Replaced var(--footer-text-color, #d5d5d5) with #d5d5d5 in Footer.css
- Removed all style={{--footer-text-color: textColor}} bindings

This makes the code cleaner and follows the hybrid pattern correctly,
consistent with earlier cleanup commits (2500e7d, bb3abd5).

Addresses review comment from RoyEJohnson in Review #21.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Copilot <175728472+Copilot@users.noreply.github.com>
Co-Authored-By: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@RoyEJohnson RoyEJohnson left a comment

Choose a reason for hiding this comment

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

Look at Footer/index.tsx. It's a pretty big file and handles several disparate tasks. Can you break it up into a few smaller, more focused modules? The social directory/icons seem like a good candidate, and maybe the dialog(s)?

@OpenStaxClaude
Copy link
Copy Markdown
Contributor Author

Refactored Footer into Smaller, Focused Modules ✅

I've addressed Review #26 by breaking up the large Footer/index.tsx file into smaller, more focused modules.

Changes Made (Commit: cbe0ab1)

Created Two New Modules:

  1. Footer/SocialIcons.tsx (194 lines)

    • All social media icon components (Facebook, Twitter, Instagram, LinkedIn)
    • Social media URL constants
    • SocialDirectory component that renders the social links menu
    • Isolated all icon-related code as suggested in the inline review comment
  2. Footer/ContactDialog.tsx (68 lines)

    • ContactDialog component for the contact form modal
    • useContactDialog hook for dialog state management
    • All contact form-related logic encapsulated in one place

Refactored Footer/index.tsx:

  • Reduced from 561 lines to 315 lines (44% reduction)
  • Now imports from the new modules
  • Maintains backward compatibility by re-exporting ContactDialog and useContactDialog
  • Focuses solely on layout and footer structure

Benefits

Improved Organization: Each module has a single, focused responsibility
Better Maintainability: Easier to find and modify specific functionality
No Breaking Changes: All existing imports continue to work
Addresses Inline Comments: Social icons extracted as suggested by @bethshook

Module Responsibilities

Module Responsibility Lines
SocialIcons.tsx Social media icons and links 194
ContactDialog.tsx Contact form dialog and hook 68
index.tsx Footer layout and structure 315

The refactoring maintains all existing functionality while significantly improving code organization. Ready for re-review! 🚀

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/app/components/Footer/index.tsx
Comment thread src/app/components/Footer/SocialIcons.tsx
OpenStaxClaude and others added 2 commits April 20, 2026 13:46
Extracted social icons and contact dialog into separate modules as
requested in code review to improve maintainability and reduce the
size of the main Footer component file.

**Changes:**
- Created `Footer/SocialIcons.tsx` (194 lines): Social media icons,
  constants, and SocialDirectory component
- Created `Footer/ContactDialog.tsx` (68 lines): ContactDialog component
  and useContactDialog hook
- Refactored `Footer/index.tsx` from 561 to 315 lines (44% reduction)
- Maintained backward compatibility by re-exporting ContactDialog and
  useContactDialog from index.tsx
- All existing imports continue to work (no breaking changes)

**Benefits:**
- Improved code organization and separation of concerns
- Each module now has a single, focused responsibility
- Easier to navigate and understand the Footer component
- Facilitates future maintenance and testing

Addresses Review #26

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Cleanup

Don't export icons

Footer is browser-only

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants