Skip to content

Commit 9ccb31b

Browse files
NiklasRamstromPrisoners of Azkaban
andauthored
Add custom content possibility to left side of topbar and top of application menu (#91)
* feat(topbar): add possibility to show custom content on left side of topbar * feat(topbar): allow custom content in top of application menu --------- Co-authored-by: Prisoners of Azkaban <healthmonitoring@axis.com>
1 parent 6f9d7c1 commit 9ccb31b

File tree

6 files changed

+54
-7
lines changed

6 files changed

+54
-7
lines changed

components/topbar/src/application-menu.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
Badge,
33
Menu,
44
MenuButton,
5+
MenuDivider,
56
MenuItem,
67
MenuList,
78
MenuPopover,
@@ -33,6 +34,7 @@ function appIcon(id: string): JSX.Element {
3334
}
3435

3536
export const ApplicationMenu = ({
37+
customContent,
3638
options,
3739
value,
3840
onChange,
@@ -43,6 +45,8 @@ export const ApplicationMenu = ({
4345
const currentSelection = options?.find(({ id }) => id === value);
4446
const isStandalone = options?.length === 1;
4547

48+
const onlyCustomContent = !options?.length && !!customContent;
49+
4650
return (
4751
<Menu>
4852
<MenuTrigger>
@@ -69,6 +73,12 @@ export const ApplicationMenu = ({
6973
</MenuTrigger>
7074
<MenuPopover>
7175
<MenuList>
76+
{customContent !== undefined && (
77+
<>
78+
{customContent}
79+
{!onlyCustomContent && <MenuDivider />}
80+
</>
81+
)}
7282
{options?.map(({ id, icon, label, beta }) => (
7383
<MenuItem
7484
data-testid={`application-menu-item-${id}`}

components/topbar/src/application-menu.types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export type ApplicationOption = {
77
};
88

99
export type ApplicationMenuProps = {
10+
customContent?: JSX.Element;
1011
options?: ApplicationOption[];
1112
value: string;
1213
onChange: (id: string) => void;

components/topbar/src/top-bar.styles.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const useTopBarStyles = makeStyles({
1616
gridTemplateColumns: "[left] auto [right] minmax(auto, max-content)",
1717
gridColumnGap: tokens.spacingHorizontalS,
1818
alignItems: "center",
19+
justifyContent: "space-between",
1920
boxSizing: "border-box",
2021
height: "46px",
2122
backgroundColor: tokens.colorNeutralBackground4,

components/topbar/src/top-bar.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import { TranslationProvider } from "./translation-provider";
99

1010
export const TopBar = forwardRef(
1111
(props: TopBarProps, ref: ForwardedRef<HTMLDivElement>) => {
12-
const { appMenu, orgMenu, profileMenu, customContent } = props;
12+
const { appMenu, orgMenu, profileMenu, customContent, leftCustomContent } =
13+
props;
1314
const styles = useTopBarStyles();
1415

1516
const rootStyle = mergeClasses(topBarClassNames.root, styles.root);
@@ -23,14 +24,23 @@ export const TopBar = forwardRef(
2324
);
2425

2526
const language = profileMenu?.language;
26-
const locale = language?.options?.find(({ id }) => id === language.value)
27-
?.id;
27+
const locale = language?.options?.find(
28+
({ id }) => id === language.value
29+
)?.id;
2830

2931
return (
3032
<TranslationProvider locale={locale}>
3133
<div className={rootStyle} ref={ref}>
3234
<div className={leftSectionStyle}>
3335
{appMenu !== undefined && <ApplicationMenu {...appMenu} />}
36+
{leftCustomContent !== undefined && (
37+
<>
38+
{appMenu !== undefined && (
39+
<Divider vertical style={{ padding: "0 4px" }} />
40+
)}
41+
{leftCustomContent}
42+
</>
43+
)}
3444
</div>
3545
<div className={rightSectionStyle}>
3646
{orgMenu !== undefined && <OrganizationMenu {...orgMenu} />}

components/topbar/src/top-bar.types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export type TopBarProps = {
66
readonly appMenu?: ApplicationMenuProps;
77
readonly children?: ReadonlyArray<never>;
88
readonly customContent?: JSX.Element;
9+
readonly leftCustomContent?: JSX.Element;
910
readonly orgMenu?: OrganizationMenuProps;
1011
readonly profileMenu?: ProfileMenuProps;
1112
};

examples/src/components/top-bar.tsx

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
TopBar,
1111
} from "@axiscommunications/fluent-topbar";
1212
import {
13+
Button,
1314
makeStyles,
1415
Menu,
1516
MenuButton,
@@ -23,8 +24,10 @@ import {
2324
BoxFilled,
2425
BoxRegular,
2526
bundleIcon,
27+
FoodApple24Regular,
2628
MailFilled,
2729
MailRegular,
30+
Megaphone24Filled,
2831
OpenRegular,
2932
QuestionCircleRegular,
3033
} from "@fluentui/react-icons";
@@ -94,19 +97,40 @@ export const Navbar = () => {
9497
alert("sign me in");
9598
}, []);
9699

97-
const onNavigateToApplication = React.useCallback((appid: string) => {
98-
setSelectedApp(appid);
99-
alert("lets navigate! => " + appid);
100-
}, [setSelectedApp]);
100+
const onNavigateToApplication = React.useCallback(
101+
(appid: string) => {
102+
setSelectedApp(appid);
103+
alert("lets navigate! => " + appid);
104+
},
105+
[setSelectedApp]
106+
);
107+
108+
const [megaman, setMegaman] = useState("Megaman");
101109

102110
return (
103111
<div className={styles.topBar}>
104112
<TopBar
105113
appMenu={{
114+
customContent: (
115+
<MenuItem icon={<FoodApple24Regular />}>
116+
Custom app menu item
117+
</MenuItem>
118+
),
106119
options: applications,
107120
value: selectedApp,
108121
onChange: onNavigateToApplication,
109122
}}
123+
leftCustomContent={
124+
<Button
125+
appearance="subtle"
126+
icon={<Megaphone24Filled />}
127+
iconPosition="before"
128+
onClick={() =>
129+
setMegaman(megaman === "Megaman" ? "Rockman" : "Megaman")}
130+
>
131+
{megaman}
132+
</Button>
133+
}
110134
customContent={
111135
<Menu>
112136
<MenuTrigger>

0 commit comments

Comments
 (0)