1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-05-31 01:16:01 +02:00

feat: transparent header (#9108)

This PR adds header redesign behind a feature flag
This commit is contained in:
Fredrik Strand Oseberg 2025-01-17 09:45:45 +01:00 committed by GitHub
parent 4b3b98f263
commit 25c09c3627
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 172 additions and 50 deletions

View File

@ -30,6 +30,7 @@ import { CommandQuickSuggestions } from './CommandQuickSuggestions';
import { CommandSearchPages } from './CommandSearchPages';
import { CommandBarFeedback } from './CommandBarFeedback';
import { RecentlyVisitedRecorder } from './RecentlyVisitedRecorder';
import { useUiFlag } from 'hooks/useUiFlag';
export const CommandResultsPaper = styled(Paper)(({ theme }) => ({
position: 'absolute',
@ -50,16 +51,20 @@ export const CommandResultsPaper = styled(Paper)(({ theme }) => ({
}));
const StyledContainer = styled('div', {
shouldForwardProp: (prop) => prop !== 'active',
shouldForwardProp: (prop) =>
prop !== 'active' && prop !== 'frontendHeaderRedesign',
})<{
active: boolean | undefined;
}>(({ theme, active }) => ({
frontendHeaderRedesign?: boolean;
}>(({ theme, active, frontendHeaderRedesign }) => ({
border: `1px solid transparent`,
display: 'flex',
flexGrow: 1,
alignItems: 'center',
position: 'relative',
backgroundColor: theme.palette.background.paper,
backgroundColor: frontendHeaderRedesign
? theme.palette.background.application
: theme.palette.background.paper,
maxWidth: active ? '100%' : '400px',
[theme.breakpoints.down('md')]: {
marginTop: theme.spacing(1),
@ -97,6 +102,7 @@ interface IPageRouteInfo {
export const CommandBar = () => {
const { trackEvent } = usePlausibleTracker();
const frontendHeaderRedesign = useUiFlag('frontendHeaderRedesign');
const searchInputRef = useRef<HTMLInputElement>(null);
const searchContainerRef = useRef<HTMLInputElement>(null);
const [showSuggestions, setShowSuggestions] = useState(false);
@ -293,7 +299,11 @@ export const CommandBar = () => {
};
return (
<StyledContainer ref={searchContainerRef} active={showSuggestions}>
<StyledContainer
ref={searchContainerRef}
active={showSuggestions}
frontendHeaderRedesign={frontendHeaderRedesign}
>
<RecentlyVisitedRecorder />
<StyledSearch
sx={{

View File

@ -18,6 +18,7 @@ import { NavigationSidebar } from './NavigationSidebar/NavigationSidebar';
import { MainLayoutEventTimeline } from './MainLayoutEventTimeline';
import { EventTimelineProvider } from 'component/events/EventTimeline/EventTimelineProvider';
import { NewInUnleash } from './NavigationSidebar/NewInUnleash/NewInUnleash';
import { useUiFlag } from 'hooks/useUiFlag';
interface IMainLayoutProps {
children: ReactNode;
@ -93,6 +94,7 @@ export const MainLayout = forwardRef<HTMLDivElement, IMainLayoutProps>(
({ children }, ref) => {
const { uiConfig } = useUiConfig();
const projectId = useOptionalPathParam('projectId');
const frontendHeaderRedesign = useUiFlag('frontendHeaderRedesign');
const { isChangeRequestConfiguredInAnyEnv } = useChangeRequestsEnabled(
projectId || '',
);
@ -103,7 +105,10 @@ export const MainLayout = forwardRef<HTMLDivElement, IMainLayoutProps>(
return (
<EventTimelineProvider>
<SkipNavLink />
<Header />
<ConditionallyRender
condition={!frontendHeaderRedesign}
show={<Header />}
/>
<SkipNavTarget />
<MainLayoutContainer>
@ -119,7 +124,9 @@ export const MainLayout = forwardRef<HTMLDivElement, IMainLayoutProps>(
<Box
sx={(theme) => ({
display: 'flex',
mt: theme.spacing(0.25),
mt: frontendHeaderRedesign
? 0
: theme.spacing(0.25),
})}
>
<ConditionallyRender
@ -139,6 +146,11 @@ export const MainLayout = forwardRef<HTMLDivElement, IMainLayoutProps>(
minWidth: 0,
}}
>
<ConditionallyRender
condition={frontendHeaderRedesign}
show={<Header />}
/>
<MainLayoutEventTimeline />
<MainLayoutContent>

View File

@ -16,6 +16,17 @@ import { useInitialPathname } from './useInitialPathname';
import { useLastViewedProject } from 'hooks/useLastViewedProject';
import { useLastViewedFlags } from 'hooks/useLastViewedFlags';
import type { NewInUnleash } from './NewInUnleash/NewInUnleash';
import { ThemeMode } from 'component/common/ThemeMode/ThemeMode';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { flexRow, focusable } from 'themes/themeStyles';
import { ReactComponent as UnleashLogo } from 'assets/img/logoDarkWithText.svg';
import { ReactComponent as UnleashLogoWhite } from 'assets/img/logoWithWhiteText.svg';
import { ReactComponent as CelebatoryUnleashLogo } from 'assets/img/unleashHoliday.svg';
import { ReactComponent as CelebatoryUnleashLogoWhite } from 'assets/img/unleashHolidayDark.svg';
import { ReactComponent as LogoOnlyWhite } from 'assets/img/logo.svg';
import { ReactComponent as LogoOnly } from 'assets/img/logoDark.svg';
import { useUiFlag } from 'hooks/useUiFlag';
import { Link } from 'react-router-dom';
export const MobileNavigationSidebar: FC<{
onClick: () => void;
@ -57,6 +68,26 @@ export const StretchContainer = styled(Box)<{ mode: string }>(
}),
);
const StyledLink = styled(Link)(({ theme }) => focusable(theme));
const StyledUnleashLogoWhite = styled(UnleashLogoWhite)({ width: '150px' });
const StyledUnleashLogo = styled(UnleashLogo)({ width: '150px' });
const StyledCelebatoryLogo = styled(CelebatoryUnleashLogo)({ width: '150px' });
const StyledUnleashLogoOnly = styled(LogoOnly)(({ theme }) => ({
width: '58px',
marginTop: theme.spacing(0.5),
margin: '0 auto',
}));
const StyledUnleashLogoOnlyWhite = styled(LogoOnlyWhite)(({ theme }) => ({
width: '37px',
marginTop: theme.spacing(1),
margin: '0 auto',
}));
// This component is needed when the sticky item could overlap with nav items. You can replicate it on a short screen.
const StickyContainer = styled(Box)(({ theme }) => ({
position: 'sticky',
@ -71,6 +102,8 @@ export const NavigationSidebar: FC<{ NewInUnleash?: typeof NewInUnleash }> = ({
NewInUnleash,
}) => {
const { routes } = useRoutes();
const celebatoryUnleash = useUiFlag('celebrateUnleash');
const frontendHeaderRedesign = useUiFlag('frontendHeaderRedesign');
const [mode, setMode] = useNavigationMode();
const [expanded, changeExpanded] = useExpanded<'configure' | 'admin'>();
@ -90,6 +123,49 @@ export const NavigationSidebar: FC<{ NewInUnleash?: typeof NewInUnleash }> = ({
return (
<StretchContainer mode={mode}>
<ConditionallyRender
condition={frontendHeaderRedesign}
show={
<ConditionallyRender
condition={mode === 'full'}
show={
<StyledLink to='/' sx={flexRow} aria-label='Home'>
<ThemeMode
darkmode={
<ConditionallyRender
condition={celebatoryUnleash}
show={
<CelebatoryUnleashLogoWhite />
}
elseShow={
<StyledUnleashLogoWhite aria-label='Unleash logo' />
}
/>
}
lightmode={
<ConditionallyRender
condition={celebatoryUnleash}
show={<StyledCelebatoryLogo />}
elseShow={
<StyledUnleashLogo aria-label='Unleash logo' />
}
/>
}
/>
</StyledLink>
}
elseShow={
<StyledLink to='/' sx={flexRow} aria-label='Home'>
<ThemeMode
darkmode={<StyledUnleashLogoOnlyWhite />}
lightmode={<StyledUnleashLogoOnly />}
/>
</StyledLink>
}
/>
}
/>
<PrimaryNavigationList
mode={mode}
onClick={setActiveItem}

View File

@ -35,26 +35,32 @@ import { useUiFlag } from 'hooks/useUiFlag';
import { CommandBar } from 'component/commandBar/CommandBar';
import { HeaderEventTimelineButton } from './HeaderEventTimelineButton';
const HeaderComponent = styled(AppBar)(({ theme }) => ({
backgroundColor: theme.palette.background.paper,
padding: theme.spacing(1),
boxShadow: 'none',
position: 'relative',
zIndex: 300,
paddingRight: theme.spacing(9),
[theme.breakpoints.down('lg')]: {
paddingLeft: theme.spacing(1),
paddingRight: theme.spacing(1),
},
[theme.breakpoints.down(1024)]: {
marginLeft: 0,
marginRight: 0,
},
[theme.breakpoints.down('sm')]: {
minWidth: '100%',
},
margin: '0 auto',
}));
const HeaderComponent = styled(AppBar, {
shouldForwardProp: (prop) => prop !== 'frontendHeaderRedesign',
})<{ frontendHeaderRedesign?: boolean }>(
({ theme, frontendHeaderRedesign }) => ({
backgroundColor: frontendHeaderRedesign
? theme.palette.background.application
: theme.palette.background.paper,
padding: theme.spacing(1),
boxShadow: 'none',
position: 'relative',
zIndex: 300,
paddingRight: theme.spacing(9),
[theme.breakpoints.down('lg')]: {
paddingLeft: theme.spacing(1),
paddingRight: theme.spacing(1),
},
[theme.breakpoints.down(1024)]: {
marginLeft: 0,
marginRight: 0,
},
[theme.breakpoints.down('sm')]: {
minWidth: '100%',
},
margin: '0 auto',
}),
);
const ContainerComponent = styled(Box)(() => ({
display: 'flex',
@ -107,6 +113,7 @@ const Header = () => {
const [openDrawer, setOpenDrawer] = useState(false);
const toggleDrawer = () => setOpenDrawer((prev) => !prev);
const celebatoryUnleash = useUiFlag('celebrateUnleash');
const frontendHeaderRedesign = useUiFlag('frontendHeaderRedesign');
const routes = getRoutes();
const adminRoutes = useAdminRoutes();
@ -123,7 +130,10 @@ const Header = () => {
if (smallScreen) {
return (
<HeaderComponent position='static'>
<HeaderComponent
position='static'
frontendHeaderRedesign={frontendHeaderRedesign}
>
<ContainerComponent>
<Tooltip title='Menu' arrow>
<IconButton
@ -153,30 +163,38 @@ const Header = () => {
}
return (
<HeaderComponent position='static'>
<HeaderComponent
frontendHeaderRedesign={frontendHeaderRedesign}
position='static'
>
<ContainerComponent>
<StyledLink to='/' sx={flexRow} aria-label='Home'>
<ThemeMode
darkmode={
<ConditionallyRender
condition={celebatoryUnleash}
show={<CelebatoryUnleashLogoWhite />}
elseShow={
<StyledUnleashLogoWhite aria-label='Unleash logo' />
<ConditionallyRender
condition={!frontendHeaderRedesign}
show={
<StyledLink to='/' sx={flexRow} aria-label='Home'>
<ThemeMode
darkmode={
<ConditionallyRender
condition={celebatoryUnleash}
show={<CelebatoryUnleashLogoWhite />}
elseShow={
<StyledUnleashLogoWhite aria-label='Unleash logo' />
}
/>
}
lightmode={
<ConditionallyRender
condition={celebatoryUnleash}
show={<StyledCelebatoryLogo />}
elseShow={
<StyledUnleashLogo aria-label='Unleash logo' />
}
/>
}
/>
}
lightmode={
<ConditionallyRender
condition={celebatoryUnleash}
show={<StyledCelebatoryLogo />}
elseShow={
<StyledUnleashLogo aria-label='Unleash logo' />
}
/>
}
/>
</StyledLink>
</StyledLink>
}
/>
<StyledNav>
<StyledUserContainer>

View File

@ -92,6 +92,7 @@ export type UiFlags = {
granularAdminPermissions?: boolean;
sortProjectRoles?: boolean;
lifecycleImprovements?: boolean;
frontendHeaderRedesign?: boolean;
};
export interface IVersionInfo {

View File

@ -62,7 +62,8 @@ export type IFlagKey =
| 'deltaApi'
| 'uniqueSdkTracking'
| 'sortProjectRoles'
| 'lifecycleImprovements';
| 'lifecycleImprovements'
| 'frontendHeaderRedesign';
export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>;
@ -295,6 +296,10 @@ const flags: IFlags = {
process.env.UNLEASH_EXPERIMENTAL_LIFECYCLE_IMPROVEMENTS,
false,
),
frontendHeaderRedesign: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_FRONTEND_HEADER_REDESIGN,
false,
),
};
export const defaultExperimentalOptions: IExperimentalOptions = {

View File

@ -40,7 +40,6 @@ process.nextTick(async () => {
embedProxyFrontend: true,
anonymiseEventLog: false,
responseTimeWithAppNameKillSwitch: false,
celebrateUnleash: true,
userAccessUIEnabled: true,
outdatedSdksBanner: true,
disableShowContextFieldSelectionValues: false,
@ -58,6 +57,7 @@ process.nextTick(async () => {
deltaApi: true,
uniqueSdkTracking: true,
lifecycleImprovements: true,
frontendHeaderRedesign: true,
},
},
authentication: {