Skip to content
Merged
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
1 change: 1 addition & 0 deletions public/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
"subtitleMessage": "Looks like this page is not opened inside of the Hyperspace Portal. Contact admins for help."
},
"ShellBar": {
"betaButtonDescription": "This web app is currently in Beta, and may not ready for productive use. We're actively improving the experience and would love your feedback — your input helps shape the future of the app!",
"signOutButton": "Sign Out"
},
"CreateProjectDialog": {
Expand Down
51 changes: 51 additions & 0 deletions src/components/Core/ShellBar.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
.container {
display: flex;
align-items: center;
gap: 0.5rem;
}

.logoWrapper {
display: flex;
align-items: center;
gap: 0.25rem;
}

.logo {
height: 1.5rem;
}

.logoText {
font-weight: bold;
font-size: 1rem;
color: var(--sapTextColor);
}

.betaButton {
background-color: #FFF3CD;
color: #856404;
padding: 4px 10px;
border-radius: 12px;
border: 1px solid #FFEB99;
font-weight: bold;
font-size: 0.75rem;
height: 1.75rem;
line-height: 1;
display: flex;
align-items: center;
justify-content: center;
}

.betaContent {
display: flex;
align-items: center;
gap: 0.25rem;
}

.betaIcon {
font-size: 1rem;
color: #0A6ED1;
}

.betaText {
font-size: 0.875rem;
}
126 changes: 101 additions & 25 deletions src/components/Core/ShellBar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import {
Avatar,
Button,
ButtonDomRef,
Icon,
List,
ListItemStandard,
Popover,
Expand All @@ -9,16 +12,21 @@ import {
Ui5CustomEvent,
} from '@ui5/webcomponents-react';
import { useAuth } from 'react-oidc-context';
import { RefObject, useRef, useState } from 'react';
import { RefObject, useEffect, useRef, useState } from 'react';
import { ShellBarProfileClickEventDetail } from '@ui5/webcomponents-fiori/dist/ShellBar.js';
import PopoverPlacement from '@ui5/webcomponents/dist/types/PopoverPlacement.js';
import { useTranslation } from 'react-i18next';
import { generateInitialsForEmail } from '../Helper/GenerateInitialsForEmail';
import styles from './ShellBar.module.css';
import { ThemingParameters } from '@ui5/webcomponents-react-base';

export function ShellBarComponent() {
const auth = useAuth();
const profilePopoverRef = useRef<PopoverDomRef>(null);
const betaPopoverRef = useRef<PopoverDomRef>(null);
const [profilePopoverOpen, setProfilePopoverOpen] = useState(false);
const [betaPopoverOpen, setBetaPopoverOpen] = useState(false);
const betaButtonRef = useRef<ButtonDomRef>(null);

const onProfileClick = (
e: Ui5CustomEvent<ShellBarDomRef, ShellBarProfileClickEventDetail>,
Expand All @@ -27,24 +35,65 @@ export function ShellBarComponent() {
setProfilePopoverOpen(!profilePopoverOpen);
};

const onBetaClick = () => {
if (betaButtonRef.current) {
betaPopoverRef.current!.opener = betaButtonRef.current;
setBetaPopoverOpen(!betaPopoverOpen);
}
};

useEffect(() => {
const shellbar = document.querySelector('ui5-shellbar');
const el = shellbar?.shadowRoot?.querySelector(
'.ui5-shellbar-overflow-container-left',
);

if (el) {
(el as HTMLElement).style.backgroundColor = 'red';
}
}, []);

return (
<>
<ShellBar
logo={<img src="/logo.png" alt="MCP" />}
primaryTitle="MCP"
className={styles.TestShellbar}
profile={
<Avatar
initials={generateInitialsForEmail(auth.user?.profile.email)}
size="XS"
/>
}
startButton={
<div className={styles.container}>
<div className={styles.logoWrapper}>
<img src="/logo.png" alt="MCP" className={styles.logo} />
<span className={styles.logoText}>MCP</span>
</div>
<Button
ref={betaButtonRef}
className={styles.betaButton}
onClick={onBetaClick}
>
<span className={styles.betaContent}>
<Icon name="information" className={styles.betaIcon} />
<span className={styles.betaText}>Beta</span>
</span>
</Button>
</div>
}
onProfileClick={onProfileClick}
/>

<ProfilePopover
open={profilePopoverOpen}
setOpen={(b) => setProfilePopoverOpen(b)}
setOpen={setProfilePopoverOpen}
popoverRef={profilePopoverRef}
/>
<BetaPopover
open={betaPopoverOpen}
setOpen={setBetaPopoverOpen}
popoverRef={betaPopoverRef}
/>
</>
);
}
Expand All @@ -62,28 +111,55 @@ const ProfilePopover = ({
const { t } = useTranslation();

return (
<>
<Popover
ref={popoverRef}
placement={PopoverPlacement.Bottom}
open={open}
headerText="Profile"
onClose={() => {
setOpen(false);
<Popover
ref={popoverRef}
placement={PopoverPlacement.Bottom}
open={open}
headerText="Profile"
onClose={() => setOpen(false)}
>
<List>
<ListItemStandard
icon="log"
onClick={() => {
setOpen(false);
auth.removeUser();
}}
>
{t('ShellBar.signOutButton')}
</ListItemStandard>
</List>
</Popover>
);
};

const BetaPopover = ({
open,
setOpen,
popoverRef,
}: {
open: boolean;
setOpen: (arg0: boolean) => void;
popoverRef: RefObject<PopoverDomRef | null>;
}) => {
const { t } = useTranslation();

return (
<Popover
ref={popoverRef}
placement={PopoverPlacement.Bottom}
open={open}
onClose={() => setOpen(false)}
>
<div
style={{
padding: '1rem',
maxWidth: '250px',
fontFamily: ThemingParameters.sapFontFamily,
}}
>
<List>
<ListItemStandard
icon="log"
onClick={() => {
setOpen(false);
auth.removeUser();
}}
>
{t('ShellBar.signOutButton')}
</ListItemStandard>
</List>
</Popover>
</>
{t('ShellBar.betaButtonDescription')}
</div>
</Popover>
);
};
Loading