Skip to content

Commit 1642a6e

Browse files
syedsajjadkazmiimubbsharanwar
authored andcommitted
feat: add user menu slots in header
1 parent 6e3948a commit 1642a6e

18 files changed

+253
-1
lines changed

README.rst

+6
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ Usage
4343

4444
``import Header, { messages } from '@edx/frontend-component-header-edx';``
4545

46+
Plugins
47+
=======
48+
This component can be customized using `Frontend Plugin Framework <https://github.com/openedx/frontend-plugin-framework>`_.
49+
50+
The parts of this component that can be customized in that manner are documented `here </src/plugin-slots>`_.
51+
4652
Development
4753
===========
4854

package-lock.json

+50
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
"@fortawesome/free-regular-svg-icons": "^6.6.0",
6262
"@fortawesome/free-solid-svg-icons": "^6.6.0",
6363
"@fortawesome/react-fontawesome": "^0.2.0",
64+
"@openedx/frontend-plugin-framework": "^1.2.1",
6465
"@openedx/paragon": "^21.11.0",
6566
"@reduxjs/toolkit": "1.9.7",
6667
"axios-mock-adapter": "1.22.0",

src/DesktopHeader.jsx

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { getConfig } from '@edx/frontend-platform';
55
import { AvatarButton, Dropdown } from '@openedx/paragon';
66

