Only load sections into the DOM if their tag is clicked.

This commit is contained in:
Chris Bojemski 2020-01-10 16:12:52 -08:00
parent 1f05af52ff
commit 8d982ae27d
7 changed files with 47 additions and 19 deletions

View File

@ -11,14 +11,19 @@ import { Operation } from '../Operation/Operation';
@observer @observer
export class ContentItems extends React.Component<{ export class ContentItems extends React.Component<{
activeSelection?: string;
items: ContentItemModel[]; items: ContentItemModel[];
}> { }> {
render() { render() {
const items = this.props.items; const items = this.props.items;
const activeSelection = this.props.activeSelection;
if (items.length === 0) { if (items.length === 0) {
return null; return null;
} }
return items.map(item => <ContentItem item={item} key={item.id} />); const filteredItems = items.filter(item => {
return item.type == "tag" ? item.name == `${activeSelection}` : true;
});
return filteredItems.map(item => <ContentItem item={item} key={item.id} />);
} }
} }

View File

@ -4,7 +4,7 @@ import * as React from 'react';
import { ThemeProvider } from '../../styled-components'; import { ThemeProvider } from '../../styled-components';
import { OptionsProvider } from '../OptionsProvider'; import { OptionsProvider } from '../OptionsProvider';
import { AppStore } from '../../services'; import { AppStore, IMenuItem } from '../../services';
import { ApiInfo } from '../ApiInfo/'; import { ApiInfo } from '../ApiInfo/';
import { ApiLogo } from '../ApiLogo/ApiLogo'; import { ApiLogo } from '../ApiLogo/ApiLogo';
import { ContentItems } from '../ContentItems/ContentItems'; import { ContentItems } from '../ContentItems/ContentItems';
@ -19,11 +19,17 @@ export interface RedocProps {
store: AppStore; store: AppStore;
} }
export class Redoc extends React.Component<RedocProps> { export interface AppState {
activeSelection: string | undefined;
}
export class Redoc extends React.Component<RedocProps, AppState> {
static propTypes = { static propTypes = {
store: PropTypes.instanceOf(AppStore).isRequired, store: PropTypes.instanceOf(AppStore).isRequired,
}; };
state = { activeSelection: undefined };
componentDidMount() { componentDidMount() {
this.props.store.onDidMount(); this.props.store.onDidMount();
} }
@ -32,6 +38,12 @@ export class Redoc extends React.Component<RedocProps> {
this.props.store.dispose(); this.props.store.dispose();
} }
setActiveSelection = (item: IMenuItem) => {
if (item && item.type === "tag") {
this.setState({ activeSelection: item.name });
}
}
render() { render() {
const { const {
store: { spec, menu, options, search, marker }, store: { spec, menu, options, search, marker },
@ -50,14 +62,15 @@ export class Redoc extends React.Component<RedocProps> {
marker={marker} marker={marker}
getItemById={menu.getItemById} getItemById={menu.getItemById}
onActivate={menu.activateAndScroll} onActivate={menu.activateAndScroll}
setActiveSelection={() => this.setActiveSelection}
/> />
)) || )) ||
null} null}
<SideMenu menu={menu} /> <SideMenu menu={menu} setActiveSelection={this.setActiveSelection} />
</StickyResponsiveSidebar> </StickyResponsiveSidebar>
<ApiContentWrap className="api-content"> <ApiContentWrap className="api-content">
<ApiInfo store={store} /> <ApiInfo store={store} />
<ContentItems items={menu.items as any} /> <ContentItems activeSelection={this.state.activeSelection} items={menu.items as any} />
</ApiContentWrap> </ApiContentWrap>
<BackgroundStub /> <BackgroundStub />
</RedocWrap> </RedocWrap>

View File

