From ae5253c822f9e935948ce7a43e7363bcc206ef6a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=B4mulo=20Penido?= <romulo.penido@gmail.com>
Date: Tue, 1 Oct 2024 10:20:34 -0300
Subject: [PATCH] feat: expose containerProps in StudioHeader [FC-0062] (#529)

---
 package-lock.json                     |  1 +
 package.json                          |  1 +
 src/studio-header/HeaderBody.jsx      | 17 ++++++++++++++---
 src/studio-header/MobileHeader.jsx    |  4 ++--
 src/studio-header/MobileMenu.jsx      |  4 ++--
 src/studio-header/NavDropdownMenu.jsx |  4 ++--
 src/studio-header/StudioHeader.jsx    |  9 ++++++---
 7 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 9752a1a8c..80c9c8121 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,6 +17,7 @@
         "@openedx/frontend-plugin-framework": "^1.3.0",
         "axios-mock-adapter": "1.22.0",
         "babel-polyfill": "6.26.0",
+        "classnames": "^2.5.1",
         "jest-environment-jsdom": "^29.7.0",
         "react-responsive": "8.2.0",
         "react-transition-group": "4.4.5"
diff --git a/package.json b/package.json
index 7993a4ac5..35eaa9ab2 100644
--- a/package.json
+++ b/package.json
@@ -63,6 +63,7 @@
     "@openedx/frontend-plugin-framework": "^1.3.0",
     "axios-mock-adapter": "1.22.0",
     "babel-polyfill": "6.26.0",
+    "classnames": "^2.5.1",
     "jest-environment-jsdom": "^29.7.0",
     "react-responsive": "8.2.0",
     "react-transition-group": "4.4.5"
diff --git a/src/studio-header/HeaderBody.jsx b/src/studio-header/HeaderBody.jsx
index 7a4426d4b..536dca1e1 100644
--- a/src/studio-header/HeaderBody.jsx
+++ b/src/studio-header/HeaderBody.jsx
@@ -1,6 +1,7 @@
 import React from 'react';
 import PropTypes from 'prop-types';
 import { useIntl } from '@edx/frontend-platform/i18n';
+import classNames from 'classnames';
 import {
   ActionRow,
   Button,
@@ -37,6 +38,7 @@ const HeaderBody = ({
   mainMenuDropdowns,
   outlineLink,
   searchButtonAction,
+  containerProps,
 }) => {
   const intl = useIntl();
 
@@ -50,8 +52,14 @@ const HeaderBody = ({
     />
   );
 
+  const { className: containerClassName, ...restContainerProps } = containerProps || {};
+
   return (
-    <Container size="xl" className="px-2.5">
+    <Container
+      size="xl"
+      className={classNames('px-2.5', containerClassName)}
+      {...restContainerProps}
+    >
       <ActionRow as="header">
         {isHiddenMainMenu ? (
           <Row className="flex-nowrap ml-4">
@@ -110,6 +118,7 @@ const HeaderBody = ({
               iconAs={Icon}
               onClick={searchButtonAction}
               aria-label={intl.formatMessage(messages['header.label.search.nav'])}
+              alt={intl.formatMessage(messages['header.label.search.nav'])}
             />
           </Nav>
         )}
@@ -147,14 +156,15 @@ HeaderBody.propTypes = {
   isHiddenMainMenu: PropTypes.bool,
   mainMenuDropdowns: PropTypes.arrayOf(PropTypes.shape({
     id: PropTypes.string,
-    buttonTitle: PropTypes.string,
+    buttonTitle: PropTypes.node,
     items: PropTypes.arrayOf(PropTypes.shape({
       href: PropTypes.string,
-      title: PropTypes.string,
+      title: PropTypes.node,
     })),
   })),
   outlineLink: PropTypes.string,
   searchButtonAction: PropTypes.func,
+  containerProps: PropTypes.shape(Container.propTypes),
 };
 
 HeaderBody.defaultProps = {
@@ -174,6 +184,7 @@ HeaderBody.defaultProps = {
   mainMenuDropdowns: [],
   outlineLink: null,
   searchButtonAction: null,
+  containerProps: {},
 };
 
 export default HeaderBody;
diff --git a/src/studio-header/MobileHeader.jsx b/src/studio-header/MobileHeader.jsx
index f1aecd7f3..fd3cca1bf 100644
--- a/src/studio-header/MobileHeader.jsx
+++ b/src/studio-header/MobileHeader.jsx
@@ -48,10 +48,10 @@ MobileHeader.propTypes = {
   isAdmin: PropTypes.bool,
   mainMenuDropdowns: PropTypes.arrayOf(PropTypes.shape({
     id: PropTypes.string,
-    buttonTitle: PropTypes.string,
+    buttonTitle: PropTypes.node,
     items: PropTypes.arrayOf(PropTypes.shape({
       href: PropTypes.string,
-      title: PropTypes.string,
+      title: PropTypes.node,
     })),
   })),
   outlineLink: PropTypes.string,
diff --git a/src/studio-header/MobileMenu.jsx b/src/studio-header/MobileMenu.jsx
index 610321e66..892151cad 100644
--- a/src/studio-header/MobileMenu.jsx
+++ b/src/studio-header/MobileMenu.jsx
@@ -37,10 +37,10 @@ const MobileMenu = ({
 MobileMenu.propTypes = {
   mainMenuDropdowns: PropTypes.arrayOf(PropTypes.shape({
     id: PropTypes.string,
-    buttonTitle: PropTypes.string,
+    buttonTitle: PropTypes.node,
     items: PropTypes.arrayOf(PropTypes.shape({
       href: PropTypes.string,
-      title: PropTypes.string,
+      title: PropTypes.node,
     })),
   })),
 };
diff --git a/src/studio-header/NavDropdownMenu.jsx b/src/studio-header/NavDropdownMenu.jsx
index d8d9dd47a..e46c04908 100644
--- a/src/studio-header/NavDropdownMenu.jsx
+++ b/src/studio-header/NavDropdownMenu.jsx
@@ -30,10 +30,10 @@ const NavDropdownMenu = ({
 
 NavDropdownMenu.propTypes = {
   id: PropTypes.string.isRequired,
-  buttonTitle: PropTypes.string.isRequired,
+  buttonTitle: PropTypes.node.isRequired,
   items: PropTypes.arrayOf(PropTypes.shape({
     href: PropTypes.string,
-    title: PropTypes.string,
+    title: PropTypes.node,
   })).isRequired,
 };
 
diff --git a/src/studio-header/StudioHeader.jsx b/src/studio-header/StudioHeader.jsx
index 886ad8411..0ee6d8539 100644
--- a/src/studio-header/StudioHeader.jsx
+++ b/src/studio-header/StudioHeader.jsx
@@ -16,7 +16,7 @@ ensureConfig([
 ], 'Studio Header component');
 
 const StudioHeader = ({
-  number, org, title, isHiddenMainMenu, mainMenuDropdowns, outlineLink, searchButtonAction,
+  number, org, title, containerProps, isHiddenMainMenu, mainMenuDropdowns, outlineLink, searchButtonAction,
 }) => {
   const { authenticatedUser, config } = useContext(AppContext);
   const props = {
@@ -25,6 +25,7 @@ const StudioHeader = ({
     number,
     org,
     title,
+    containerProps,
     username: authenticatedUser?.username,
     isAdmin: authenticatedUser?.administrator,
     authenticatedUserAvatar: authenticatedUser?.avatar,
@@ -53,13 +54,14 @@ StudioHeader.propTypes = {
   number: PropTypes.string,
   org: PropTypes.string,
   title: PropTypes.string.isRequired,
+  containerProps: HeaderBody.propTypes.containerProps,
   isHiddenMainMenu: PropTypes.bool,
   mainMenuDropdowns: PropTypes.arrayOf(PropTypes.shape({
     id: PropTypes.string,
-    buttonTitle: PropTypes.string,
+    buttonTitle: PropTypes.node,
     items: PropTypes.arrayOf(PropTypes.shape({
       href: PropTypes.string,
-      title: PropTypes.string,
+      title: PropTypes.node,
     })),
   })),
   outlineLink: PropTypes.string,
@@ -69,6 +71,7 @@ StudioHeader.propTypes = {
 StudioHeader.defaultProps = {
   number: '',
   org: '',
+  containerProps: {},
   isHiddenMainMenu: false,
   mainMenuDropdowns: [],
   outlineLink: null,