• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

alkem-io / client-web / #6261

16 Nov 2023 07:34AM UTC coverage: 5.912%. First build
#6261

Pull #5202

travis-ci

Pull Request #5202: Skip links for content blocks and platform navigation

184 of 8737 branches covered (0.0%)

Branch coverage included in aggregate %.

0 of 30 new or added lines in 7 files covered. (0.0%)

1280 of 16027 relevant lines covered (7.99%)

0.19 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/main/ui/platformNavigation/PlatformNavigationBar.tsx
1
import { cloneElement, ReactElement, Ref, useLayoutEffect, useRef, useState } from 'react';
2
import NavigationBar, { NAVIGATION_CONTENT_HEIGHT_GUTTERS } from '@/core/ui/navigation/NavigationBar';
3
import PlatformNavigationUserAvatar from './PlatformNavigationUserAvatar';
4
import PlatformSearch from '../platformSearch/PlatformSearch';
5
import PlatformNavigationMenuButton from './PlatformNavigationMenuButton';
6
import { Box, MenuItem, Slide } from '@mui/material';
7
import PlatformNavigationUserMenu, { UserMenuDivider } from './PlatformNavigationUserMenu';
8
import UserMenuPlatformNavigationSegment from './platformNavigationMenu/UserMenuPlatformNavigationSegment';
9
import NavigationBarSideContent from '@/core/ui/navigation/NavigationBarSideContent';
10
import { gutters } from '@/core/ui/grid/utils';
11
import { Collapsible } from '@/core/ui/navigation/Collapsible';
12
import { UncontrolledExpandable } from '@/core/ui/navigation/UncontrolledExpandable';
13
import { useResizeDetector } from 'react-resize-detector';
14
import { GUTTER_PX, useScreenSize } from '@/core/ui/grid/constants';
15
import PlatformNavigationUncollapse from './PlatformNavigationUncollapse';
16
import SkipLink from '@/core/ui/keyboardNavigation/SkipLink';
17
import { useTranslation } from 'react-i18next';
18
import PoweredBy from '../poweredBy/PoweredBy';
19
import { PlatformNotificationsButton } from './PlatformNotificationsButton';
20
import { UserMessagingButton } from '@/main/userMessaging/UserMessagingButton';
21

22
export interface PlatformNavigationBarProps {
23
  breadcrumbs?: ReactElement<UncontrolledExpandable & { ref: Ref<Collapsible> }>;
×
24
}
25

26
const DEFAULT_BOUNDING_CLIENT_RECT = {
27
  right: 0,
×
28
} as const;
×
29

