Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/desktop-header/DesktopHeader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { desktopUserMenuDataShape } from './DesktopHeaderUserMenu';

// i18n
import messages from '../Header.messages';
import NotificationTraySlot from '../plugin-slots/NotificationSlot';

// Assets

Expand All @@ -39,6 +40,8 @@ const DesktopHeader = ({

const renderSecondaryMenu = () => <DesktopSecondaryMenuSlot menu={secondaryMenu} />;

const renderNotificationTray = () => <NotificationTraySlot />;

const renderUserMenu = () => (
<Menu transitionClassName="menu-dropdown" transitionTimeout={250}>
<MenuTrigger
Expand Down Expand Up @@ -78,6 +81,7 @@ const DesktopHeader = ({
{loggedIn
? (
<>
{renderNotificationTray()}
{renderSecondaryMenu()}
{renderUserMenu()}
</>
Expand Down
14 changes: 8 additions & 6 deletions src/learning-header/LearningHeader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import CourseInfoSlot from '../plugin-slots/CourseInfoSlot';
import { courseInfoDataShape } from './LearningHeaderCourseInfo';
import messages from './messages';
import LearningHelpSlot from '../plugin-slots/LearningHelpSlot';
import NotificationTraySlot from '../plugin-slots/NotificationSlot';

const LearningHeader = ({
courseOrg,
Expand Down Expand Up @@ -38,12 +39,13 @@ const LearningHeader = ({
<CourseInfoSlot courseOrg={courseOrg} courseNumber={courseNumber} courseTitle={courseTitle} />
</div>
{showUserDropdown && authenticatedUser && (
<>
<LearningHelpSlot />
<AuthenticatedUserDropdown
username={authenticatedUser.username}
/>
</>
<>
<NotificationTraySlot />
<LearningHelpSlot />
<AuthenticatedUserDropdown
username={authenticatedUser.username}
/>
</>
)}
{showUserDropdown && !authenticatedUser && (
<AnonymousUserMenu />
Expand Down
4 changes: 4 additions & 0 deletions src/mobile-header/MobileHeader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import MobileMainMenuSlot from '../plugin-slots/MobileMainMenuSlot';
import { mobileHeaderMainMenuDataShape } from './MobileHeaderMainMenu';
import MobileUserMenuSlot from '../plugin-slots/MobileUserMenuSlot';
import { mobileHeaderUserMenuDataShape } from './MobileHeaderUserMenu';
import NotificationTraySlot from '../plugin-slots/NotificationSlot';

// i18n
import messages from '../Header.messages';
Expand Down Expand Up @@ -43,6 +44,8 @@ const MobileHeader = ({

const renderUserMenuToggle = () => <MobileUserMenuToggleSlot avatar={avatar} label={username} />;

const renderNotificationTray = () => <NotificationTraySlot />;

const logoProps = { src: logo, alt: logoAltText, href: logoDestination };
const stickyClassName = stickyOnMobile ? 'sticky-top' : '';
const logoClasses = getConfig().AUTHN_MINIMAL_HEADER ? 'justify-content-left pl-3' : 'justify-content-center';
Expand Down Expand Up @@ -87,6 +90,7 @@ const MobileHeader = ({
aria-label={intl.formatMessage(messages['header.label.account.menu'])}
title={intl.formatMessage(messages['header.label.account.menu'])}
>
{renderNotificationTray()}
{renderUserMenuToggle()}
</MenuTrigger>
<MenuContent tag="ul" className="nav flex-column pin-left pin-right border-top shadow py-2">
Expand Down
81 changes: 81 additions & 0 deletions src/plugin-slots/NotificationSlot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Notification Tray Slot

### Slot ID: `org.openedx.frontend.layout.notification_tray.v1`

## Description

This slot is used to replace, modify, or hide the contents of the notification tray in the Open edX header. It allows developers to easily extend or customize the notification tray using the [Open edX Frontend Plugin Framework](https://github.com/openedx/frontend-plugin-framework).

The slot is kept empty so that it can only be enabled when it is required else
nothing is displayed.

![Screenshot for frontend-app-learning]('./images/learner_header_notification.png')

![Screenshot for frontend-app-learner-dashboard]('./images/learner_dashboard_notification.png')

![Screenshot for frontend-app-authroing]('./images/studio_header_notification.png')

## Examples

### Insert Notification Tray with Custom Component

The following `env.config.jsx` will replace the notification tray's contents entirely (in this case with a custom emoji icon):

```jsx
import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';

const config = {
pluginSlots: {
'org.openedx.frontend.layout.notification_tray.v1': {
keepDefault: false,
plugins: [
{
op: PLUGIN_OPERATIONS.Insert,
widget: {
id: 'custom_notification_tray',
type: DIRECT_PLUGIN,
RenderWidget: () => (
<span>🔔 Custom Notification</span>
),
},
},
],
},
},
};

export default config;
```

## Component Usage

Import the `NotificationTraySlot` component and use it in your layout or header component where you want the notifications tray to appear:

```jsx
import NotificationTraySlot from './src/plugin-slots/NotificationSlot';

function Header() {
return (
<header>
{/* Other header content */}
<NotificationTraySlot />
</header>
);
}
```

## API

- **Slot ID:** `org.openedx.frontend.layout.notification_tray.v1`
- **Alias:** `notification_tray_plugin`
- **Component:** Uses the [PluginSlot](https://github.com/openedx/frontend-plugin-framework#pluginslot) from the Open edX Frontend Plugin Framework for plugin injection.
- **Props:** This component does not accept any props directly.

## License

This component is part of the [open-craft/frontend-component-header](https://github.com/open-craft/frontend-component-header) repository and is made available under its license.

## Contributing

If you would like to contribute improvements or additional plugin slots, please open a pull request or issue in the [repository](https://github.com/open-craft/frontend-component-header).

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions src/plugin-slots/NotificationSlot/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import { PluginSlot } from '@openedx/frontend-plugin-framework';

const NotificationTraySlot = () => (
<PluginSlot
id="org.openedx.frontend.layout.notification_tray.v1"
idAliases={['notification_tray_plugin']}

Choose a reason for hiding this comment

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

This is not needed for a new slot.

/>
);

export default NotificationTraySlot;
1 change: 1 addition & 0 deletions src/plugin-slots/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

### Shared
* [`org.openedx.frontend.layout.header_logo.v1`](./LogoSlot/)
* [`org.openedx.frontend.layout.notification_tray.v1`](./NotificationSlot/)

### Desktop Header
* [`org.openedx.frontend.layout.header_desktop.v1`](./DesktopHeaderSlot/)
Expand Down
6 changes: 5 additions & 1 deletion src/studio-header/HeaderBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import UserMenu from './UserMenu';
import BrandNav from './BrandNav';
import NavDropdownMenu from './NavDropdownMenu';
import messages from './messages';
import NotificationTraySlot from '../plugin-slots/NotificationSlot';

const HeaderBody = ({
logo,
Expand Down Expand Up @@ -57,7 +58,7 @@ const HeaderBody = ({
return (
<Container
size="xl"
className={classNames('px-2.5', containerClassName)}
className={classNames('px-0', containerClassName)}
{...restContainerProps}
>
<ActionRow as="header">
Expand Down Expand Up @@ -116,6 +117,9 @@ const HeaderBody = ({
</>
)}
<ActionRow.Spacer />
<Nav>
<NotificationTraySlot />
</Nav>
{searchButtonAction && (
<Nav>
<IconButton
Expand Down