@ -23,6 +23,8 @@ export interface SearchBoxProps {
onActivate: (item: IMenuItem) => void; onActivate: (item: IMenuItem) => void;
className?: string; className?: string;
setActiveSelection: () => void;
} }
export interface SearchBoxState { export interface SearchBoxState {
@ -153,6 +155,7 @@ export class SearchBox extends React.PureComponent<SearchBoxProps, SearchBoxStat
withoutChildren={true} withoutChildren={true}
key={res.item.id} key={res.item.id}
data-role="search:result" data-role="search:result"
setActiveSelection={() => this.props.setActiveSelection}
/> />
))} ))}
</SearchResultsBox> </SearchResultsBox>

View File

@ -11,6 +11,7 @@ import { MenuItemLabel, MenuItemLi, MenuItemTitle, OperationBadge } from './styl
export interface MenuItemProps { export interface MenuItemProps {
item: IMenuItem; item: IMenuItem;
onActivate?: (item: IMenuItem) => void; onActivate?: (item: IMenuItem) => void;
setActiveSelection: (item: IMenuItem) => void;
withoutChildren?: boolean; withoutChildren?: boolean;
} }
@ -19,6 +20,7 @@ export class MenuItem extends React.Component<MenuItemProps> {
ref = React.createRef<HTMLLabelElement>(); ref = React.createRef<HTMLLabelElement>();
activate = (evt: React.MouseEvent<HTMLElement>) => { activate = (evt: React.MouseEvent<HTMLElement>) => {
this.props.setActiveSelection(this.props.item);
this.props.onActivate!(this.props.item); this.props.onActivate!(this.props.item);
evt.stopPropagation(); evt.stopPropagation();
}; };
@ -60,6 +62,7 @@ export class MenuItem extends React.Component<MenuItemProps> {
expanded={item.expanded} expanded={item.expanded}
items={item.items} items={item.items}
onActivate={this.props.onActivate} onActivate={this.props.onActivate}
setActiveSelection={() => this.props.setActiveSelection}
/> />
)} )}
</MenuItemLi> </MenuItemLi>

View File

@ -14,6 +14,8 @@ export interface MenuItemsProps {
root?: boolean; root?: boolean;
className?: string; className?: string;
setActiveSelection: (item: IMenuItem) => void;
} }
@observer @observer
@ -29,7 +31,7 @@ export class MenuItems extends React.Component<MenuItemsProps> {
{...(root ? { role: 'navigation' } : {})} {...(root ? { role: 'navigation' } : {})}
> >
{items.map((item, idx) => ( {items.map((item, idx) => (
<MenuItem key={idx} item={item} onActivate={this.props.onActivate} /> <MenuItem key={idx} item={item} onActivate={this.props.onActivate} setActiveSelection={this.props.setActiveSelection} />
))} ))}
</MenuItemUl> </MenuItemUl>
); );

View File

@ -9,7 +9,7 @@ import { PerfectScrollbarWrap } from '../../common-elements/perfect-scrollbar';
import { RedocAttribution } from './styled.elements'; import { RedocAttribution } from './styled.elements';
@observer @observer
export class SideMenu extends React.Component<{ menu: MenuStore; className?: string }> { export class SideMenu extends React.Component<{ menu: MenuStore; className?: string; setActiveSelection: (item: IMenuItem) => void }> {
static contextType = OptionsContext; static contextType = OptionsContext;
private _updateScroll?: () => void; private _updateScroll?: () => void;
@ -23,7 +23,7 @@ export class SideMenu extends React.Component<{ menu: MenuStore; className?: str
wheelPropagation: false, wheelPropagation: false,
}} }}
> >
<MenuItems items={store.items} onActivate={this.activate} root={true} /> <MenuItems items={store.items} onActivate={this.activate} root={true} setActiveSelection={this.props.setActiveSelection} />
<RedocAttribution> <RedocAttribution>
<a target="_blank" href="https://github.com/Redocly/redoc"> <a target="_blank" href="https://github.com/Redocly/redoc">
Documentation Powered by ReDoc Documentation Powered by ReDoc

View File

@ -64,6 +64,8 @@ export class MenuStore {
items: IMenuItem[]; items: IMenuItem[];
flatItems: IMenuItem[]; flatItems: IMenuItem[];
activeSelection?: string;
/** /**
* cached flattened menu items to support absolute indexing * cached flattened menu items to support absolute indexing
*/ */