mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-09 01:17:06 +02:00
feat: transparent header (#9108)
This PR adds header redesign behind a feature flag
This commit is contained in:
parent
4b3b98f263
commit
25c09c3627
@ -30,6 +30,7 @@ import { CommandQuickSuggestions } from './CommandQuickSuggestions';
|
|||||||
import { CommandSearchPages } from './CommandSearchPages';
|
import { CommandSearchPages } from './CommandSearchPages';
|
||||||
import { CommandBarFeedback } from './CommandBarFeedback';
|
import { CommandBarFeedback } from './CommandBarFeedback';
|
||||||
import { RecentlyVisitedRecorder } from './RecentlyVisitedRecorder';
|
import { RecentlyVisitedRecorder } from './RecentlyVisitedRecorder';
|
||||||
|
import { useUiFlag } from 'hooks/useUiFlag';
|
||||||
|
|
||||||
export const CommandResultsPaper = styled(Paper)(({ theme }) => ({
|
export const CommandResultsPaper = styled(Paper)(({ theme }) => ({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
@ -50,16 +51,20 @@ export const CommandResultsPaper = styled(Paper)(({ theme }) => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
const StyledContainer = styled('div', {
|
const StyledContainer = styled('div', {
|
||||||
shouldForwardProp: (prop) => prop !== 'active',
|
shouldForwardProp: (prop) =>
|
||||||
|
prop !== 'active' && prop !== 'frontendHeaderRedesign',
|
||||||
})<{
|
})<{
|
||||||
active: boolean | undefined;
|
active: boolean | undefined;
|
||||||
}>(({ theme, active }) => ({
|
frontendHeaderRedesign?: boolean;
|
||||||
|
}>(({ theme, active, frontendHeaderRedesign }) => ({
|
||||||
border: `1px solid transparent`,
|
border: `1px solid transparent`,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
backgroundColor: theme.palette.background.paper,
|
backgroundColor: frontendHeaderRedesign
|
||||||
|
? theme.palette.background.application
|
||||||
|
: theme.palette.background.paper,
|
||||||
maxWidth: active ? '100%' : '400px',
|
maxWidth: active ? '100%' : '400px',
|
||||||
[theme.breakpoints.down('md')]: {
|
[theme.breakpoints.down('md')]: {
|
||||||
marginTop: theme.spacing(1),
|
marginTop: theme.spacing(1),
|
||||||
@ -97,6 +102,7 @@ interface IPageRouteInfo {
|
|||||||
|
|
||||||
export const CommandBar = () => {
|
export const CommandBar = () => {
|
||||||
const { trackEvent } = usePlausibleTracker();
|
const { trackEvent } = usePlausibleTracker();
|
||||||
|
const frontendHeaderRedesign = useUiFlag('frontendHeaderRedesign');
|
||||||
const searchInputRef = useRef<HTMLInputElement>(null);
|
const searchInputRef = useRef<HTMLInputElement>(null);
|
||||||
const searchContainerRef = useRef<HTMLInputElement>(null);
|
const searchContainerRef = useRef<HTMLInputElement>(null);
|
||||||
const [showSuggestions, setShowSuggestions] = useState(false);
|
const [showSuggestions, setShowSuggestions] = useState(false);
|
||||||
@ -293,7 +299,11 @@ export const CommandBar = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledContainer ref={searchContainerRef} active={showSuggestions}>
|
<StyledContainer
|
||||||
|
ref={searchContainerRef}
|
||||||
|
active={showSuggestions}
|
||||||
|
frontendHeaderRedesign={frontendHeaderRedesign}
|
||||||
|
>
|
||||||
<RecentlyVisitedRecorder />
|
<RecentlyVisitedRecorder />
|
||||||
<StyledSearch
|
<StyledSearch
|
||||||
sx={{
|
sx={{
|
||||||
|
@ -18,6 +18,7 @@ import { NavigationSidebar } from './NavigationSidebar/NavigationSidebar';
|
|||||||
import { MainLayoutEventTimeline } from './MainLayoutEventTimeline';
|
import { MainLayoutEventTimeline } from './MainLayoutEventTimeline';
|
||||||
import { EventTimelineProvider } from 'component/events/EventTimeline/EventTimelineProvider';
|
import { EventTimelineProvider } from 'component/events/EventTimeline/EventTimelineProvider';
|
||||||
import { NewInUnleash } from './NavigationSidebar/NewInUnleash/NewInUnleash';
|
import { NewInUnleash } from './NavigationSidebar/NewInUnleash/NewInUnleash';
|
||||||
|
import { useUiFlag } from 'hooks/useUiFlag';
|
||||||
|
|
||||||
interface IMainLayoutProps {
|
interface IMainLayoutProps {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
@ -93,6 +94,7 @@ export const MainLayout = forwardRef<HTMLDivElement, IMainLayoutProps>(
|
|||||||
({ children }, ref) => {
|
({ children }, ref) => {
|
||||||
const { uiConfig } = useUiConfig();
|
const { uiConfig } = useUiConfig();
|
||||||
const projectId = useOptionalPathParam('projectId');
|
const projectId = useOptionalPathParam('projectId');
|
||||||
|
const frontendHeaderRedesign = useUiFlag('frontendHeaderRedesign');
|
||||||
const { isChangeRequestConfiguredInAnyEnv } = useChangeRequestsEnabled(
|
const { isChangeRequestConfiguredInAnyEnv } = useChangeRequestsEnabled(
|
||||||
projectId || '',
|
projectId || '',
|
||||||
);
|
);
|
||||||
@ -103,7 +105,10 @@ export const MainLayout = forwardRef<HTMLDivElement, IMainLayoutProps>(
|
|||||||
return (
|
return (
|
||||||
<EventTimelineProvider>
|
<EventTimelineProvider>
|
||||||
<SkipNavLink />
|
<SkipNavLink />
|
||||||
<Header />
|
<ConditionallyRender
|
||||||
|
condition={!frontendHeaderRedesign}
|
||||||
|
show={<Header />}
|
||||||
|
/>
|
||||||
|
|
||||||
<SkipNavTarget />
|
<SkipNavTarget />
|
||||||
<MainLayoutContainer>
|
<MainLayoutContainer>
|
||||||
@ -119,7 +124,9 @@ export const MainLayout = forwardRef<HTMLDivElement, IMainLayoutProps>(
|
|||||||
<Box
|
<Box
|
||||||
sx={(theme) => ({
|
sx={(theme) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
mt: theme.spacing(0.25),
|
mt: frontendHeaderRedesign
|
||||||
|
? 0
|
||||||
|
: theme.spacing(0.25),
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
@ -139,6 +146,11 @@ export const MainLayout = forwardRef<HTMLDivElement, IMainLayoutProps>(
|
|||||||
minWidth: 0,
|
minWidth: 0,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={frontendHeaderRedesign}
|
||||||
|
show={<Header />}
|
||||||
|
/>
|
||||||
|
|
||||||
<MainLayoutEventTimeline />
|
<MainLayoutEventTimeline />
|
||||||
|
|
||||||
<MainLayoutContent>
|
<MainLayoutContent>
|
||||||
|
@ -16,6 +16,17 @@ import { useInitialPathname } from './useInitialPathname';
|
|||||||
import { useLastViewedProject } from 'hooks/useLastViewedProject';
|
import { useLastViewedProject } from 'hooks/useLastViewedProject';
|
||||||
import { useLastViewedFlags } from 'hooks/useLastViewedFlags';
|
import { useLastViewedFlags } from 'hooks/useLastViewedFlags';
|
||||||
import type { NewInUnleash } from './NewInUnleash/NewInUnleash';
|
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<{
|
export const MobileNavigationSidebar: FC<{
|
||||||
onClick: () => void;
|
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.
|
// 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 }) => ({
|
const StickyContainer = styled(Box)(({ theme }) => ({
|
||||||
position: 'sticky',
|
position: 'sticky',
|
||||||
@ -71,6 +102,8 @@ export const NavigationSidebar: FC<{ NewInUnleash?: typeof NewInUnleash }> = ({
|
|||||||
NewInUnleash,
|
NewInUnleash,
|
||||||
}) => {
|
}) => {
|
||||||
const { routes } = useRoutes();
|
const { routes } = useRoutes();
|
||||||
|
const celebatoryUnleash = useUiFlag('celebrateUnleash');
|
||||||
|
const frontendHeaderRedesign = useUiFlag('frontendHeaderRedesign');
|
||||||
|
|
||||||
const [mode, setMode] = useNavigationMode();
|
const [mode, setMode] = useNavigationMode();
|
||||||
const [expanded, changeExpanded] = useExpanded<'configure' | 'admin'>();
|
const [expanded, changeExpanded] = useExpanded<'configure' | 'admin'>();
|
||||||
@ -90,6 +123,49 @@ export const NavigationSidebar: FC<{ NewInUnleash?: typeof NewInUnleash }> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StretchContainer mode={mode}>
|
<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
|
<PrimaryNavigationList
|
||||||
mode={mode}
|
mode={mode}
|
||||||
onClick={setActiveItem}
|
onClick={setActiveItem}
|
||||||
|
@ -35,8 +35,13 @@ import { useUiFlag } from 'hooks/useUiFlag';
|
|||||||
import { CommandBar } from 'component/commandBar/CommandBar';
|
import { CommandBar } from 'component/commandBar/CommandBar';
|
||||||
import { HeaderEventTimelineButton } from './HeaderEventTimelineButton';
|
import { HeaderEventTimelineButton } from './HeaderEventTimelineButton';
|
||||||
|
|
||||||
const HeaderComponent = styled(AppBar)(({ theme }) => ({
|
const HeaderComponent = styled(AppBar, {
|
||||||
backgroundColor: theme.palette.background.paper,
|
shouldForwardProp: (prop) => prop !== 'frontendHeaderRedesign',
|
||||||
|
})<{ frontendHeaderRedesign?: boolean }>(
|
||||||
|
({ theme, frontendHeaderRedesign }) => ({
|
||||||
|
backgroundColor: frontendHeaderRedesign
|
||||||
|
? theme.palette.background.application
|
||||||
|
: theme.palette.background.paper,
|
||||||
padding: theme.spacing(1),
|
padding: theme.spacing(1),
|
||||||
boxShadow: 'none',
|
boxShadow: 'none',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
@ -54,7 +59,8 @@ const HeaderComponent = styled(AppBar)(({ theme }) => ({
|
|||||||
minWidth: '100%',
|
minWidth: '100%',
|
||||||
},
|
},
|
||||||
margin: '0 auto',
|
margin: '0 auto',
|
||||||
}));
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
const ContainerComponent = styled(Box)(() => ({
|
const ContainerComponent = styled(Box)(() => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@ -107,6 +113,7 @@ const Header = () => {
|
|||||||
const [openDrawer, setOpenDrawer] = useState(false);
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
const toggleDrawer = () => setOpenDrawer((prev) => !prev);
|
const toggleDrawer = () => setOpenDrawer((prev) => !prev);
|
||||||
const celebatoryUnleash = useUiFlag('celebrateUnleash');
|
const celebatoryUnleash = useUiFlag('celebrateUnleash');
|
||||||
|
const frontendHeaderRedesign = useUiFlag('frontendHeaderRedesign');
|
||||||
|
|
||||||
const routes = getRoutes();
|
const routes = getRoutes();
|
||||||
const adminRoutes = useAdminRoutes();
|
const adminRoutes = useAdminRoutes();
|
||||||
@ -123,7 +130,10 @@ const Header = () => {
|
|||||||
|
|
||||||
if (smallScreen) {
|
if (smallScreen) {
|
||||||
return (
|
return (
|
||||||
<HeaderComponent position='static'>
|
<HeaderComponent
|
||||||
|
position='static'
|
||||||
|
frontendHeaderRedesign={frontendHeaderRedesign}
|
||||||
|
>
|
||||||
<ContainerComponent>
|
<ContainerComponent>
|
||||||
<Tooltip title='Menu' arrow>
|
<Tooltip title='Menu' arrow>
|
||||||
<IconButton
|
<IconButton
|
||||||
@ -153,8 +163,14 @@ const Header = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HeaderComponent position='static'>
|
<HeaderComponent
|
||||||
|
frontendHeaderRedesign={frontendHeaderRedesign}
|
||||||
|
position='static'
|
||||||
|
>
|
||||||
<ContainerComponent>
|
<ContainerComponent>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={!frontendHeaderRedesign}
|
||||||
|
show={
|
||||||
<StyledLink to='/' sx={flexRow} aria-label='Home'>
|
<StyledLink to='/' sx={flexRow} aria-label='Home'>
|
||||||
<ThemeMode
|
<ThemeMode
|
||||||
darkmode={
|
darkmode={
|
||||||
@ -177,6 +193,8 @@ const Header = () => {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</StyledLink>
|
</StyledLink>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<StyledNav>
|
<StyledNav>
|
||||||
<StyledUserContainer>
|
<StyledUserContainer>
|
||||||
|
@ -92,6 +92,7 @@ export type UiFlags = {
|
|||||||
granularAdminPermissions?: boolean;
|
granularAdminPermissions?: boolean;
|
||||||
sortProjectRoles?: boolean;
|
sortProjectRoles?: boolean;
|
||||||
lifecycleImprovements?: boolean;
|
lifecycleImprovements?: boolean;
|
||||||
|
frontendHeaderRedesign?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface IVersionInfo {
|
export interface IVersionInfo {
|
||||||
|
@ -62,7 +62,8 @@ export type IFlagKey =
|
|||||||
| 'deltaApi'
|
| 'deltaApi'
|
||||||
| 'uniqueSdkTracking'
|
| 'uniqueSdkTracking'
|
||||||
| 'sortProjectRoles'
|
| 'sortProjectRoles'
|
||||||
| 'lifecycleImprovements';
|
| 'lifecycleImprovements'
|
||||||
|
| 'frontendHeaderRedesign';
|
||||||
|
|
||||||
export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>;
|
export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>;
|
||||||
|
|
||||||
@ -295,6 +296,10 @@ const flags: IFlags = {
|
|||||||
process.env.UNLEASH_EXPERIMENTAL_LIFECYCLE_IMPROVEMENTS,
|
process.env.UNLEASH_EXPERIMENTAL_LIFECYCLE_IMPROVEMENTS,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
|
frontendHeaderRedesign: parseEnvVarBoolean(
|
||||||
|
process.env.UNLEASH_EXPERIMENTAL_FRONTEND_HEADER_REDESIGN,
|
||||||
|
false,
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const defaultExperimentalOptions: IExperimentalOptions = {
|
export const defaultExperimentalOptions: IExperimentalOptions = {
|
||||||
|
@ -40,7 +40,6 @@ process.nextTick(async () => {
|
|||||||
embedProxyFrontend: true,
|
embedProxyFrontend: true,
|
||||||
anonymiseEventLog: false,
|
anonymiseEventLog: false,
|
||||||
responseTimeWithAppNameKillSwitch: false,
|
responseTimeWithAppNameKillSwitch: false,
|
||||||
celebrateUnleash: true,
|
|
||||||
userAccessUIEnabled: true,
|
userAccessUIEnabled: true,
|
||||||
outdatedSdksBanner: true,
|
outdatedSdksBanner: true,
|
||||||
disableShowContextFieldSelectionValues: false,
|
disableShowContextFieldSelectionValues: false,
|
||||||
@ -58,6 +57,7 @@ process.nextTick(async () => {
|
|||||||
deltaApi: true,
|
deltaApi: true,
|
||||||
uniqueSdkTracking: true,
|
uniqueSdkTracking: true,
|
||||||
lifecycleImprovements: true,
|
lifecycleImprovements: true,
|
||||||
|
frontendHeaderRedesign: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
authentication: {
|
authentication: {
|
||||||
|
Loading…
Reference in New Issue
Block a user