diff --git a/awx/ui_next/src/components/CollapsibleSection/CollapsibleSection.jsx b/awx/ui_next/src/components/CollapsibleSection/CollapsibleSection.jsx new file mode 100644 index 0000000000..4bae5b2c9d --- /dev/null +++ b/awx/ui_next/src/components/CollapsibleSection/CollapsibleSection.jsx @@ -0,0 +1,54 @@ +import React, { useState } from 'react'; +import { bool, string } from 'prop-types'; +import styled from 'styled-components'; +import { Button } from '@patternfly/react-core'; +import { AngleRightIcon } from '@patternfly/react-icons'; +import ExpandingContainer from './ExpandingContainer'; + +const Toggle = styled.div` + display: flex; + + hr { + margin-left: 20px; + flex: 1 1 auto; + align-self: center; + border: 0; + border-bottom: 1px solid var(--pf-global--BorderColor--300); + } +`; + +const Arrow = styled(AngleRightIcon)` + margin-right: -5px; + margin-left: 5px; + transition: transform 0.1s ease-out; + transform-origin: 50% 50%; + ${(props) => props.isExpanded && `transform: rotate(90deg);`} +`; + +function CollapsibleSection({ label, startExpanded, children }) { + const [isExpanded, setIsExpanded] = useState(startExpanded); + const toggle = () => setIsExpanded(!isExpanded); + + return ( +
+ + +
+
+ + {children} + +
+ ); +} +CollapsibleSection.propTypes = { + label: string.isRequired, + startExpanded: bool, +}; +CollapsibleSection.defaultProps = { + startExpanded: false, +}; + +export default CollapsibleSection; diff --git a/awx/ui_next/src/components/CollapsibleSection/ExpandingContainer.jsx b/awx/ui_next/src/components/CollapsibleSection/ExpandingContainer.jsx new file mode 100644 index 0000000000..9ee27c52ff --- /dev/null +++ b/awx/ui_next/src/components/CollapsibleSection/ExpandingContainer.jsx @@ -0,0 +1,36 @@ +import React, { useState, useEffect, useRef } from 'react'; +import { bool } from 'prop-types'; +import styled from 'styled-components'; + +const Container = styled.div` + margin: 15px 0; + transition: all 0.2s ease-out; + overflow: hidden; +`; + +function ExpandingContainer({ isExpanded, children }) { + const [contentHeight, setContentHeight] = useState(0); + const ref = useRef(null); + useEffect(() => { + setContentHeight(ref.current.scrollHeight); + }); + const height = isExpanded ? contentHeight : '0'; + return ( + + {children} + + ); +} +ExpandingContainer.propTypes = { + isExpanded: bool, +}; +ExpandingContainer.defaultProps = { + isExpanded: false, +}; + +export default ExpandingContainer; diff --git a/awx/ui_next/src/components/CollapsibleSection/index.js b/awx/ui_next/src/components/CollapsibleSection/index.js new file mode 100644 index 0000000000..a4623e90ed --- /dev/null +++ b/awx/ui_next/src/components/CollapsibleSection/index.js @@ -0,0 +1 @@ +export { default } from './CollapsibleSection'; diff --git a/awx/ui_next/src/screens/Template/shared/JobTemplateForm.jsx b/awx/ui_next/src/screens/Template/shared/JobTemplateForm.jsx index d7a699c387..a0bd23e30c 100644 --- a/awx/ui_next/src/screens/Template/shared/JobTemplateForm.jsx +++ b/awx/ui_next/src/screens/Template/shared/JobTemplateForm.jsx @@ -13,6 +13,7 @@ import MultiSelect from '@components/MultiSelect'; import FormActionGroup from '@components/FormActionGroup'; import FormField from '@components/FormField'; import FormRow from '@components/FormRow'; +import CollapsibleSection from '@components/CollapsibleSection'; import { required } from '@util/validators'; import styled from 'styled-components'; import { JobTemplate } from '@types'; @@ -415,6 +416,9 @@ class JobTemplateForm extends Component { /> + + Advanced inputs here + );