]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-21565 Migrate Global Footer to the new UI
authorJeremy Davis <jeremy.davis@sonarsource.com>
Mon, 5 Feb 2024 15:26:24 +0000 (16:26 +0100)
committersonartech <sonartech@sonarsource.com>
Tue, 6 Feb 2024 16:38:17 +0000 (16:38 +0000)
server/sonar-web/design-system/src/helpers/constants.ts
server/sonar-web/src/main/js/app/components/GlobalFooter.tsx
server/sonar-web/src/main/js/app/components/GlobalFooterBranding.tsx
server/sonar-web/src/main/js/app/styles/components/page.css
server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx
server/sonar-web/src/main/js/apps/issues/sidebar/Sidebar.tsx
server/sonar-web/src/main/js/apps/projects/components/AllProjects.tsx

index b7dbb6371313aceade0ab8aa84cf19dbe8ed78f6..0b18515f3e5bde03f86aba449e7095e2836af9ee 100644 (file)
@@ -63,7 +63,7 @@ export const LAYOUT_PROJECT_NAV_HEIGHT = 108;
 export const LAYOUT_LOGO_MARGIN_RIGHT = 45;
 export const LAYOUT_LOGO_MAX_HEIGHT = 40;
 export const LAYOUT_LOGO_MAX_WIDTH = 150;
-export const LAYOUT_FOOTER_HEIGHT = 60;
+export const LAYOUT_FOOTER_HEIGHT = 69;
 export const LAYOUT_NOTIFICATIONSBAR_WIDTH = 350;
 
 export const CORE_CONCEPTS_WIDTH = 350;
index 2a613a95828b809cd37a916e327b7b11170a9d4c..adee7ea7bcfc0f5ab6367bcb70d1a45147474284 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
-import { LargeCenteredLayout } from 'design-system';
+import styled from '@emotion/styled';
+import {
+  DiscreetLink,
+  FlagMessage,
+  LAYOUT_VIEWPORT_MIN_WIDTH,
+  PageContentFontWrapper,
+  themeBorder,
+  themeColor,
+} from 'design-system';
 import * as React from 'react';
-import DocLink from '../../components/common/DocLink';
 import InstanceMessage from '../../components/common/InstanceMessage';
-import Link from '../../components/common/Link';
-import { Alert } from '../../components/ui/Alert';
+import { useDocUrl } from '../../helpers/docs';
 import { getEdition } from '../../helpers/editions';
 import { translate, translateWithParameters } from '../../helpers/l10n';
 import GlobalFooterBranding from './GlobalFooterBranding';
