Skip to content

Commit c861651

Browse files
feat: Moves search button into a slot (#644)
Signed-off-by: Farhaan Bukhsh <[email protected]>
1 parent 9706385 commit c861651

File tree

6 files changed

+131
-17
lines changed

6 files changed

+131
-17
lines changed

src/plugin-slots/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,6 @@
2424
* [`org.openedx.frontend.layout.header_mobile_main_menu.v1`](./MobileMainMenuSlot/)
2525
* [`org.openedx.frontend.layout.header_mobile_user_menu.v1`](./MobileUserMenuSlot/)
2626
* [`org.openedx.frontend.layout.header_mobile_user_menu_trigger.v1`](./MobileUserMenuToggleSlot/)
27+
28+
### Studio Header
29+
* [`org.openedx.frontend.layout.studio_header_search_button_slot.v1`](./StudioHeaderSearchButtonSlot/)
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Studio Header Search Button Slot
2+
3+
### Slot ID: `org.openedx.frontend.layout.studio_header_search_button_slot.v1`
4+
5+
## Description
6+
7+
This slot is used to replace/modify/hide the search button in the studio header.
8+
9+
## Examples
10+
11+
### Replace search with custom component
12+
13+
The following `env.config.jsx` will replace the search button entirely (in this case with a custom emoji icon):
14+
15+
![Search button being replaced](./images/studio_header_search_button_replace.png)
16+
17+
```jsx
18+
import {
19+
DIRECT_PLUGIN,
20+
PLUGIN_OPERATIONS,
21+
} from "@openedx/frontend-plugin-framework";
22+
23+
const config = {
24+
pluginSlots: {
25+
"org.openedx.frontend.layout.studio_header_search_button_slot.v1": {
26+
keepDefault: false,
27+
plugins: [
28+
{
29+
op: PLUGIN_OPERATIONS.Insert,
30+
widget: {
31+
id: "custom_notification_tray",
32+
type: DIRECT_PLUGIN,
33+
RenderWidget: () => <span>🔔</span>,
34+
},
35+
},
36+
],
37+
},
38+
},
39+
};
40+
41+
export default config;
42+
```
43+
44+
### Add custom component before and after search button
45+
46+
The following `env.config.jsx` will insert emoji after and before the search button
47+
48+
![Add custom component before and after search button](./images/studio_header_search_button_before_after.png)
49+
50+
```jsx
51+
import {
52+
DIRECT_PLUGIN,
53+
PLUGIN_OPERATIONS,
54+
} from "@openedx/frontend-plugin-framework";
55+
56+
const config = {
57+
pluginSlots: {
58+
"org.openedx.frontend.layout.studio_header_search_button_slot.v1": {
59+
keepDefault: true,
60+
plugins: [
61+
{
62+
op: PLUGIN_OPERATIONS.Insert,
63+
widget: {
64+
priority: 10,
65+
id: 'custom_notification_tray_before',
66+
type: DIRECT_PLUGIN,
67+
RenderWidget: () => <span>🔔</span>,
68+
},
69+
},
70+
{
71+
op: PLUGIN_OPERATIONS.Insert,
72+
widget: {
73+
priority: 90,
74+
id: 'custom_notification_tray_after',
75+
type: DIRECT_PLUGIN,
76+
RenderWidget: () => <span>🔕</span>,
77+
},
78+
},
79+
],
80+
},
81+
};
82+
83+
export default config;
84+
```
85+
86+
## API
87+
88+
- **Slot ID:** `org.openedx.frontend.layout.studio_header_search_button_slot.v1`
89+
- **Component:** Uses the [PluginSlot](https://github.com/openedx/frontend-plugin-framework#pluginslot) from the Open edX Frontend Plugin Framework for plugin injection.
13.7 KB
Loading
10.5 KB
Loading
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import React from 'react';
2+
import { PluginSlot } from '@openedx/frontend-plugin-framework';
3+
import { Nav, IconButton, Icon } from '@openedx/paragon';
4+
import { Search } from '@openedx/paragon/icons';
5+
import PropTypes from 'prop-types';
6+
import { useIntl } from '@edx/frontend-platform/i18n';
7+
import messages from '../../studio-header/messages';
8+
9+
const StudioHeaderSearchButtonSlot = ({ searchButtonAction }) => {
10+
const intl = useIntl();
11+
return (
12+
<PluginSlot
13+
id="org.openedx.frontend.layout.studio_header_search_button_slot.v1"
14+
>
15+
{searchButtonAction && (
16+
<Nav>
17+
<IconButton
18+
src={Search}
19+
iconAs={Icon}
20+
onClick={searchButtonAction}
21+
aria-label={intl.formatMessage(messages['header.label.search.nav'])}
22+
alt={intl.formatMessage(messages['header.label.search.nav'])}
23+
/>
24+
</Nav>
25+
)}
26+
</PluginSlot>
27+
);
28+
};
29+
30+
StudioHeaderSearchButtonSlot.propTypes = {
31+
searchButtonAction: PropTypes.func,
32+
};
33+
34+
export default StudioHeaderSearchButtonSlot;

src/studio-header/HeaderBody.tsx

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
11
import React, { type ReactNode, type ComponentProps } from 'react';
2-
import { useIntl } from '@edx/frontend-platform/i18n';
32
import classNames from 'classnames';
43
import {
54
ActionRow,
65
Button,
76
Container,
8-
Icon,
9-
IconButton,
107
Nav,
118
Row,
129
} from '@openedx/paragon';
13-
import { Close, MenuIcon, Search } from '@openedx/paragon/icons';
10+
import { Close, MenuIcon } from '@openedx/paragon/icons';
1411

1512
import CourseLockUp from './CourseLockUp';
1613
import UserMenu from './UserMenu';
1714
import BrandNav from './BrandNav';
1815
import NavDropdownMenu from './NavDropdownMenu';
19-
import messages from './messages';
16+
import StudioHeaderSearchButtonSlot from '../plugin-slots/StudioHeaderSearchButtonSlot';
2017

2118
export interface HeaderBodyProps {
2219
studioBaseUrl: string;
@@ -65,7 +62,6 @@ const HeaderBody = ({
6562
searchButtonAction,
6663
containerProps = {},
6764
}: HeaderBodyProps) => {
68-
const intl = useIntl();
6965

7066
const renderBrandNav = (
7167
<BrandNav
@@ -141,17 +137,9 @@ const HeaderBody = ({
141137
</>
142138
)}
143139
<ActionRow.Spacer />
144-
{searchButtonAction && (
145-
<Nav>
146-
<IconButton
147-
src={Search}
148-
iconAs={Icon}
149-
onClick={searchButtonAction}
150-
aria-label={intl.formatMessage(messages['header.label.search.nav'])}
151-
alt={intl.formatMessage(messages['header.label.search.nav'])}
152-
/>
153-
</Nav>
154-
)}
140+
<StudioHeaderSearchButtonSlot
141+
searchButtonAction={searchButtonAction}
142+
/>
155143
<Nav>
156144
<UserMenu
157145
{...{

0 commit comments

Comments
 (0)