feat: Moves search button into a slot (#644)
Signed-off-by: Farhaan Bukhsh <farhaan@opencraft.com>
This commit is contained in:
@@ -24,3 +24,6 @@
|
|||||||
* [`org.openedx.frontend.layout.header_mobile_main_menu.v1`](./MobileMainMenuSlot/)
|
* [`org.openedx.frontend.layout.header_mobile_main_menu.v1`](./MobileMainMenuSlot/)
|
||||||
* [`org.openedx.frontend.layout.header_mobile_user_menu.v1`](./MobileUserMenuSlot/)
|
* [`org.openedx.frontend.layout.header_mobile_user_menu.v1`](./MobileUserMenuSlot/)
|
||||||
* [`org.openedx.frontend.layout.header_mobile_user_menu_trigger.v1`](./MobileUserMenuToggleSlot/)
|
* [`org.openedx.frontend.layout.header_mobile_user_menu_trigger.v1`](./MobileUserMenuToggleSlot/)
|
||||||
|
|
||||||
|
### Studio Header
|
||||||
|
* [`org.openedx.frontend.layout.studio_header_search_button_slot.v1`](./StudioHeaderSearchButtonSlot/)
|
||||||
|
|||||||
89
src/plugin-slots/StudioHeaderSearchButtonSlot/README.md
Normal file
89
src/plugin-slots/StudioHeaderSearchButtonSlot/README.md
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
# Studio Header Search Button Slot
|
||||||
|
|
||||||
|
### Slot ID: `org.openedx.frontend.layout.studio_header_search_button_slot.v1`
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
This slot is used to replace/modify/hide the search button in the studio header.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Replace search with custom component
|
||||||
|
|
||||||
|
The following `env.config.jsx` will replace the search button 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.studio_header_search_button_slot.v1": {
|
||||||
|
keepDefault: false,
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
op: PLUGIN_OPERATIONS.Insert,
|
||||||
|
widget: {
|
||||||
|
id: "custom_notification_tray",
|
||||||
|
type: DIRECT_PLUGIN,
|
||||||
|
RenderWidget: () => <span>🔔</span>,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Add custom component before and after search button
|
||||||
|
|
||||||
|
The following `env.config.jsx` will insert emoji after and before the search button
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import {
|
||||||
|
DIRECT_PLUGIN,
|
||||||
|
PLUGIN_OPERATIONS,
|
||||||
|
} from "@openedx/frontend-plugin-framework";
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
pluginSlots: {
|
||||||
|
"org.openedx.frontend.layout.studio_header_search_button_slot.v1": {
|
||||||
|
keepDefault: true,
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
op: PLUGIN_OPERATIONS.Insert,
|
||||||
|
widget: {
|
||||||
|
priority: 10,
|
||||||
|
id: 'custom_notification_tray_before',
|
||||||
|
type: DIRECT_PLUGIN,
|
||||||
|
RenderWidget: () => <span>🔔</span>,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
op: PLUGIN_OPERATIONS.Insert,
|
||||||
|
widget: {
|
||||||
|
priority: 90,
|
||||||
|
id: 'custom_notification_tray_after',
|
||||||
|
type: DIRECT_PLUGIN,
|
||||||
|
RenderWidget: () => <span>🔕</span>,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
- **Slot ID:** `org.openedx.frontend.layout.studio_header_search_button_slot.v1`
|
||||||
|
- **Component:** Uses the [PluginSlot](https://github.com/openedx/frontend-plugin-framework#pluginslot) from the Open edX Frontend Plugin Framework for plugin injection.
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
34
src/plugin-slots/StudioHeaderSearchButtonSlot/index.jsx
Normal file
34
src/plugin-slots/StudioHeaderSearchButtonSlot/index.jsx
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { PluginSlot } from '@openedx/frontend-plugin-framework';
|
||||||
|
import { Nav, IconButton, Icon } from '@openedx/paragon';
|
||||||
|
import { Search } from '@openedx/paragon/icons';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
|
import messages from '../../studio-header/messages';
|
||||||
|
|
||||||
|
const StudioHeaderSearchButtonSlot = ({ searchButtonAction }) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
return (
|
||||||
|
<PluginSlot
|
||||||
|
id="org.openedx.frontend.layout.studio_header_search_button_slot.v1"
|
||||||
|
>
|
||||||
|
{searchButtonAction && (
|
||||||
|
<Nav>
|
||||||
|
<IconButton
|
||||||
|
src={Search}
|
||||||
|
iconAs={Icon}
|
||||||
|
onClick={searchButtonAction}
|
||||||
|
aria-label={intl.formatMessage(messages['header.label.search.nav'])}
|
||||||
|
alt={intl.formatMessage(messages['header.label.search.nav'])}
|
||||||
|
/>
|
||||||
|
</Nav>
|
||||||
|
)}
|
||||||
|
</PluginSlot>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
StudioHeaderSearchButtonSlot.propTypes = {
|
||||||
|
searchButtonAction: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default StudioHeaderSearchButtonSlot;
|
||||||
@@ -1,22 +1,19 @@
|
|||||||
import React, { type ReactNode, type ComponentProps } from 'react';
|
import React, { type ReactNode, type ComponentProps } from 'react';
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import {
|
import {
|
||||||
ActionRow,
|
ActionRow,
|
||||||
Button,
|
Button,
|
||||||
Container,
|
Container,
|
||||||
Icon,
|
|
||||||
IconButton,
|
|
||||||
Nav,
|
Nav,
|
||||||
Row,
|
Row,
|
||||||
} from '@openedx/paragon';
|
} from '@openedx/paragon';
|
||||||
import { Close, MenuIcon, Search } from '@openedx/paragon/icons';
|
import { Close, MenuIcon } from '@openedx/paragon/icons';
|
||||||
|
|
||||||
import CourseLockUp from './CourseLockUp';
|
import CourseLockUp from './CourseLockUp';
|
||||||
import UserMenu from './UserMenu';
|
import UserMenu from './UserMenu';
|
||||||
import BrandNav from './BrandNav';
|
import BrandNav from './BrandNav';
|
||||||
import NavDropdownMenu from './NavDropdownMenu';
|
import NavDropdownMenu from './NavDropdownMenu';
|
||||||
import messages from './messages';
|
import StudioHeaderSearchButtonSlot from '../plugin-slots/StudioHeaderSearchButtonSlot';
|
||||||
|
|
||||||
export interface HeaderBodyProps {
|
export interface HeaderBodyProps {
|
||||||
studioBaseUrl: string;
|
studioBaseUrl: string;
|
||||||
@@ -65,7 +62,6 @@ const HeaderBody = ({
|
|||||||
searchButtonAction,
|
searchButtonAction,
|
||||||
containerProps = {},
|
containerProps = {},
|
||||||
}: HeaderBodyProps) => {
|
}: HeaderBodyProps) => {
|
||||||
const intl = useIntl();
|
|
||||||
|
|
||||||
const renderBrandNav = (
|
const renderBrandNav = (
|
||||||
<BrandNav
|
<BrandNav
|
||||||
@@ -141,17 +137,9 @@ const HeaderBody = ({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<ActionRow.Spacer />
|
<ActionRow.Spacer />
|
||||||
{searchButtonAction && (
|
<StudioHeaderSearchButtonSlot
|
||||||
<Nav>
|
searchButtonAction={searchButtonAction}
|
||||||
<IconButton
|
/>
|
||||||
src={Search}
|
|
||||||
iconAs={Icon}
|
|
||||||
onClick={searchButtonAction}
|
|
||||||
aria-label={intl.formatMessage(messages['header.label.search.nav'])}
|
|
||||||
alt={intl.formatMessage(messages['header.label.search.nav'])}
|
|
||||||
/>
|
|
||||||
</Nav>
|
|
||||||
)}
|
|
||||||
<Nav>
|
<Nav>
|
||||||
<UserMenu
|
<UserMenu
|
||||||
{...{
|
{...{
|
||||||
|
|||||||
Reference in New Issue
Block a user