Skip to content

[EuiSideNav] Migrate from class to function component#9831

Merged
weronikaolejniczak merged 2 commits into
elastic:mainfrom
youdie006:refactor/side-nav-function-component
Jul 27, 2026
Merged

[EuiSideNav] Migrate from class to function component#9831
weronikaolejniczak merged 2 commits into
elastic:mainfrom
youdie006:refactor/side-nav-function-component

Conversation

@youdie006

Copy link
Copy Markdown
Contributor

Summary

Migrates EuiSideNav from a withEuiTheme-wrapped class to a generic function component, per #9475 and the class-to-function campaign.

Changes

  • withEuiTheme HOC → useEuiTheme() hook.
  • static defaultProps → destructured default values (items = [], mobileBreakpoints = ['xs', 's']).
  • Instance methods (isItemOpen, renderTree) → local closures.
  • The generated-id helper is memoized (useMemo(() => htmlIdGenerator('euiSideNav'), [])) so the content / heading DOM ids stay stable across renders, matching the previous class-field behavior.
  • The component stays generic (<T>); previously the export erased T to {} via withEuiTheme<EuiSideNavProps>, so T is now genuinely inferred from items — strictly more capable, no breaking change.

There's no internal state to migrate: isOpenOnMobile / toggleOpenOnMobile are controlled props owned by the consumer, so no useState was introduced.

Verification

Behavior and the public props API are unchanged — all existing snapshots pass as-is (none regenerated). yarn build:workspaces, yarn test-unit on side_nav.test.tsx + side_nav_item.test.tsx (28 tests, 22 snapshots), yarn tsc --noEmit (0 errors), and eslint all pass.

I followed the precedent of the earlier reference PR for this issue (#9533), which changed only side_nav.tsx with no changelog entry, since this is an internal, behavior-identical migration — happy to add a changelog note if you'd prefer one.

Closes #9475.


AI disclosure: this PR was drafted with Claude Code (AI-assisted) and human-reviewed. I mirrored the already-migrated EuiCollapsibleNav pattern and verified the migration is behavior-identical (all snapshots unchanged).

Convert EuiSideNav from a withEuiTheme-wrapped class to a generic
function component: useEuiTheme replaces the HOC, destructured defaults
replace defaultProps, and the instance methods become local closures.
Behavior and the public props API are unchanged (all snapshots pass
as-is). generateId is memoized so the generated DOM ids stay stable
across renders, matching the previous class-field behavior.
@youdie006
youdie006 requested a review from a team as a code owner July 22, 2026 01:28
Copilot AI review requested due to automatic review settings July 22, 2026 01:28
@cla-checker-service

cla-checker-service Bot commented Jul 22, 2026

Copy link
Copy Markdown

💚 CLA has been signed

@github-actions

Copy link
Copy Markdown

👋 Since this is a community submitted pull request, a Buildkite build has not been started automatically. Would an Elastic organization member please verify the contents of this pull request and kick off a build manually?

@github-actions github-actions Bot added the community contribution (Don't delete - used for automation) label Jul 22, 2026

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

Migrates EuiSideNav from a withEuiTheme-wrapped class component to a generic function component using hooks, while preserving existing rendering behavior and snapshot output.

Changes:

  • Replaced withEuiTheme/WithEuiThemeProps with the useEuiTheme() hook.
  • Converted class instance methods (isItemOpen, renderTree) into local closures inside the function component.
  • Replaced static defaultProps with default values in props destructuring and memoized the htmlIdGenerator to keep IDs stable across re-renders.

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

@weronikaolejniczak

Copy link
Copy Markdown
Contributor

Hey @youdie006 👋🏻 before we review your contribution, could you sign CLA? 🙏🏻

@youdie006 youdie006 closed this Jul 23, 2026
@youdie006 youdie006 reopened this Jul 23, 2026
@github-actions

Copy link
Copy Markdown

👋 Since this is a community submitted pull request, a Buildkite build has not been started automatically. Would an Elastic organization member please verify the contents of this pull request and kick off a build manually?

@youdie006

Copy link
Copy Markdown
Contributor Author

Thanks @weronikaolejniczak! I've signed the Elastic CLA now - the CLA check is green. Ready for review whenever you have a chance.

@weronikaolejniczak weronikaolejniczak added the skip-changelog Use on PRs to skip changelog requirement (Don't delete - used for automation) label Jul 23, 2026
Comment thread packages/eui/src/components/side_nav/side_nav.tsx Outdated

@weronikaolejniczak weronikaolejniczak 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.

I only found one nit. The behavior is preserved, changes minimal, CI passed (including unit, Cypress and VRT tests). I added skip-changelog label. All looks great! 🟢 Thank you for contributing, @youdie006!

Feel free to push the commit for that one nit, otherwise we'll take it from there.

EDIT: No need to rebase onto main unless there are conflicts. Otherwise, we will need to keep re-running CI.

Replace the manual htmlIdGenerator/useMemo with EUI's useGeneratedHtmlId
hook for the content and heading IDs, per review nit. Behavior is
preserved: useGeneratedHtmlId({ prefix, suffix, conditionalId }) returns
conditionalId || htmlIdGenerator(prefix)(suffix).
@infra-vault-gh-plugin-prod

Copy link
Copy Markdown

💚 Build Succeeded

History

@infra-vault-gh-plugin-prod

Copy link
Copy Markdown

💚 Build Succeeded

History

@weronikaolejniczak
weronikaolejniczak merged commit 2db2517 into elastic:main Jul 27, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community contribution (Don't delete - used for automation) skip-changelog Use on PRs to skip changelog requirement (Don't delete - used for automation)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[EuiSideNav] Migrate from class to function component

3 participants