diff --git a/app-typescript/components/ToggleBox/CustomHeaderToggleBox.tsx b/app-typescript/components/ToggleBox/CustomHeaderToggleBox.tsx index be91ddcf..f691961a 100644 --- a/app-typescript/components/ToggleBox/CustomHeaderToggleBox.tsx +++ b/app-typescript/components/ToggleBox/CustomHeaderToggleBox.tsx @@ -2,31 +2,49 @@ import * as React from 'react'; import classNames from 'classnames'; import nextId from "react-id-generator"; import {IPropsCustomHeader} from "../ToggleBox/index"; +import {assertNever} from '../../helpers'; interface IState { isOpen: boolean; + wasOpened: boolean; isAnimating: boolean; } -export class CustomHeaderToggleBox extends React.PureComponent { +type IProps = IPropsCustomHeader; + +export class CustomHeaderToggleBox extends React.PureComponent { + static defaultProps: Partial; + htmlId = nextId('togglebox-'); contentRef = React.createRef(); - constructor(props: IPropsCustomHeader) { + constructor(props: IProps) { super(props); + + const isOpen = this.props.initiallyOpen ?? false; + this.state = { - isOpen: this.props.initiallyOpen ?? false, + isOpen: isOpen, + wasOpened: isOpen, isAnimating: false, }; } toggle = (): void => { - this.setState({isOpen: !this.state.isOpen}, () => { + const nextState: Partial = { + isOpen: !this.state.isOpen, + }; + + if (this.state.wasOpened !== true && nextState.isOpen === true) { + nextState.wasOpened = true; + } + + this.setState({...this.state, ...nextState}, () => { this.props.onToggle?.(this.state.isOpen); }); } - componentDidUpdate(_prevProps: IPropsCustomHeader, prevState: IState) { + componentDidUpdate(_prevProps: IProps, prevState: IState) { if (prevState.isOpen !== this.state.isOpen) { this.setState({ isAnimating: true }); @@ -49,6 +67,7 @@ export class CustomHeaderToggleBox extends React.PureComponent - {this.props.children} + {(() => { + if (renderChildren === 'always') { + return this.props.children; + } else if (renderChildren === 'when-open') { + if (isOpen) { + return this.props.children; + } else { + return null; + } + } else if (renderChildren === 'after-first-opening') { + if (this.state.isOpen || this.state.wasOpened) { + return this.props.children; + } else { + return null; + } + } else { + return assertNever(renderChildren); + } + })()} diff --git a/app-typescript/components/ToggleBox/index.tsx b/app-typescript/components/ToggleBox/index.tsx index 3f7e36d6..eede0461 100644 --- a/app-typescript/components/ToggleBox/index.tsx +++ b/app-typescript/components/ToggleBox/index.tsx @@ -24,6 +24,13 @@ export interface IPropsCustomHeader { getToggleButtonLabel: (isOpen: boolean) => string; initiallyOpen?: boolean; onToggle?(isOpen: boolean): void; + + /** + * 'after-first-opening' - will start rendering children upon first opening the togglebox. + * If togglebox is closed, it will continue rendering children in order to prevent unmounting + * and losing state of components rendered in children. + */ + renderChildren?: 'when-open' | 'always' | 'after-first-opening'; // defaults to 'always' } type IProps = IPropsSimple | IPropsCustomHeader; diff --git a/examples/pages/components/Togglebox.tsx b/examples/pages/components/Togglebox.tsx index 24e1a768..904e5881 100644 --- a/examples/pages/components/Togglebox.tsx +++ b/examples/pages/components/Togglebox.tsx @@ -49,15 +49,15 @@ const ToggleboxDocs = () => { Togglebox content
-

Maecenas sed diam eget risus varius blandit sit amet non magna. Nulla vitae elit libero, a pharetra augue. - Donec id elit non mi porta gravida at eget metus. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. +

Maecenas sed diam eget risus varius blandit sit amet non magna. Nulla vitae elit libero, a pharetra augue. + Donec id elit non mi porta gravida at eget metus. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Curabitur blandit tempus porttitor.

Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Nullam quis risus eget urna mollis ornare vel eu leo. - Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit. Integer posuere + Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit. Integer posuere erat a ante venenatis dapibus posuere velit aliquet.

-

Aenean lacinia bibendum nulla sed consectetur. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Vestibulum id +

Aenean lacinia bibendum nulla sed consectetur. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Vestibulum id ligula porta felis euismod semper. Cras justo odio, dapibus ac facilisis in, egestas eget quam.

@@ -98,12 +98,12 @@ const ToggleboxDocs = () => { } - toggleButtonLabel={'show more'} + getToggleButtonLabel={() => 'show more'} onToggle={(isOpen) => false} >
- Australian Open 2024 + Australian Open 2024-
@@ -148,6 +148,7 @@ const ToggleboxDocs = () => {
} + getToggleButtonLabel={() => 'show more'} onToggle={() => false} >