diff --git a/src/components/Steps/step-content.tsx b/src/components/Steps/step-content.tsx index 14542d6229..dc9c799ab6 100644 --- a/src/components/Steps/step-content.tsx +++ b/src/components/Steps/step-content.tsx @@ -1,12 +1,20 @@ // Copyright 2023 DatabendLabs. -import React, { FC, ReactElement, ReactNode, useEffect, useRef, useState } from "react"; +import React, { + FC, + ReactElement, + ReactNode, + useEffect, + useMemo, + useRef, + useState, +} from "react"; import LinkSvg from "../../../static/icons/link"; import copy from "copy-to-clipboard"; import Tooltip from "../BaseComponents/Tooltip"; -// import { MDXProvider } from '@mdx-js/react'; +import DownArrow from "@site/static/icons/down.svg"; interface IProps { number: number | string; - children: ReactNode; + children: ReactNode | ReactNode[]; title: string; outLink?: string; defaultCollapsed?: boolean; @@ -16,10 +24,9 @@ const StepContent: FC = ({ children, title, outLink, - defaultCollapsed = false, + defaultCollapsed = undefined, }): ReactElement => { const wrapRef = useRef(null); - const contentRef = useRef(null); const [isCollapsed, setIsCollapsed] = useState(defaultCollapsed); useEffect(() => { @@ -44,48 +51,14 @@ const StepContent: FC = ({ ); } } - - // Add collapse button after first h2 if defaultCollapsed is defined - if (defaultCollapsed !== undefined && contentRef?.current) { - const firstH2 = contentRef.current.querySelector('h2'); - if (firstH2 && !firstH2.nextElementSibling?.classList?.contains('collapse-button-wrapper')) { - const buttonWrapper = document.createElement('div'); - buttonWrapper.className = 'collapse-button-wrapper'; - buttonWrapper.style.cssText = 'display: flex; justify-content: flex-start; margin: 8px 0 16px 0;'; - - const button = document.createElement('button'); - 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);'; - button.textContent = isCollapsed ? '▼ Show Details' : '▲ Hide Details'; - button.onclick = () => setIsCollapsed(prev => !prev); - - buttonWrapper.appendChild(button); - firstH2.parentNode.insertBefore(buttonWrapper, firstH2.nextSibling); - } + }, []); + const childrenArray = useMemo(() => { + if (Array.isArray(children)) { + return children; + } else { + return [children]; } - }, [defaultCollapsed]); - useEffect(() => { - // Update button text and hide/show content after button when collapsed - if (contentRef?.current) { - const buttonWrapper = contentRef.current.querySelector('.collapse-button-wrapper'); - if (buttonWrapper) { - const button = buttonWrapper.querySelector('button'); - if (button) { - button.textContent = isCollapsed ? '▼ Show Details' : '▲ Hide Details'; - // Re-bind the click event with function form to avoid closure issues - button.onclick = () => setIsCollapsed(prev => !prev); - } - - let node = buttonWrapper.nextSibling; - while (node) { - if (node.nodeType === 1) { // Element node - (node as HTMLElement).style.display = isCollapsed ? 'none' : ''; - } - node = node.nextSibling; - } - } - } - }, [isCollapsed]); - + }, [children]); return (
= ({ )}
-
- {children} +
+ {isCollapsed !== undefined && ( + + )} + {childrenArray?.[0]} + {(isCollapsed === undefined || !isCollapsed) && + childrenArray?.slice(1)}
diff --git a/src/css/steps.scss b/src/css/steps.scss index f9dd324edf..2fb8387d35 100644 --- a/src/css/steps.scss +++ b/src/css/steps.scss @@ -74,7 +74,8 @@ background-color: hsl(var(--muted)); text-align: center; text-indent: -1px; - font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace; + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, + Liberation Mono, Courier New, monospace; font-size: 1rem; line-height: 1.5rem; font-weight: 500; @@ -93,6 +94,39 @@ display: none; } .step-content { + .collapsible-btn { + position: relative; + top: -15px; + display: inline-flex; + align-items: center; + gap: 6px; + padding: 2px 8px; + font-size: 0.875rem; + font-weight: 500; + color: #374151; + background: var(--color-fill-0); + border: 1px solid var(--color-border); + border-radius: 6px; + cursor: pointer; + transition: all 0.2s ease; + } + .collapsible-btn:focus-visible { + outline: none; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.3); + } + + .collapsible-icon { + display: flex; + transition: transform 0.2s ease; + } + + .collapsible-icon.open { + transform: rotate(180deg); + } + .collapsible-content { + overflow: hidden; + transition: max-height 0.3s ease-in-out; + } h3:first-child { color: var(--h3-title-color); font-size: 1.25rem;