77
// Local Components
8+
import UserMenuGroupItemSlot from './plugin-slots/UserMenuGroupItemSlot';
9+
import UserMenuGroupSlot from './plugin-slots/UserMenuGroupSlot';
810
import UserMenuItem from './common/UserMenuItem';
911
import { Menu, MenuTrigger, MenuContent } from './Menu';
1012
import { LinkedLogo, Logo } from './Logo';
@@ -104,10 +106,12 @@ class DesktopHeader extends React.Component {
104106
/>
105107
</Dropdown.Item>
106108
)}
109+
<UserMenuGroupSlot />
107110
{userMenu.map((group, index) => (
108111
// eslint-disable-next-line react/jsx-no-comment-textnodes,react/no-array-index-key
109112
<React.Fragment key={index}>
110113
{group.heading && <Dropdown.Header>{group.heading}</Dropdown.Header>}
114+
{index === 0 && (<UserMenuGroupItemSlot />)}
111115
{group.items.map(({
112116
type, content, href, disabled, isActive, onClick,
113117
}) => (

src/MobileHeader.jsx

+8-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { getConfig } from '@edx/frontend-platform';
55

66
// Local Components
77
import { AvatarButton } from '@openedx/paragon';
8+
import UserMenuGroupSlot from './plugin-slots/UserMenuGroupSlot';
9+
import UserMenuGroupItemSlot from './plugin-slots/UserMenuGroupItemSlot';
810
import { Menu, MenuTrigger, MenuContent } from './Menu';
911
import { LinkedLogo, Logo } from './Logo';
1012
import UserMenuItem from './common/UserMenuItem';
@@ -97,7 +99,12 @@ class MobileHeader extends React.Component {
9799
))
98100
));
99101

100-
return userInfoItem ? [userInfoItem, ...userMenuItems] : userMenuItems;
102+
const userMenuGroupSlot = <UserMenuGroupSlot />;
103+
const userMenuGroupItemSlot = <UserMenuGroupItemSlot />;
104+
105+
return userInfoItem
106+
? [userInfoItem, userMenuGroupSlot, userMenuGroupItemSlot, ...userMenuItems]
107+
: [userMenuGroupSlot, userMenuGroupItemSlot, ...userMenuItems];
101108
}
102109

103110
renderLoggedOutItems() {

src/plugin-slots/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# `frontend-component-header-edx` Plugin Slots
2+
3+
* [`header_user_menu_group_slot`](./UserMenuGroupSlot/)
4+
* [`header_user_menu_group_item_slot`](./UserMenuGroupItemSlot/)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Header User Menu Group Slot
2+
3+
### Slot ID: `header_user_menu_group_item_slot`
4+
5+
## Description
6+
7+
This slot allows you to insert a user menu item into a group within the header's user menu for both desktop and mobile screens.
8+
9+
Note: Ensure the slot is provided with appropriate JSX that can render smoothly on both desktop and mobile screens.
10+
11+
## Example
12+
13+
The following ``env.config.jsx`` demonstrates how to insert a user menu item into a group within the header's user menu
14+
for both desktop and mobile screens.
15+
16+
**Default Behaviour:**
17+
18+
Desktop:
19+
![Screenshot of Default Header_User_Menu](./images/default_user_menu_desktop.png)
20+
21+
Mobile:
22+
![Screenshot of Default Header_User_Menu](./images/default_user_menu_mobile.png)
23+
24+
**Inserted a user menu group:**
25+
26+
Desktop:
27+
![Screenshot of Inserted_User_Menu_Group](./images/inserted_user_menu_item_desktop.png)
28+
29+
Mobile:
30+
![Screenshot of Inserted_User_Menu_Group](./images/inserted_user_menu_item_mobile.png)
31+
32+
```jsx
33+
import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';
34+
import { breakpoints, Dropdown, useWindowSize } from '@openedx/paragon';
35+
36+
const config = {
37+
pluginSlots: {
38+
header_user_menu_group_slot: {
39+
plugins: [
40+
{
41+
// Insert some user menu group item
42+
op: PLUGIN_OPERATIONS.Insert,
43+
widget: {
44+
id: 'user_menu_group',
45+
type: DIRECT_PLUGIN,
46+
RenderWidget: () => {
47+
const { width } = useWindowSize();
48+
const isMobile = width <= breakpoints.small.maxWidth;
49+
if (!isMobile) {
50+
return (
51+
<Dropdown.Item as="a" href="#">
52+
User Menu Group Item
53+
</Dropdown.Item>
54+
);
55+
}
56+
return (
57+
<li className="nav-item">
58+
<a href="#" className="nav-link">
59+
User Menu Group Item
60+
</a>
61+
</li>
62+
);
63+
},
64+
},
65+
},
66+
],
67+
},
68+
},
69+
}
70+
71+
export default config;
72+
```
Loading
Loading
Loading
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import React from 'react';
2+
3+
import { PluginSlot } from '@openedx/frontend-plugin-framework';
4+
5+
const UserMenuGroupItemSlot = () => (
6+
<PluginSlot
7+
id="header_user_menu_group_item_slot"
8+
/>
9+
);
10+
11+
export default UserMenuGroupItemSlot;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Header User Menu Group Slot
2+
3+
### Slot ID: `header_user_menu_group_slot`
4+
5+
## Description
6+
7+
This slot is used to insert a user menu group in the header's user menu for both desktop and mobile screens.
8+
9+
Note: Ensure the slot is provided with appropriate JSX that can render smoothly on both desktop and mobile screens.
10+
11+
## Example
12+
13+
The following ``env.config.jsx`` demonstrates how to insert a user menu group into the header's user menu
14+
for both mobile and desktop screens.
15+
16+
**Default Behaviour:**
17+
18+
Desktop:
19+
![Screenshot of Default Header_User_Menu_Desktop](./images/default_user_menu_desktop.png)
20+
21+
Mobile:
22+
![Screenshot of Default Header_User_Menu_Mobile](./images/default_user_menu_mobile.png)
23+
24+
**Inserted a user menu group:**
25+
26+
Desktop:
27+
![Screenshot of Inserted_User_Menu_Group_Desktop](./images/inserted_user_menu_desktop.png)
28+
29+
Mobile:
30+
![Screenshot of Inserted_User_Menu_Group_Mobile](./images/inserted_user_menu_mobile.png)
31+
32+
```jsx
33+
import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';
34+
import { breakpoints, Dropdown, useWindowSize } from '@openedx/paragon';
35+
36+
const config = {
37+
pluginSlots: {
38+
header_user_menu_group_slot: {
39+
plugins: [
40+
{
41+
// Insert some user menu group
42+
op: PLUGIN_OPERATIONS.Insert,
43+
widget: {
44+
id: 'user_menu_group',
45+
type: DIRECT_PLUGIN,
46+
RenderWidget: () => {
47+
const { width } = useWindowSize();
48+
const isMobile = width <= breakpoints.small.maxWidth;
49+
if (!isMobile) {
50+
return (
51+
<>
52+
<Dropdown.Header>User Menu Group Header</Dropdown.Header>
53+
<Dropdown.Item as="a" href="#" className="active">
54+
User Menu Group Item - Active
55+
</Dropdown.Item>
56+
<Dropdown.Item as="a" href="#">
57+
User Menu Group Item 2
58+
</Dropdown.Item>
59+
<Dropdown.Divider />
60+
</>
61+
);
62+
}
63+
return (
64+
<>
65+
<li className="nav-item">
66+
<a href="#" className="nav-link active">
67+
User Menu Group Item - Active
68+
</a>
69+
</li>
70+
<li className="nav-item">
71+
<a href="#" className="nav-link active">
72+
User Menu Group Item 2
73+
</a>
74+
</li>
75+
</>
76+
);
77+
},
78+
},
79+
},
80+
],
81+
},
82+
},
83+
}
84+
85+
export default config;
86+
```
Loading
Loading
Loading
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import React from 'react';
2+
3+
import { PluginSlot } from '@openedx/frontend-plugin-framework';
4+
5+
const UserMenuGroupSlot = () => (
6+
<PluginSlot
7+
id="header_user_menu_group_slot"
8+
/>
9+
);
10+
11+
export default UserMenuGroupSlot;

0 commit comments

Comments
 (0)