Skip to content

Commit

Permalink
feat(System): headers of sections should be sticky [YTFRONT-4420]
Browse files Browse the repository at this point in the history
  • Loading branch information
ma-efremoff committed Nov 13, 2024
1 parent cdee29c commit 7e04dae
Show file tree
Hide file tree
Showing 12 changed files with 225 additions and 140 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export class CollapsibleSectionStateLess extends Component<PropsStateLess> {
size,
overview,
className,
headingClassName,
collapsed,
marginDirection,
togglerRightPadding,
Expand All @@ -41,7 +42,7 @@ export class CollapsibleSectionStateLess extends Component<PropsStateLess> {
return (
<ErrorBoundary>
<div className={b({margin: marginDirection}, className)}>
<div className={headingCN({size, overview: 'yes'})}>
<div className={headingCN({size, overview: 'yes'}, headingClassName)}>
<span
className={headingCN(
'heading',
Expand Down Expand Up @@ -72,6 +73,7 @@ export class CollapsibleSectionStateLess extends Component<PropsStateLess> {

export interface CollapsibleSectionProps {
className?: string;
headingClassName?: string;
name: React.ReactNode;
collapsed?: boolean;
onToggle?: (value: boolean) => void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@ $thin-border: 1px solid var(--light-divider);
overflow: auto;

&-wrapper {
padding-bottom: 50px;

&_sticky_top {
padding: 0;
position: sticky;
z-index: var(--elements-table-sticky-top-z-index);

Expand All @@ -42,8 +39,6 @@ $thin-border: 1px solid var(--light-divider);
}

&_sticky_bottom {
padding: 0;
margin-top: -50px;
position: sticky;
bottom: 0;
z-index: var(--elements-table-sticky-top-z-index);
Expand Down
18 changes: 18 additions & 0 deletions packages/ui/src/ui/components/StickyContainer/StickyContainer.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.yt-sticky-container {
&__sticky {
position: sticky;
z-index: 1;

background-color: var(--main-background);
box-shadow: 0 1px 10px var(--opacity-background);

width: calc(100vw - var(--gn-aside-header-size));
margin-left: -20px;
padding-left: 20px;
padding-right: 20px;

&_top {
top: var(--app-header-height);
}
}
}
56 changes: 56 additions & 0 deletions packages/ui/src/ui/components/StickyContainer/StickyContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from 'react';
import cn from 'bem-cn-lite';
import {HEADER_HEIGHT} from '../../constants';

import './StickyContainer.scss';

const block = cn('yt-sticky-container');

export function StickyContainer({
topOffset = HEADER_HEIGHT,
children,
}: {
topOffset?: number;
children: (params: {sticky: boolean; topStickyClassName?: string}) => React.ReactNode;
}) {
const [sticky, setSticky] = React.useState(false);
const [element, setElement] = React.useState<HTMLDivElement | null>(null);

const observer = React.useMemo(() => {
return new IntersectionObserver(
(entries) => {
if (entries[0].intersectionRatio === 0) {
setSticky(true);
} else if (entries[0].intersectionRatio === 1) {
setSticky(false);
}
},
{threshold: [0, 1], rootMargin: `${-topOffset ?? 0}px 0px 0px 0px`},
);
}, [topOffset]);

React.useEffect(() => {
if (element) {
observer.observe(element);
}
return () => {
if (element) {
observer.unobserve(element);
}
};
}, [element]);

const onRef = React.useCallback((div: HTMLDivElement | null) => {
setElement(div);
}, []);

return (
<div className={block()}>
<div className={block('top')} ref={onRef} />
{children({
sticky,
topStickyClassName: sticky ? block('sticky', {top: true}) : undefined,
})}
</div>
);
}
29 changes: 18 additions & 11 deletions packages/ui/src/ui/pages/system/Chunks/Chunks.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import withStickyHead from '../../../components/ElementsTable/hocs/withStickyHea
import ElementsTableBase from '../../../components/ElementsTable/ElementsTable';
import SystemCounters from '../SystemCounters/SystemCounters';
import Label from '../../../components/Label/Label';
import {StickyContainer} from '../../../components/StickyContainer/StickyContainer';

import {SYSTEM_CHUNKS_TABLE_ID} from '../../../constants/tables';
import {loadChunks} from '../../../store/actions/system/chunks';
Expand All @@ -26,6 +27,7 @@ import {useUpdater} from '../../../hooks/use-updater';

import './Chunks.scss';
import {UI_COLLAPSIBLE_SIZE} from '../../../constants/global';
import {HEADER_HEIGHT} from '../../../constants';

const b = block('system');

Expand Down Expand Up @@ -225,17 +227,22 @@ class Chunks extends Component {
);

return (
<CollapsibleSectionStateLess
name={'Chunks'}
overview={overview}
onToggle={this.onToggle}
collapsed={collapsed}
size={collapsibleSize}
>
<div className={b('chunks')}>
<ElementsTable {...table} footer={totalRow} />
</div>
</CollapsibleSectionStateLess>
<StickyContainer>
{({topStickyClassName}) => (
<CollapsibleSectionStateLess
name={'Chunks'}
headingClassName={topStickyClassName}
overview={overview}
onToggle={this.onToggle}
collapsed={collapsed}
size={collapsibleSize}
>
<div className={b('chunks')}>
<ElementsTable {...table} top={HEADER_HEIGHT + 64} footer={totalRow} />
</div>
</CollapsibleSectionStateLess>
)}
</StickyContainer>
);
}

Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/ui/pages/system/Chunks/Chunks.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
.system {
&__chunks {
margin-bottom: 20px;
z-index: -1;
position: relative;
}

.chunk-cells {
Expand Down
72 changes: 34 additions & 38 deletions packages/ui/src/ui/pages/system/Masters/Masters.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {useUpdater} from '../../../hooks/use-updater';
import './Masters.scss';
import {SystemAlert} from './SystemAlert';
import {UI_COLLAPSIBLE_SIZE} from '../../../constants/global';
import {StickyContainer} from '../../../components/StickyContainer/StickyContainer';

const b = block('system-master');
const headingCN = block('elements-heading')({size: 's'});
Expand Down Expand Up @@ -104,10 +105,7 @@ class Masters extends Component {

return fitIntoSection ? (
<div className={b('all-masters')}>
<div className={headingCN}>
Primary Masters
{this.renderMasterTypeSwitcher()}
</div>
<div className={headingCN}>Primary Masters</div>
<MasterGroup
className={b('primary-master')}
{...primary}
Expand All @@ -122,10 +120,7 @@ class Masters extends Component {
)}
{Boolean(providers?.instances?.length) && (
<React.Fragment>
<div className={headingCN}>
Timestamp providers
{this.renderMasterTypeSwitcher()}
</div>
<div className={headingCN}>Timestamp providers</div>
<MasterGroup
{...providers}
className={b('timestamp-providers')}
Expand All @@ -137,10 +132,7 @@ class Masters extends Component {
)}
{Boolean(discovery?.instances?.length) && (
<React.Fragment>
<div className={headingCN}>
Discovery servers
{this.renderMasterTypeSwitcher()}
</div>
<div className={headingCN}>Discovery servers</div>
<MasterGroup
{...discovery}
className={b('discovery-servers')}
Expand All @@ -150,20 +142,14 @@ class Masters extends Component {
)}
{Boolean(queueAgents?.instances?.length) && (
<React.Fragment>
<div className={headingCN}>
Queue agents
{this.renderMasterTypeSwitcher()}
</div>
<div className={headingCN}>Queue agents</div>
<MasterGroup {...queueAgents} allowService />
</React.Fragment>
)}
</div>
) : (
<div>
<div className={headingCN}>
Primary Masters
{this.renderMasterTypeSwitcher()}
</div>
<div className={headingCN}>Primary Masters</div>
<MasterGroup
className={b('primary-master')}
{...primary}
Expand Down Expand Up @@ -239,14 +225,17 @@ class Masters extends Component {
}

return (
<SystemStateOverview
tab="masters"
labels={labels}
counters={counters}
stateThemeMappings={stateThemeMappings}
stateOverview={stateOverview}
counterGroup={counterGroups}
/>
<>
{this.renderMasterTypeSwitcher()}
<SystemStateOverview
tab="masters"
labels={labels}
counters={counters}
stateThemeMappings={stateThemeMappings}
stateOverview={stateOverview}
counterGroup={counterGroups}
/>
</>
);
}

Expand All @@ -261,16 +250,23 @@ class Masters extends Component {
const overview = this.renderOverview();

return (
<CollapsibleSectionStateLess
name={'Masters'}
overview={overview}
collapsed={collapsed}
onToggle={this.onToggle}
size={collapsibleSize}
>
{this.renderAlerts()}
{content}
</CollapsibleSectionStateLess>
<StickyContainer>
{({topStickyClassName}) => (
<CollapsibleSectionStateLess
name={'Masters'}
headingClassName={b('heading', topStickyClassName)}
overview={overview}
collapsed={collapsed}
onToggle={this.onToggle}
size={collapsibleSize}
>
<div className={b('content')}>
{this.renderAlerts()}
{content}
</div>
</CollapsibleSectionStateLess>
)}
</StickyContainer>
);
}

Expand Down
4 changes: 0 additions & 4 deletions packages/ui/src/ui/pages/system/Masters/Masters.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@
}

.system-master {
&__container-host-radio {
margin-left: 20px;
}

&__all-masters {
@include three-column-grid(8px);
grid-auto-flow: column;
Expand Down
24 changes: 15 additions & 9 deletions packages/ui/src/ui/pages/system/Nodes/Nodes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {ExpandButton} from '../../../components/ExpandButton';
import {CollapsibleSectionStateLess} from '../../../components/CollapsibleSection/CollapsibleSection';
import Link from '../../../components/Link/Link';
import {NoContent} from '../../../components/NoContent/NoContent';
import {StickyContainer} from '../../../components/StickyContainer/StickyContainer';

import SystemStateOverview from '../SystemStateOverview/SystemStateOverview';

Expand Down Expand Up @@ -213,15 +214,20 @@ const Nodes = (props: NodesProps) => {
}

return (
<CollapsibleSectionStateLess
overview={renderOverview()}
collapsed={collapsed}
onToggle={onToggle}
name={'Nodes'}
size={UI_COLLAPSIBLE_SIZE}
>
{renderContent()}
</CollapsibleSectionStateLess>
<StickyContainer>
{({topStickyClassName}) => (
<CollapsibleSectionStateLess
overview={renderOverview()}
headingClassName={topStickyClassName}
collapsed={collapsed}
onToggle={onToggle}
name={'Nodes'}
size={UI_COLLAPSIBLE_SIZE}
>
{renderContent()}
</CollapsibleSectionStateLess>
)}
</StickyContainer>
);
};

Expand Down
Loading

0 comments on commit 7e04dae

Please sign in to comment.