Skip to content

Commit 8e33ca2

Browse files
authored
feat(CompanyLogo): follow logo brand guidelines, support light mode (#981)
* feat(defaultlogo): follow logo brand guidelines * feat(CompanyLogo): support light theme backgrounds * feat(CompanyLogo): change the shape of `app.branding.fullLogo` to be consistent with CompanyLogo * feat: no longer breaking change it would probably be a useful feature to define one logo for both themes * fix(theme): use ids instead of classname * allow the width of `LogoRender` to be explicitly set
1 parent 02bf923 commit 8e33ca2

12 files changed

Lines changed: 185 additions & 239 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@red-hat-developer-hub/backstage-plugin-global-header': patch
3+
---
4+
5+
Update the Red Hat Developer Hub logo to align with the [brand guidelines](https://www.redhat.com/en/about/brand/standards/product-logos)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
'@red-hat-developer-hub/backstage-plugin-global-header': minor
3+
---
4+
5+
Updated the `CompanyLogo` component to support global headers either light or dark background colours. The light/dark mode of the logo is determined by the `theme.palette.rhdh.general.appBarBackgroundScheme` field in the theme configuration.
6+
7+
The `logo` prop now also accepts an object with `light` and `dark` properties, each containing a string URL for the logo image. If `logo` is a string, it will be used for both light and dark modes.
8+
9+
The `CompanyLogo` will prefer the `config.props.logo.[light|dark]` mount point configuration when rendering. If not provided, it will fall back to the `app.branding.fullLogo` in the app configuration.
10+
11+
Moreover, `app.branding.fullLogo` is now an object with `light` and `dark` properties, each containing a string URL for the logo image. If `app.branding.fullLogo` is a string, it will be used for both light and dark modes.
12+
13+
If neither `config.props.logo` nor `app.branding.fullLogo` is provided, the `CompanyLogo` will render the Red Hat Developer Hub logo by default.

workspaces/global-header/packages/app/src/App.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,6 @@ export default app.createRoot(
141141
<GlobalStyles
142142
styles={{
143143
html: { overflowY: 'hidden' },
144-
':root': {
145-
'--rhdh-v1-page-inset': '1.5rem',
146-
'--global-header-default-height': '64px',
147-
},
148144
}}
149145
/>
150146
<AlertDisplay />

workspaces/global-header/packages/app/src/components/Root/Root.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ const SidebarLayout = styled(Box, {
114114
export const Root = ({ children = null }: PropsWithChildren<{}>) => {
115115
return (
116116
<PageWithoutFixHeight>
117-
<div id="above-sidebar-header-container">
117+
<div id="rhdh-above-sidebar-header-container">
118118
{/* update globalHeaderMountPoints config to test Global header */}
119119
<GlobalHeaderComponent
120120
globalHeaderMountPoints={defaultGlobalHeaderComponentsMountPoints}
@@ -125,7 +125,7 @@ export const Root = ({ children = null }: PropsWithChildren<{}>) => {
125125
aboveSidebarHeaderHeight={64}
126126
>
127127
<SidebarPage>
128-
<div id="above-main-content-header-container" />
128+
<div id="rhdh-above-main-content-header-container" />
129129
<Sidebar>
130130
<SidebarGroup label="Menu" icon={<MenuIcon />}>
131131
{/* Global nav, not org-specific */}

workspaces/global-header/plugins/global-header/report.api.md

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,17 @@ import { JSX as JSX_2 } from 'react/jsx-runtime';
1212
export const ApplicationLauncherDropdown: () => JSX_2.Element;
1313

1414
// @public
15-
export const CompanyLogo: ({ logo, to }: CompanyLogoProps) => JSX_2.Element;
15+
export const CompanyLogo: ({
16+
logo,
17+
logoWidth,
18+
to,
19+
}: CompanyLogoProps) => JSX_2.Element;
1620

1721
// @public (undocumented)
1822
export interface CompanyLogoProps {
19-
// (undocumented)
2023
layout?: CSSProperties;
21-
// (undocumented)
22-
logo?: string;
23-
// (undocumented)
24+
logo?: LogoURLs;
25+
logoWidth?: number;
2426
to?: string;
2527
}
2628

@@ -169,6 +171,15 @@ export interface HeaderIconProps {
169171
size?: 'small' | 'medium' | 'large';
170172
}
171173

174+
// @public
175+
export type LogoURLs =
176+
| {
177+
light: string;
178+
dark: string;
179+
}
180+
| string
181+
| undefined;
182+
172183
// @public
173184
export const LogoutButton: ComponentType;
174185

workspaces/global-header/plugins/global-header/src/components/CompanyLogo/CompanyLogo.tsx

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,16 @@ import { Link } from '@backstage/core-components';
1818
import { configApiRef, useApi } from '@backstage/core-plugin-api';
1919
import DefaultLogo from './DefaultLogo';
2020
import Box from '@mui/material/Box';
21+
import { useAppBarBackgroundScheme } from '../../hooks/useAppBarBackgroundScheme';
2122

2223
const LogoRender = ({
2324
base64Logo,
2425
defaultLogo,
26+
width = 150,
2527
}: {
2628
base64Logo: string | undefined;
2729
defaultLogo: JSX.Element;
30+
width?: number;
2831
}) => {
2932
return base64Logo ? (
3033
<img
@@ -36,26 +39,76 @@ const LogoRender = ({
3639
maxHeight: '40px',
3740
maxWidth: '150px',
3841
}}
42+
width={width}
3943
/>
4044
) : (
4145
defaultLogo
4246
);
4347
};
4448

49+
/**
50+
* An interface representing the URLs for light and dark variants of a logo.
51+
* @public
52+
*/
53+
export type LogoURLs =
54+
| {
55+
/** The logo that will be used in global headers with a light-coloured background */
56+
light: string;
57+
/** The logo that will be used in global headers with a dark-coloured background */
58+
dark: string;
59+
}
60+
| string
61+
| undefined;
62+
4563
/**
4664
* @public
4765
*/
4866
export interface CompanyLogoProps {
49-
logo?: string;
67+
/** An object containing the logo URLs */
68+
logo?: LogoURLs;
69+
/** The route to link the logo to */
5070
to?: string;
71+
/**
72+
* The width of the logo in pixels (defaults to 150px). This prop fixes an
73+
* issue where encoded SVGs without an explicit width would not render.
74+
* You likely do not need to set this prop.
75+
*/
76+
logoWidth?: number;
77+
/** This prop is not used by this component. */
5178
layout?: CSSProperties;
5279
}
5380

54-
export const CompanyLogo = ({ logo, to = '/' }: CompanyLogoProps) => {
81+
/**
82+
* Gets a themed image based on the current theme.
83+
*/
84+
const useFullLogo = (logo: LogoURLs): string | undefined => {
85+
const appBarBackgroundScheme = useAppBarBackgroundScheme();
86+
5587
const configApi = useApi(configApiRef);
56-
const logoFullBase64URI = configApi.getOptionalString(
57-
'app.branding.fullLogo',
58-
);
88+
89+
/** The fullLogo config specified by app.branding.fullLogo */
90+
const fullLogo = configApi.getOptional<LogoURLs>('app.branding.fullLogo');
91+
92+
/** The URI of the logo specified by app.branding.fullLogo */
93+
const fullLogoURI =
94+
typeof fullLogo === 'string'
95+
? fullLogo
96+
: fullLogo?.[appBarBackgroundScheme];
97+
98+
/** The URI of the logo specified by CompanyLogo props */
99+
const propsLogoURI =
100+
typeof logo === 'string' ? logo : logo?.[appBarBackgroundScheme];
101+
102+
return propsLogoURI ?? fullLogoURI ?? undefined;
103+
};
104+
105+
export const CompanyLogo = ({
106+
logo,
107+
logoWidth,
108+
to = '/',
109+
}: CompanyLogoProps) => {
110+
const logoURL = useFullLogo(logo);
111+
59112
return (
60113
<Box
61114
sx={{
@@ -76,8 +129,9 @@ export const CompanyLogo = ({ logo, to = '/' }: CompanyLogoProps) => {
76129
}}
77130
>
78131
<LogoRender
79-
base64Logo={logo ?? logoFullBase64URI}
132+
base64Logo={logoURL}
80133
defaultLogo={<DefaultLogo />}
134+
width={logoWidth}
81135
/>
82136
</Link>
83137
</Box>

0 commit comments

Comments
 (0)