@@ -36,62 +42,66 @@ export default function GlobalFooter({ hideLoggedInInfo }: GlobalFooterProps) {
   const appState = React.useContext(AppStateContext);
   const currentEdition = appState?.edition && getEdition(appState.edition);
 
+  const docUrl = useDocUrl();
+
   return (
-    <div className="page-footer page-container" id="footer">
-      <LargeCenteredLayout className=" sw-flex sw-flex-col sw-items-center">
+    <StyledFooter className="sw-p-6" id="footer">
+      <PageContentFontWrapper className="sw-body-sm sw-h-full sw-flex sw-flex-col sw-items-stretch">
         {appState?.productionDatabase === false && (
-          <Alert display="inline" id="evaluation_warning" variant="warning">
-            <p className="big">{translate('footer.production_database_warning')}</p>
+          <FlagMessage className="sw-mb-4" id="evaluation_warning" variant="warning">
             <p>
+              <span className="sw-body-md-highlight">
+                {translate('footer.production_database_warning')}
+              </span>
+              <br />
               <InstanceMessage message={translate('footer.production_database_explanation')} />
             </p>
-          </Alert>
+          </FlagMessage>
         )}
 
-        <GlobalFooterBranding />
+        <div className="sw-flex sw-justify-between sw-items-center">
+          <GlobalFooterBranding />
 
-        <ul className="page-footer-menu">
-          {!hideLoggedInInfo && currentEdition && (
-            <li className="page-footer-menu-item">{currentEdition.name}</li>
-          )}
-          {!hideLoggedInInfo && appState?.version && (
-            <li className="page-footer-menu-item">
-              {translateWithParameters('footer.version_x', appState.version)}
+          <ul className="sw-flex sw-items-center sw-gap-3 sw-ml-4">
+            {!hideLoggedInInfo && currentEdition && <li>{currentEdition.name}</li>}
+            {!hideLoggedInInfo && appState?.version && (
+              <li className="sw-code">
+                {translateWithParameters('footer.version_x', appState.version)}
+              </li>
+            )}
+            <li>
+              <DiscreetLink to="https://www.gnu.org/licenses/lgpl-3.0.txt">
+                {translate('footer.license')}
+              </DiscreetLink>
+            </li>
+            <li>
+              <DiscreetLink to="https://community.sonarsource.com/c/help/sq">
+                {translate('footer.community')}
+              </DiscreetLink>
             </li>
-          )}
-          <li className="page-footer-menu-item">
-            <a
-              href="https://www.gnu.org/licenses/lgpl-3.0.txt"
-              rel="noopener noreferrer"
-              target="_blank"
-            >
-              {translate('footer.license')}
-            </a>
-          </li>
-          <li className="page-footer-menu-item">
-            <a
-              href="https://community.sonarsource.com/c/help/sq"
-              rel="noopener noreferrer"
-              target="_blank"
-            >
-              {translate('footer.community')}
-            </a>
-          </li>
-          <li className="page-footer-menu-item">
-            <DocLink to="/">{translate('footer.documentation')}</DocLink>
-          </li>
-          <li className="page-footer-menu-item">
-            <DocLink to="/instance-administration/plugin-version-matrix/">
-              {translate('footer.plugins')}
-            </DocLink>
-          </li>
-          {!hideLoggedInInfo && (
-            <li className="page-footer-menu-item">
-              <Link to="/web_api">{translate('footer.web_api')}</Link>
+            <li>
+              <DiscreetLink to={docUrl('/')}>{translate('footer.documentation')}</DiscreetLink>
             </li>
-          )}
-        </ul>
-      </LargeCenteredLayout>
-    </div>
+            <li>
+              <DiscreetLink to={docUrl('/instance-administration/plugin-version-matrix/')}>
+                {translate('footer.plugins')}
+              </DiscreetLink>
+            </li>
+            {!hideLoggedInInfo && (
+              <li>
+                <DiscreetLink to="/web_api">{translate('footer.web_api')}</DiscreetLink>
+              </li>
+            )}
+          </ul>
+        </div>
+      </PageContentFontWrapper>
+    </StyledFooter>
   );
 }
+
+const StyledFooter = styled.div`
+  box-sizing: border-box;
+  min-width: ${LAYOUT_VIEWPORT_MIN_WIDTH}px;
+  border-top: ${themeBorder('default')};
+  background-color: ${themeColor('backgroundSecondary')};
+`;
index 6b3609084969840a8c6ffefc4ec7b0ab09e3bcb9..b9a5ddbf252e9206d9a91a33789fbd0789bcbcba 100644 (file)
@@ -17,6 +17,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+import { DiscreetLink } from 'design-system';
 import * as React from 'react';
 import { isOfficial } from '../../helpers/system';
 
@@ -26,30 +27,21 @@ export default function GlobalFooterBranding() {
   return official ? (
     <div>
       SonarQube&trade; technology is powered by{' '}
-      <a href="https://www.sonarsource.com" rel="noopener noreferrer" target="_blank">
-        SonarSource SA
-      </a>
+      <DiscreetLink to="https://www.sonarsource.com">SonarSource SA</DiscreetLink>
     </div>
   ) : (
     <div>
       This application is based on{' '}
-      <a
-        href="https://www.sonarsource.com/products/sonarqube/?referrer=sonarqube"
-        rel="noopener noreferrer"
-        target="_blank"
+      <DiscreetLink
+        to="https://www.sonarsource.com/products/sonarqube/?referrer=sonarqube"
         title="SonarQube™"
       >
         SonarQube™
-      </a>{' '}
+      </DiscreetLink>{' '}
       but is <strong>not</strong> an official version provided by{' '}
-      <a
-        href="https://www.sonarsource.com"
-        rel="noopener noreferrer"
-        target="_blank"
-        title="SonarSource SA"
-      >
+      <DiscreetLink to="https://www.sonarsource.com" title="SonarSource SA">
         SonarSource SA
-      </a>
+      </DiscreetLink>
       .
     </div>
   );
index 61910dc6b45846bd9af7289b00da47c7722c3f52..812f7cf6cc90a85a5c3a58ea320f9604fc0988ea 100644 (file)
   margin-top: 6px;
 }
 
-.page-footer {
-  min-height: 60px;
-  padding: 10px;
-  line-height: 1.5;
-  border-top: 1px solid var(--barBorderColor);
-  box-sizing: border-box;
-  background-color: var(--barBackgroundColor);
-  color: #595959;
-  font-size: var(--smallFontSize);
-  text-align: center;
-}
-
-.sidebar-page #footer > div {
-  padding-left: 410px;
-}
-
-.sidebar-page #footer > div div,
-.sidebar-page #footer > div .page-footer-menu {
-  max-width: 980px;
-}
-
-.page-footer-menu-item {
-  display: inline-block;
-}
-
-.page-footer-menu-item + .page-footer-menu-item::before {
-  content: '-';
-  padding: 0 calc(0.5 * var(--gridSize));
-  user-select: none;
-}
-
 .page-with-sidebar {
   display: flex;
 }
   padding-right: 20px;
 }
 
-@media (min-width: 1920px) {
-  .sidebar-page #footer > div {
-    padding-left: 500px;
-  }
-}
-
 @media (max-width: 1320px) {
   .layout-page-side-outer {
     width: 300px;
index 1b1573006e6e89e873393b350b86d5fa089ba7c5..f712711fcd73218d371e19d5edd27e401f329d1a 100644 (file)
@@ -1093,7 +1093,7 @@ export class App extends React.PureComponent<Props, State> {
               aria-label={openIssue ? translate('list_of_issues') : translate('filters')}
               data-testid="issues-nav-bar"
               className="issues-nav-bar sw-overflow-y-auto issue-filters-list"
-              style={{ height: `calc((100vh - ${top}px) - 60px)` }} // 60px (footer)
+              style={{ height: `calc((100vh - ${top}px) - ${LAYOUT_FOOTER_HEIGHT}px)` }}
             >
               <div className="sw-w-[300px] lg:sw-w-[390px] sw-h-full">
                 <A11ySkipTarget
index cb994ed1c529b91186958345e1d30300bb6b5f6a..1a464436c81db8b87281be7a05cce60ec0b96ba5 100644 (file)
@@ -382,17 +382,19 @@ export class SidebarClass extends React.PureComponent<Props> {
 
                 <BasicSeparator className="sw-my-4" />
 
-                <AuthorFacet
-                  author={query.author}
-                  component={component}
-                  fetching={this.props.loadingFacets.author === true}
-                  loadSearchResultCount={this.props.loadSearchResultCount}
-                  onChange={this.props.onFilterChange}
-                  onToggle={this.props.onFacetToggle}
-                  open={!!openFacets.author}
-                  query={query}
-                  stats={facets.author}
-                />
+                <div className="sw-mb-4">
+                  <AuthorFacet
+                    author={query.author}
+                    component={component}
+                    fetching={this.props.loadingFacets.author === true}
+                    loadSearchResultCount={this.props.loadSearchResultCount}
+                    onChange={this.props.onFilterChange}
+                    onToggle={this.props.onFacetToggle}
+                    open={!!openFacets.author}
+                    query={query}
+                    stats={facets.author}
+                  />
+                </div>
               </>
             )}
           </>
index 53e91fabb82e5460b26ed1e89c471a7698cc5d77..e57a78228587521792560358fcba031e9881520c 100644 (file)
@@ -19,6 +19,7 @@
  */
 import styled from '@emotion/styled';
 import {
+  LAYOUT_FOOTER_HEIGHT,
   LargeCenteredLayout,
   PageContentFontWrapper,
   Spinner,
@@ -235,7 +236,7 @@ export class AllProjects extends React.PureComponent<Props, State> {
           <section
             aria-label={translate('filters')}
             className="sw-overflow-y-auto project-filters-list"
-            style={{ height: `calc((100vh - ${top}px) - 60px)` }} // 60 for the footer
+            style={{ height: `calc((100vh - ${top}px) - ${LAYOUT_FOOTER_HEIGHT}px)` }}
           >
             <div className="sw-w-[300px] lg:sw-w-[390px]">
               <A11ySkipTarget