]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-18776 New layout for project header
authorJeremy Davis <jeremy.davis@sonarsource.com>
Fri, 17 Mar 2023 15:54:45 +0000 (16:54 +0100)
committersonartech <sonartech@sonarsource.com>
Mon, 27 Mar 2023 20:03:03 +0000 (20:03 +0000)
server/sonar-web/design-system/src/components/InteractiveIcon.tsx
server/sonar-web/design-system/src/components/MainAppBar.tsx
server/sonar-web/design-system/src/components/TopBar.tsx [new file with mode: 0644]
server/sonar-web/design-system/src/components/icons/Icon.tsx
server/sonar-web/design-system/src/components/index.ts
server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.tsx
server/sonar-web/src/main/js/app/components/nav/component/HeaderMeta.tsx
server/sonar-web/src/main/js/components/controls/HomePageSelect.tsx

index 03bbe3bdf6ef5d1744e6d4443ef7555e714d4cab..0a9b068bd4818eea55783630cdbfa8bc77bb1937 100644 (file)
@@ -50,7 +50,6 @@ export interface InteractiveIconProps {
 export class InteractiveIconBase extends React.PureComponent<InteractiveIconProps> {
   handleClick = (event: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => {
     const { disabled, onClick, stopPropagation = true } = this.props;
-    event.currentTarget.blur();
 
     if (stopPropagation) {
       event.stopPropagation();
index 97303a001589c83231a93cc8be14ba06ede2a2d3..6de796006c203ce05b2cd8d029b254ee5ddfaf78 100644 (file)
@@ -37,8 +37,8 @@ const MainAppBarDiv = styled.div`
   ${tw`sw-flex`};
   ${tw`sw-items-center`};
   ${tw`sw-left-0`};
-  ${tw`sw-px-6`};
   ${tw`sw-right-0`};
+  ${tw`sw-px-6`};
   ${tw`sw-w-full`};
   ${tw`sw-box-border`};
   ${tw`sw-z-global-navbar`};
diff --git a/server/sonar-web/design-system/src/components/TopBar.tsx b/server/sonar-web/design-system/src/components/TopBar.tsx
new file mode 100644 (file)
index 0000000..a35bd83
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import styled from '@emotion/styled';
+import { DetailedHTMLProps, HTMLAttributes, PropsWithChildren } from 'react';
+import tw from 'twin.macro';
+import { LAYOUT_GLOBAL_NAV_HEIGHT } from '../helpers';
+import { themeColor, themeContrast } from '../helpers/theme';
+
+interface Props {
+  id?: string;
+}
+
+export function TopBar({
+  children,
+  ...props
+}: PropsWithChildren<Props> & DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>) {
+  return (
+    <BaseStyle style={{ top: LAYOUT_GLOBAL_NAV_HEIGHT }} {...props}>
+      {children}
+    </BaseStyle>
+  );
+}
+
+const BaseStyle = styled.nav`
+  ${tw`sw-sticky`}
+  ${tw`sw-z-top-navbar`}
+  ${tw`sw-px-6 sw-pt-4`}
+  ${tw`sw-font-sans`}
+  ${tw`sw-text-sm`}
+
+  background-color: ${themeColor('backgroundPrimary')};
+  color: ${themeContrast('backgroundPrimary')};
+`;
index 0f5f743f4d42523846146858dc3d1359d0b28669..5edea8c38c05aa7f5718ba83e99c7ee0dd4c2987 100644 (file)
@@ -71,6 +71,7 @@ export function OcticonHoc(
 ): React.ComponentType<IconProps> {
   function IconWrapper({ fill, ...props }: IconProps) {
     const theme = useTheme();
+
     return (
       <WrappedOcticon
         fill={fill && themeColor(fill)({ theme })}
index 452c570433e26845ab8b36e45378092345c37e8b..67b83f5d7afe45189fab7f246bbb2cb29bd0887e 100644 (file)
@@ -37,3 +37,4 @@ export * from './popups';
 export * from './SonarQubeLogo';
 export * from './Text';
 export { default as Tooltip } from './Tooltip';
+export { TopBar } from './TopBar';
index 8ca22c7edfbccae708270d303a6b0074bce4fd75..785922bdb95472cf1b3ca27319fe219401981126 100644 (file)
@@ -17,9 +17,8 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
-import classNames from 'classnames';
+import { TopBar } from 'design-system';
 import * as React from 'react';
-import ContextNavBar from '../../../../components/ui/ContextNavBar';
 import { translate } from '../../../../helpers/l10n';
 import {
   ProjectAlmBindingConfigurationErrors,
@@ -101,18 +100,8 @@ export default function ComponentNav(props: ComponentNavProps) {
   }
 
   return (
-    <ContextNavBar
-      height={contextNavHeight}
-      id="context-navigation"
-      label={translate('qualifier', component.qualifier)}
-      notif={<>{prDecoNotifComponent}</>}
-    >
-      <div
-        className={classNames('display-flex-center display-flex-space-between', {
-          'padded-bottom little-padded-top': warnings.length === 0,
-          'little-padded-bottom': warnings.length > 0,
-        })}
-      >
+    <TopBar id="context-navigation" aria-label={translate('qualifier', component.qualifier)}>
+      <div className="sw-flex sw-justify-between">
         <Header
           branchLikes={branchLikes}
           component={component}
@@ -143,7 +132,9 @@ export default function ComponentNav(props: ComponentNavProps) {
       />
       <InfoDrawer
         displayed={displayProjectInfo}
-        onClose={() => setDisplayProjectInfo(false)}
+        onClose={() => {
+          setDisplayProjectInfo(false);
+        }}
         top={globalNavHeightRaw + contextNavHeight}
       >
         <ProjectInformation
@@ -152,6 +143,7 @@ export default function ComponentNav(props: ComponentNavProps) {
           onComponentChange={props.onComponentChange}
         />
       </InfoDrawer>
-    </ContextNavBar>
+      {prDecoNotifComponent}
+    </TopBar>
   );
 }
index 1cff50e993b1f09d40eae46aa109b374eddcbc26..f706073a9de3dcce8f2f9977e9ea465bd3ad133e 100644 (file)
@@ -76,7 +76,7 @@ export function HeaderMeta(props: HeaderMetaProps) {
         </span>
       )}
       {isLoggedIn(currentUser) && currentPage !== undefined && !isPullRequest(branchLike) && (
-        <HomePageSelect className="sw-ml-4" currentPage={currentPage} />
+        <HomePageSelect className="sw-ml-2" currentPage={currentPage} />
       )}
     </div>
   );
index cb65d92527a1d421a06d0632ed8c611fba3f921e..18d523634927423607a5d9fe8d403c3631ed0427 100644 (file)
@@ -18,7 +18,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import classNames from 'classnames';
-import { BareButton, HomeFillIcon, HomeIcon, Tooltip } from 'design-system';
+import { DiscreetInteractiveIcon, HomeFillIcon, HomeIcon, Tooltip } from 'design-system';
 import * as React from 'react';
 import { setHomePage } from '../../api/users';
 import { CurrentUserContextInterface } from '../../app/components/current-user/CurrentUserContext';
@@ -73,19 +73,18 @@ export class HomePageSelect extends React.PureComponent<Props> {
         {isDefault ? (
           <span
             aria-label={tooltip}
-            className={classNames('display-inline-block', className)}
+            className={classNames('sw-inline-block', className)}
             role="img"
           >
             <HomeFillIcon />
           </span>
         ) : (
-          <BareButton
+          <DiscreetInteractiveIcon
             aria-label={tooltip}
             className={className}
+            Icon={isChecked ? HomeFillIcon : HomeIcon}
             onClick={isChecked ? this.handleReset : this.handleClick}
-          >
-            {isChecked ? <HomeFillIcon /> : <HomeIcon />}
-          </BareButton>
+          />
         )}
       </Tooltip>
     );