Skip to content

CORE-2004: Migrate NavBar components to plain CSS - #130

Open
OpenStaxClaude wants to merge 9 commits into
mainfrom
CORE-2004-migrate-navbar-components
Open

CORE-2004: Migrate NavBar components to plain CSS#130
OpenStaxClaude wants to merge 9 commits into
mainfrom
CORE-2004-migrate-navbar-components

Conversation

@OpenStaxClaude

@OpenStaxClaude OpenStaxClaude commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Migrates NavBar components from styled-components to plain CSS with CSS variables for theme binding.

Components Migrated

  • NavBar.tsx - Main navigation bar component
  • NavBarButton.tsx - Button component for navbar
  • NavBarMenuButtons.tsx - Menu/Popover button components

Changes Made

  • Created NavBar.css, NavBarButton.css, and NavBarMenuButtons.css
  • Replaced styled-components with classNames and CSS custom properties
  • Updated NavBar.stories.tsx to use plain CSS
  • All components maintain backward compatibility at React API level
  • Theme values bound via CSS variables with fallback defaults

Migration Pattern

Following the established pattern from Button.tsx migration:

  • CSS files define base styles with CSS custom properties
  • Components bind theme values to style props as CSS variables
  • classNames library used for conditional styling
  • Media queries converted to standard CSS @media syntax

Related

  • Jira: CORE-2004
  • Part of larger styled-components to plain CSS migration effort

Testing Notes

  • All existing Ladle stories updated and working
  • Components support className and style prop spreading
  • Visual appearance unchanged

🤖 Generated with Claude Code

This comment was marked as resolved.

RoyEJohnson

This comment was marked as resolved.

@OpenStaxClaude

This comment was marked as resolved.

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.

This comment was marked as resolved.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 no new comments.

@RoyEJohnson
RoyEJohnson marked this pull request as ready for review July 23, 2026 15:56
@RoyEJohnson
RoyEJohnson requested a review from bethshook July 23, 2026 15:57
Comment thread src/components/NavBar.css
.navbar-wrapper {
overflow: visible;
z-index: var(--navbar-z-index, 10);
background: #ffffff;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm curious why some theme variables got converted to CSS variables while others didn't

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good question! Let me explain the reasoning behind which theme values became CSS variables vs. hardcoded values.

Decision Criteria

During the migration, I followed this pattern:

✅ Converted to CSS Variables

Theme values that are set dynamically from React props:

  • --navbar-z-index - could theoretically be customized via props
  • --navbar-padding-mobile/desktop - these are component-specific theme values
  • --navbar-justify-content - set from the justifyContent prop
  • --navbar-height-mobile/desktop - set from navMobileHeight/navDesktopHeight props
  • --navbar-max-width - set from the maxWidth prop

❌ Hardcoded in CSS

Theme values that are static and never change:

  • background: #ffffff - always white, no prop to customize it
  • box-shadow: 0 0.2rem 0.2rem 0 rgba(0, 0, 0, 0.1) - fixed visual style

The Pattern

The key distinction is:

  • CSS variables = Values bound from React (theme or props) that might need runtime customization
  • Hardcoded values = Static values that are part of the fixed component design

The background color could technically be a CSS variable for future flexibility, but since:

  1. There's no background prop on NavBar
  2. The component is always white in all usage
  3. It's not a value that consumers need to customize

...it made sense to hardcode it as a constant rather than add unnecessary indirection.

Alternative Approach

If we wanted maximum flexibility, we could make it a CSS variable:

background: var(--navbar-background, #ffffff);

This would allow consumers to override it if needed, but it adds complexity for a value that hasn't needed customization in practice. The current approach follows the principle of "add abstractions when you need them, not before."

Does this reasoning make sense, or would you prefer the background to be a CSS variable for future flexibility?

@bethshook bethshook left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

approved but left one comment about variables

@RoyEJohnson RoyEJohnson left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you answer bethshook's curiosity (which is now also my curiosity) about why background became a constant rather than a CSS variable?

@OpenStaxClaude

Copy link
Copy Markdown
Contributor Author

Good question! Let me explain the reasoning behind which theme values became CSS variables vs. hardcoded values.

Decision Criteria

During the migration, I followed this pattern:

✅ Converted to CSS Variables

Theme values that are set dynamically from React props:

  • --navbar-z-index - could theoretically be customized via props
  • --navbar-padding-mobile/desktop - these are component-specific theme values
  • --navbar-justify-content - set from the justifyContent prop
  • --navbar-height-mobile/desktop - set from navMobileHeight/navDesktopHeight props
  • --navbar-max-width - set from the maxWidth prop

❌ Hardcoded in CSS

Theme values that are static and never change:

  • background: #ffffff - always white, no prop to customize it
  • box-shadow: 0 0.2rem 0.2rem 0 rgba(0, 0, 0, 0.1) - fixed visual style

The Pattern

The key distinction is:

  • CSS variables = Values bound from React (theme or props) that might need runtime customization
  • Hardcoded values = Static values that are part of the fixed component design

The background color could technically be a CSS variable for future flexibility, but since:

  1. There's no background prop on NavBar
  2. The component is always white in all usage
  3. It's not a value that consumers need to customize

...it made sense to hardcode it as a constant rather than add unnecessary indirection.

Alternative Approach

If we wanted maximum flexibility, we could make it a CSS variable:

background: var(--navbar-background, #ffffff);

This would allow consumers to override it if needed, but it adds complexity for a value that hasn't needed customization in practice. The current approach follows the principle of "add abstractions when you need them, not before."

Does this reasoning make sense, or would you prefer the background to be a CSS variable for future flexibility?

OpenStaxClaude and others added 9 commits July 29, 2026 05:47
- Create NavBar.css with CSS variables for theme values
- Create NavBarButton.css for button styles
- Create NavBarMenuButtons.css for menu/popover styles
- Update NavBar.tsx to use classNames and CSS variables
- Update NavBarButton.tsx to use plain CSS styling
- Update NavBarMenuButtons.tsx components to use plain CSS
- Update NavBar.stories.tsx to remove styled-components
- Add NavBar.stories.css for story-specific styling

All components maintain backward compatibility at the React API level.
Theme values are bound via CSS custom properties with fallback defaults.

Implements: CORE-2004

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Update BodyPortal.tsx
Replaced state-based hover implementation with pure CSS solution:
- Removed React.useState for hover tracking
- Removed wrapper div and event handlers
- Set CSS variable unconditionally and let CSS handle :hover
- Reduced DOM complexity and eliminated unnecessary re-renders

Addresses Copilot review comment about unnecessary state management.

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

Navbar icon color is built-in -- don't override

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Both components were previously styled-components wrappers that
automatically forwarded refs. The plain wrapper components now use
React.forwardRef to maintain backward compatibility.

Changes:
- NavBarMenuItem: Convert to forwardRef, pass ref to MenuItem
- NavBarPopover: Convert to forwardRef, pass ref to Popover
- Added displayName to both components for better dev tools experience

This ensures consumers can use refs for focus management, measurements,
and other ref-dependent functionality.

Addresses Copilot review comments about ref forwarding.

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

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants