Browse Source

SONAR-21235 Add shadow to main app bar and separator to project list sticky header (#10625)

tags/10.5.0.89998
Ismail Cherri 2 months ago
parent
commit
68767ffafb

+ 22
- 4
server/sonar-web/design-system/src/components/MainAppBar.tsx View File

@@ -17,7 +17,10 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { throttle } from 'lodash';
import React from 'react';
import tw from 'twin.macro';
import {
LAYOUT_GLOBAL_NAV_HEIGHT,
@@ -25,11 +28,12 @@ import {
LAYOUT_LOGO_MAX_HEIGHT,
LAYOUT_LOGO_MAX_WIDTH,
LAYOUT_VIEWPORT_MIN_WIDTH,
THROTTLE_SCROLL_DELAY,
} from '../helpers/constants';
import { themeBorder, themeColor, themeContrast } from '../helpers/theme';
import { themeBorder, themeColor, themeContrast, themeShadow } from '../helpers/theme';
import { BaseLink } from './Link';

const MainAppBarDiv = styled.div`
const MainAppBarHeader = styled.header`
${tw`sw-flex`};
${tw`sw-items-center`};
${tw`sw-px-6`};
@@ -68,14 +72,28 @@ export function MainAppBar({
children,
Logo,
}: React.PropsWithChildren<{ Logo: React.ElementType }>) {
const theme = useTheme();
const [boxShadow, setBoxShadow] = React.useState('none');

React.useEffect(() => {
const handleScroll = throttle(() => {
setBoxShadow(document.documentElement?.scrollTop > 0 ? themeShadow('md')({ theme }) : 'none');
}, THROTTLE_SCROLL_DELAY);

document.addEventListener('scroll', handleScroll);
return () => {
document.removeEventListener('scroll', handleScroll);
};
}, [theme]);

return (
<MainAppBarDiv>
<MainAppBarHeader style={{ boxShadow }}>
<MainAppBarNavLogoDiv>
<MainAppBarNavLogoLink to="/">
<Logo />
</MainAppBarNavLogoLink>
</MainAppBarNavLogoDiv>
<MainAppBarNavRightDiv>{children}</MainAppBarNavRightDiv>
</MainAppBarDiv>
</MainAppBarHeader>
);
}

+ 16
- 1
server/sonar-web/design-system/src/components/__tests__/MainAppBar-test.tsx View File

@@ -19,7 +19,7 @@
*/
/* eslint-disable import/no-extraneous-dependencies */

import { screen } from '@testing-library/react';
import { fireEvent, screen } from '@testing-library/react';
import { MemoryRouter, Route, Routes } from 'react-router-dom';
import { LAYOUT_LOGO_MAX_HEIGHT, LAYOUT_LOGO_MAX_WIDTH } from '../../helpers/constants';
import { render } from '../../helpers/testUtils';
@@ -45,6 +45,21 @@ it('should render the logo', () => {
expect(element.container.querySelector('svg')).toHaveStyle({ height: '40px', width: '132px' });
});

it('should add shadow when scrolled', () => {
setupWithProps();

expect(screen.getByRole('banner')).toHaveStyle({
'box-shadow': 'none',
});

document.documentElement.scrollTop = 100;
fireEvent.scroll(document, { target: { scrollTop: 100 } });

expect(screen.getByRole('banner')).toHaveStyle({
'box-shadow': '0px 4px 8px -2px rgba(29,33,47,0.1),0px 2px 15px -2px rgba(29,33,47,0.06)',
});
});

function setupWithProps(
props: FCProps<typeof MainAppBar> = {
Logo: () => <img alt="logo" src="http://example.com/logo.png" />,

+ 7
- 2
server/sonar-web/src/main/js/apps/projects/components/AllProjects.tsx View File

@@ -264,7 +264,7 @@ export class AllProjects extends React.PureComponent<Props, State> {
);

renderHeader = () => (
<div className="sw-w-full" style={{ height: '120px' }}>
<PageHeaderWrapper className="sw-w-full">
<PageHeader
currentUser={this.props.currentUser}
onPerspectiveChange={this.handlePerspectiveChange}
@@ -275,7 +275,7 @@ export class AllProjects extends React.PureComponent<Props, State> {
total={this.state.total}
view={this.getView()}
/>
</div>
</PageHeaderWrapper>
);

renderMain = () => {
@@ -382,3 +382,8 @@ const SideBarStyle = styled.div`
border-right: ${themeBorder('default', 'filterbarBorder')};
background-color: ${themeColor('backgroundSecondary')};
`;

const PageHeaderWrapper = styled.div`
height: 7.5rem;
border-bottom: ${themeBorder('default', 'filterbarBorder')};
`;

+ 19
- 6
server/sonar-web/src/main/js/apps/projects/components/ProjectsList.tsx View File

@@ -18,6 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

import classNames from 'classnames';
import { Spinner } from 'design-system';
import * as React from 'react';
import { AutoSizer } from 'react-virtualized/dist/commonjs/AutoSizer';
@@ -80,7 +81,12 @@ export default class ProjectsList extends React.PureComponent<Props> {
const project = projects[index];

return (
<div key={key} role="row" style={{ ...style, height: PROJECT_CARD_HEIGHT }}>
<div
className={classNames({ 'sw-mt-4': index === 0 })}
key={key}
role="row"
style={{ ...style, height: PROJECT_CARD_HEIGHT }}
>
<div className="sw-h-full" role="gridcell">
<ProjectCard
currentUser={this.props.currentUser}
@@ -105,11 +111,18 @@ export default class ProjectsList extends React.PureComponent<Props> {
height={height}
overscanRowCount={2}
rowCount={this.props.projects.length + 1}
rowHeight={({ index }) =>
index === this.props.projects.length
? PROJECT_LIST_FOOTER_HEIGHT
: PROJECT_CARD_HEIGHT + PROJECT_CARD_MARGIN
}
rowHeight={({ index }) => {
if (index === 0) {
// first card, double top and bottom margin
return PROJECT_CARD_HEIGHT + PROJECT_CARD_MARGIN * 2;
}
if (index === this.props.projects.length) {
// Footer card, no margin
return PROJECT_LIST_FOOTER_HEIGHT;
}
// all other cards, only bottom margin
return PROJECT_CARD_HEIGHT + PROJECT_CARD_MARGIN;
}}
rowRenderer={this.renderRow}
style={{ outline: 'none' }}
tabIndex={-1}

Loading…
Cancel
Save