30
const PlatformNavigationBar = ({ breadcrumbs }: PlatformNavigationBarProps) => {
×
31
  const { isSmallScreen } = useScreenSize();
32

×
33
  const [areBreadcrumbsHidden, setAreBreadcrumbsHidden] = useState(false);
34

×
35
  const breadcrumbsContainerRef = useRef<HTMLDivElement>(null);
36

×
37
  const buttonsContainerRef = useRef<HTMLDivElement>(null);
38

×
39
  const uncollapseButtonRef = useRef<HTMLButtonElement>(null);
40

×
41
  const [rightSideShift, setRightSideShift] = useState(0);
×
42

43
  const breadcrumbsRef = useRef<Collapsible>(null);
×
44
  const searchBoxRef = useRef<Collapsible>(null);
×
45

×
46
  const handleExpandSearch = (isExpanded: boolean) => {
×
47
    setAreBreadcrumbsHidden(isSmallScreen && isExpanded);
48
    if (isExpanded) {
49
      breadcrumbsRef.current?.collapse();
50
    }
×
51
  };
×
52

×
53
  const handleExpandBreadcrumbs = (areExpanded: boolean) => {
54
    if (areExpanded) {
55
      searchBoxRef.current?.collapse();
×
56
    }
×
57

×
58
    if (!isSmallScreen || !areExpanded) {
59
      setRightSideShift(0);
60
      return;
61
    }
×
62

63
    const { right: containerRight } =
×
64
      buttonsContainerRef.current?.getBoundingClientRect() ?? DEFAULT_BOUNDING_CLIENT_RECT;
65
    const { right: contentRight } =
×
66
      uncollapseButtonRef.current?.getBoundingClientRect() ?? DEFAULT_BOUNDING_CLIENT_RECT;
67

68
    setRightSideShift(prevShift => prevShift || containerRight - contentRight);
×
69
  };
70

71
  const { height: breadcrumbsHeight = 0, ref: breadcrumbsWrapperRef } = useResizeDetector();
×
72

73
  const breadcrumbsVerticalShift =
×
74
    breadcrumbsHeight > GUTTER_PX * 2 ? (NAVIGATION_CONTENT_HEIGHT_GUTTERS * GUTTER_PX - breadcrumbsHeight) / 2 : 0;
×
75

×
76
  useLayoutEffect(() => {
77
    breadcrumbsRef.current?.collapse();
NEW
78
    searchBoxRef.current?.collapse();
×
79
  }, [isSmallScreen]);
80

×
81
  const { t } = useTranslation();
NEW
82

×
83
  return (
84
    <NavigationBar>
85
      <SkipLink anchor={() => document.querySelector('main')}>{t('components.navigation.skipMenu')}</SkipLink>
86

87
      <NavigationBarSideContent ref={buttonsContainerRef}>
88
        <Box
89
          display="flex"
90
          gap={gutters(0.5)}
91
          padding={gutters(0.5)}
92
          justifyContent="end"
93
          position="relative"
94
          sx={{
×
95
            transform: `translateX(${rightSideShift}px)`,
96
            transition: theme =>
97
              `transform ${theme.transitions.duration.standard}ms ${theme.transitions.easing.easeInOut}`,
98
          }}
99
        >
100
          <PlatformSearch ref={searchBoxRef} onExpand={handleExpandSearch} compact={isSmallScreen}>
×
101
            <PlatformNavigationUncollapse ref={uncollapseButtonRef} visible={rightSideShift !== 0} />
102
          </PlatformSearch>
103
          <UserMessagingButton />
×
104
          <PlatformNotificationsButton />
105
          {!isSmallScreen && <PlatformNavigationMenuButton />}
106
          <PlatformNavigationUserAvatar drawer={isSmallScreen}>
107
            <PlatformNavigationUserMenu
108
              surface={!isSmallScreen}
109
              footer={
110
                isSmallScreen && [
111
                  <UserMenuDivider key="divider" />,
112
                  <Box component={MenuItem} paddingY={gutters(0.5)} key="menu-item">
113
                    <PoweredBy preview />
114
                  </Box>,
×
115
                ]
116
              }
117
            >
118
              {isSmallScreen && <UserMenuPlatformNavigationSegment />}
119
              {isSmallScreen && <UserMenuDivider />}
×
120
            </PlatformNavigationUserMenu>
121
          </PlatformNavigationUserAvatar>
122
        </Box>
123
      </NavigationBarSideContent>
124

125
      <NavigationBarSideContent
126
        ref={breadcrumbsContainerRef}
127
        sx={{
128
          pointerEvents: 'none',
129
          transform: `translateY(${breadcrumbsVerticalShift}px)`,
130
          transition: theme => `transform ${theme.transitions.duration.shortest}ms linear`,
131
        }}
132
      >
133
        <Slide in={!areBreadcrumbsHidden} container={breadcrumbsContainerRef.current} direction="right">
134
          <Box ref={breadcrumbsWrapperRef} display="flex">
135
            {breadcrumbs && cloneElement(breadcrumbs, { ref: breadcrumbsRef, onExpand: handleExpandBreadcrumbs })}
136
          </Box>
137
        </Slide>
138
      </NavigationBarSideContent>
139
    </NavigationBar>
140
  );
141
};
142

143
export default PlatformNavigationBar;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc