Skip to content

Commit 2d0be14

Browse files
committed
Omnibar: support dotcom site badge nodes
1 parent 669b1bb commit 2d0be14

6 files changed

Lines changed: 90 additions & 14 deletions

File tree

client/dashboard/app/omnibar/omnibar.tsx

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { omnibarEvents } from './events';
1414
import { OmnibarHomeIcon } from './home';
1515
import { useHelpCenterPlugin } from './plugin-help-center';
1616
import { useNotificationsPlugin } from './plugin-notifications';
17+
import { buildSiteBadgeNode } from './plugin-site-badges';
1718
import { useStatsSparklinePlugin } from './plugin-stats-sparkline';
1819
import { buildWpcomAccountNode } from './plugin-wpcom-account';
1920
import type { AppConfig } from '../context';
@@ -22,25 +23,16 @@ import type { OmnibarNodeBuilders } from '@automattic/omnibar';
2223

2324
const onClickResponsiveMenu = () => omnibarEvents.mobileMenu.emit();
2425

25-
const UNSUPPORTED_DOTCOM_NODE_IDS = new Set( [
26-
'site-plan',
27-
'site-plan-badge',
28-
'site-status-badge',
29-
] );
30-
3126
const DOTCOM_NODE_BUILDERS: OmnibarNodeBuilders = {
3227
'my-wpcom-account': buildWpcomAccountNode,
28+
'site-plan-badge': buildSiteBadgeNode,
29+
'site-status-badge': buildSiteBadgeNode,
3330
};
3431

3532
function removeUnsupportedNodes( nodes: AdminBarNode[], supports: AppConfig[ 'supports' ] ) {
36-
return nodes.filter( ( node ) => {
37-
if ( UNSUPPORTED_DOTCOM_NODE_IDS.has( node.id ) ) {
38-
return false;
39-
}
40-
// The palette is only mounted where the app supports it, so elsewhere the
41-
// admin bar's button would open nothing.
42-
return node.id !== 'command-palette' || supports.commandPalette;
43-
} );
33+
// The palette is only mounted where the app supports it, so elsewhere the
34+
// admin bar's button would open nothing.
35+
return nodes.filter( ( node ) => node.id !== 'command-palette' || supports.commandPalette );
4436
}
4537

4638
export default function OmnibarContainer( { user }: { user?: User } ) {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
.omnibar__popover {
2+
[role='menuitem']:has( .omnibar__site-badge ),
3+
.omnibar__menu-static-item:has( .omnibar__site-badge ) {
4+
min-width: 260px;
5+
}
6+
7+
.omnibar__site-badge {
8+
display: flex;
9+
flex-direction: row;
10+
align-items: center;
11+
justify-content: space-between;
12+
gap: 8px;
13+
width: 100%;
14+
}
15+
16+
.omnibar__site-badge-value {
17+
box-sizing: border-box;
18+
flex-shrink: 0;
19+
padding-inline: 8px;
20+
border-radius: 2px;
21+
background-color: rgba( 255, 255, 255, 0.15 );
22+
color: var( --omnibar-text-color );
23+
font-size: 12px;
24+
line-height: 20px;
25+
}
26+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import type { AdminBarNode, OmnibarNode } from '@automattic/omnibar';
2+
3+
import './plugin-site-badges.scss';
4+
5+
export function buildSiteBadgeNode( adminBarNode: AdminBarNode ): Partial< OmnibarNode > {
6+
const doc = new DOMParser().parseFromString( adminBarNode.title || '', 'text/html' );
7+
const info = doc.querySelector( '.wp-admin-bar__site-info' );
8+
const label = info?.querySelector( '.wp-admin-bar__site-info-label' )?.textContent?.trim();
9+
const value = info?.querySelector( '.wp-admin-bar__info-badges' )?.textContent?.trim();
10+
11+
if ( ! value ) {
12+
return {};
13+
}
14+
15+
const href = info?.getAttribute( 'href' ) ?? undefined;
16+
17+
return {
18+
title: undefined,
19+
href,
20+
interactive: !! href,
21+
render: () => (
22+
<span className="omnibar__site-badge">
23+
<span className="omnibar__site-badge-label">{ label }</span>
24+
<span className="omnibar__site-badge-value">{ value }</span>
25+
</span>
26+
),
27+
};
28+
}

packages/omnibar/src/components/omnibar-menu.scss

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
@import './variables';
2+
13
.omnibar__popover {
24
// All colors used by the Menu's internal Emotion styles read from these
35
// CSS custom properties (see node_modules/@wordpress/components/src/menu/styles.ts).
@@ -28,9 +30,28 @@
2830
padding-inline: 10px;
2931
}
3032

33+
.omnibar__menu-static-item {
34+
box-sizing: border-box;
35+
grid-column: 1 / -1;
36+
display: grid;
37+
grid-template-columns: minmax( 0, max-content ) 1fr;
38+
align-items: center;
39+
min-height: 32px;
40+
padding-block: 4px;
41+
padding-inline: 10px;
42+
color: var( --omnibar-text-color );
43+
font-size: $omnibar-font-size;
44+
line-height: 20px;
45+
46+
> * {
47+
grid-column: 2;
48+
}
49+
}
50+
3151
.omnibar__menu-group.is-secondary {
3252
grid-column: 1 / -1;
3353
margin-block-start: 8px;
54+
padding-block: 4px;
3455
background-color: var( --omnibar-secondary-group-background );
3556

3657
&:first-child {

packages/omnibar/src/components/omnibar-menu.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ function OmnibarMenuItem( { node }: { node: OmnibarNode } ) {
2727
);
2828
}
2929

30+
if ( node.interactive === false ) {
31+
return (
32+
<div className="omnibar__menu-static-item">
33+
<OmnibarNodeContent node={ node } />
34+
</div>
35+
);
36+
}
37+
3038
return (
3139
<Menu.Item render={ node.href ? <a href={ node.href } /> : undefined }>
3240
<OmnibarNodeContent node={ node } />

packages/omnibar/src/types/omnibar.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export interface OmnibarNode {
99
variant?: 'secondary';
1010
href?: string;
1111
onClick?: () => void;
12+
interactive?: boolean;
1213
meta?: SiteActionNodeMeta & UserInfoNodeMeta;
1314
render?: ( node: OmnibarNode ) => React.ReactNode;
1415
children?: OmnibarNode[];

0 commit comments

Comments
 (0)