1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Introducting ScrollSpy component

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>
This commit is contained in:
Alex Andreev 2021-02-25 15:40:11 +03:00
parent f4764c757f
commit 90a1101a0f
3 changed files with 88 additions and 26 deletions

View File

@ -38,9 +38,9 @@ export class Preferences extends React.Component {
contentGaps={false} contentGaps={false}
header={header} header={header}
> >
<section> <section id="application">
<h1>Application</h1> <h1>Application</h1>
<section> <section id="appearance">
<h2>Appearance</h2> <h2>Appearance</h2>
<SubTitle title="Theme"/> <SubTitle title="Theme"/>
<Select <Select

View File

@ -5,6 +5,7 @@ import { observer } from "mobx-react";
import { autobind, cssNames, IClassName } from "../../utils"; import { autobind, cssNames, IClassName } from "../../utils";
import { Icon } from "../icon"; import { Icon } from "../icon";
import { navigation } from "../../navigation"; import { navigation } from "../../navigation";
import { ScrollSpy } from "../scroll-spy/scroll-spy";
export interface PageLayoutProps extends React.DOMAttributes<any> { export interface PageLayoutProps extends React.DOMAttributes<any> {
className?: IClassName; className?: IClassName;
@ -63,33 +64,35 @@ export class PageLayout extends React.Component<PageLayoutProps> {
const className = cssNames("PageLayout", { showOnTop, showNavigation }, this.props.className); const className = cssNames("PageLayout", { showOnTop, showNavigation }, this.props.className);
return ( return (
<div {...elemProps} className={className}> <ScrollSpy render={navigation => (
<div className={cssNames("header flex gaps align-center", headerClass)}> <div {...elemProps} className={className}>
{header} <div className={cssNames("header flex gaps align-center", headerClass)}>
{provideBackButtonNavigation && ( {header}
<Icon {provideBackButtonNavigation && (
big material="close" <Icon
className="back box right" big material="close"
onClick={this.back} className="back box right"
/> onClick={this.back}
)} />
</div>
<div className="content-scrollable-area">
<div className="content-wrapper">
{ showNavigation && (
<div className="content-navigation">
<ul>
<li>Section 1</li>
<li>Section 2</li>
</ul>
</div>
)} )}
<div className={cssNames("content", contentGaps && "flex column gaps", contentClass)}> </div>
{children} <div className="content-scrollable-area">
<div className="content-wrapper">
{ showNavigation && (
<div className="content-navigation">
<ul>
<li>Section 1</li>
<li>Section 2</li>
<li>{navigation.toString()}</li>
</ul>
</div>
)}
<div className={cssNames("content", contentGaps && "flex column gaps", contentClass)}>
{children}
</div>
</div> </div>
</div> </div>
</div> </div>
</div> )} />);
);
} }
} }

View File

@ -0,0 +1,59 @@
import React, { useEffect } from "react";
interface Props extends React.DOMAttributes<any> {
render: (data: any) => any
}
export function ScrollSpy(props: Props) {
let navigationData: any = {};
const updateNavigation = () => {
const firstSection = document.querySelector("section");
if (!firstSection) {
throw new Error("No <section/> tag founded! Content should be placed inside <section></section> elements to activate navigation.");
}
navigationData = {
id: "root",
name: "Parent",
children: getNavigation(firstSection.parentElement)
};
console.log(navigationData);
};
const getNavigation = (element: Element) => {
const sections = element.querySelectorAll(":scope > section"); // Searching only direct children of an element. Impossible without :scope
const children: any = [];
sections.forEach(section => {
const id = section.getAttribute("id");
const name = section.querySelector(":first-child").textContent;
if (!name || !id) {
return;
}
children.push({
id,
name,
children: getNavigation(section)
});
});
return children;
};
useEffect(() => {
updateNavigation();
// element.current.addEventListener("scroll", updateActive);
// TODO: Attach on dom change event
}, []);
return (
<div className="ScrollSpy">
{props.render(navigationData)}
</div>
);
}