11// Copyright 2023 DatabendLabs.
2- import React , { FC , ReactElement , ReactNode , useEffect , useRef , useState } from "react" ;
2+ import React , {
3+ FC ,
4+ ReactElement ,
5+ ReactNode ,
6+ useEffect ,
7+ useMemo ,
8+ useRef ,
9+ useState ,
10+ } from "react" ;
311import LinkSvg from "../../../static/icons/link" ;
412import copy from "copy-to-clipboard" ;
513import Tooltip from "../BaseComponents/Tooltip" ;
6- // import { MDXProvider } from '@mdx-js/react' ;
14+ import DownArrow from "@site/static/icons/down.svg" ;
715interface IProps {
816 number : number | string ;
9- children : ReactNode ;
17+ children : ReactNode | ReactNode [ ] ;
1018 title : string ;
1119 outLink ?: string ;
1220 defaultCollapsed ?: boolean ;
@@ -16,10 +24,9 @@ const StepContent: FC<IProps> = ({
1624 children,
1725 title,
1826 outLink,
19- defaultCollapsed = false ,
27+ defaultCollapsed = undefined ,
2028} ) : ReactElement => {
2129 const wrapRef = useRef < any > ( null ) ;
22- const contentRef = useRef < any > ( null ) ;
2330 const [ isCollapsed , setIsCollapsed ] = useState ( defaultCollapsed ) ;
2431
2532 useEffect ( ( ) => {
@@ -44,48 +51,14 @@ const StepContent: FC<IProps> = ({
4451 ) ;
4552 }
4653 }
47-
48- // Add collapse button after first h2 if defaultCollapsed is defined
49- if ( defaultCollapsed !== undefined && contentRef ?. current ) {
50- const firstH2 = contentRef . current . querySelector ( 'h2' ) ;
51- if ( firstH2 && ! firstH2 . nextElementSibling ?. classList ?. contains ( 'collapse-button-wrapper' ) ) {
52- const buttonWrapper = document . createElement ( 'div' ) ;
53- buttonWrapper . className = 'collapse-button-wrapper' ;
54- buttonWrapper . style . cssText = 'display: flex; justify-content: flex-start; margin: 8px 0 16px 0;' ;
55-
56- const button = document . createElement ( 'button' ) ;
57- button . style . cssText = 'padding: 4px 12px; cursor: pointer; background: transparent; border: 1px solid var(--ifm-color-emphasis-300); border-radius: 4px; font-size: 12px; color: var(--ifm-color-emphasis-700);' ;
58- button . textContent = isCollapsed ? '▼ Show Details' : '▲ Hide Details' ;
59- button . onclick = ( ) => setIsCollapsed ( prev => ! prev ) ;
60-
61- buttonWrapper . appendChild ( button ) ;
62- firstH2 . parentNode . insertBefore ( buttonWrapper , firstH2 . nextSibling ) ;
63- }
54+ } , [ ] ) ;
55+ const childrenArray = useMemo ( ( ) => {
56+ if ( Array . isArray ( children ) ) {
57+ return children ;
58+ } else {
59+ return [ children ] ;
6460 }
65- } , [ defaultCollapsed ] ) ;
66- useEffect ( ( ) => {
67- // Update button text and hide/show content after button when collapsed
68- if ( contentRef ?. current ) {
69- const buttonWrapper = contentRef . current . querySelector ( '.collapse-button-wrapper' ) ;
70- if ( buttonWrapper ) {
71- const button = buttonWrapper . querySelector ( 'button' ) ;
72- if ( button ) {
73- button . textContent = isCollapsed ? '▼ Show Details' : '▲ Hide Details' ;
74- // Re-bind the click event with function form to avoid closure issues
75- button . onclick = ( ) => setIsCollapsed ( prev => ! prev ) ;
76- }
77-
78- let node = buttonWrapper . nextSibling ;
79- while ( node ) {
80- if ( node . nodeType === 1 ) { // Element node
81- ( node as HTMLElement ) . style . display = isCollapsed ? 'none' : '' ;
82- }
83- node = node . nextSibling ;
84- }
85- }
86- }
87- } , [ isCollapsed ] ) ;
88-
61+ } , [ children ] ) ;
8962 return (
9063 < div
9164 className = "global-step-container"
@@ -132,8 +105,22 @@ const StepContent: FC<IProps> = ({
132105 ) }
133106 </ span >
134107 < div className = "step-content" ref = { wrapRef } >
135- < div ref = { contentRef } >
136- { children }
108+ < div >
109+ { isCollapsed !== undefined && (
110+ < button
111+ onClick = { ( ) => setIsCollapsed ( ( v ) => ! v ) }
112+ className = "collapsible-btn"
113+ aria-expanded = { ! isCollapsed }
114+ >
115+ < span className = { `collapsible-icon ${ isCollapsed ? "" : "open" } ` } >
116+ < DownArrow width = { 16 } height = { 16 } />
117+ </ span >
118+ { isCollapsed ? "Show Details" : "Hide Details" }
119+ </ button >
120+ ) }
121+ { childrenArray ?. [ 0 ] }
122+ { ( isCollapsed === undefined || ! isCollapsed ) &&
123+ childrenArray ?. slice ( 1 ) }
137124 </ div >
138125 </ div >
139126 </ div >
0 commit comments