diff --git a/superset-frontend/cypress-base/cypress/integration/explore/advanced.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/advanced.test.ts
index c27f054c2a..7a50b6e934 100644
--- a/superset-frontend/cypress-base/cypress/integration/explore/advanced.test.ts
+++ b/superset-frontend/cypress-base/cypress/integration/explore/advanced.test.ts
@@ -28,7 +28,7 @@ describe('Advanced analytics', () => {
cy.visitChartByName('Num Births Trend');
cy.verifySliceSuccess({ waitAlias: '@postJson' });
- cy.get('.panel-title').contains('Advanced Analytics').click();
+ cy.get('.ant-collapse-header').contains('Advanced Analytics').click();
cy.get('[data-test=time_compare]').find('.Select__control').click();
cy.get('[data-test=time_compare]')
@@ -47,7 +47,7 @@ describe('Advanced analytics', () => {
chartSelector: 'svg',
});
- cy.get('.panel-title').contains('Advanced Analytics').click();
+ cy.get('.ant-collapse-header').contains('Advanced Analytics').click();
cy.get('[data-test=time_compare]')
.find('.Select__multi-value__label')
.contains('28 days');
diff --git a/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts
index 8c9d3e7b3f..6ab462f32b 100644
--- a/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts
+++ b/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts
@@ -112,7 +112,7 @@ describe('VizType control', () => {
// should load mathjs for line chart
cy.get('script[src*="mathjs"]').should('have.length', 1);
cy.get('script').then(nodes => {
- expect(nodes.length).to.greaterThan(numScripts);
+ expect(nodes.length).to.eq(numScripts);
});
cy.get('button[data-test="run-query-button"]').click();
diff --git a/superset-frontend/spec/javascripts/explore/components/ControlPanelSection_spec.jsx b/superset-frontend/spec/javascripts/explore/components/ControlPanelSection_spec.jsx
deleted file mode 100644
index 521a5532ef..0000000000
--- a/superset-frontend/spec/javascripts/explore/components/ControlPanelSection_spec.jsx
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-import React from 'react';
-import { shallow } from 'enzyme';
-import { Panel } from 'react-bootstrap';
-import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls';
-import ControlPanelSection from 'src/explore/components/ControlPanelSection';
-
-const defaultProps = {
- children:
a child element
,
-};
-
-const optionalProps = {
- label: 'my label',
- description: 'my description',
- tooltip: 'my tooltip',
-};
-
-describe('ControlPanelSection', () => {
- let wrapper;
- let props;
- it('is a valid element', () => {
- expect(
- React.isValidElement(),
- ).toBe(true);
- });
-
- it('renders a Panel component', () => {
- wrapper = shallow();
- expect(wrapper.find(Panel)).toExist();
- });
-
- describe('with optional props', () => {
- beforeEach(() => {
- props = Object.assign(defaultProps, optionalProps);
- wrapper = shallow();
- });
-
- it('renders a label if present', () => {
- expect(
- wrapper
- .find('[data-test="clickable-control-panel-section-title"]')
- .text(),
- ).toContain('my label');
- });
-
- it('renders a InfoTooltipWithTrigger if label and tooltip is present', () => {
- expect(
- wrapper.find(Panel).dive().find(InfoTooltipWithTrigger),
- ).toHaveLength(1);
- });
- });
-});
diff --git a/superset-frontend/spec/javascripts/explore/components/ControlPanelsContainer_spec.jsx b/superset-frontend/spec/javascripts/explore/components/ControlPanelsContainer_spec.jsx
index 7063e64fdd..35de5b6c5b 100644
--- a/superset-frontend/spec/javascripts/explore/components/ControlPanelsContainer_spec.jsx
+++ b/superset-frontend/spec/javascripts/explore/components/ControlPanelsContainer_spec.jsx
@@ -22,7 +22,7 @@ import { getChartControlPanelRegistry, t } from '@superset-ui/core';
import { defaultControls } from 'src/explore/store';
import { getFormDataFromControls } from 'src/explore/controlUtils';
import { ControlPanelsContainer } from 'src/explore/components/ControlPanelsContainer';
-import ControlPanelSection from 'src/explore/components/ControlPanelSection';
+import Collapse from 'src/common/components/Collapse';
describe('ControlPanelsContainer', () => {
let wrapper;
@@ -91,6 +91,6 @@ describe('ControlPanelsContainer', () => {
it('renders ControlPanelSections', () => {
wrapper = shallow();
- expect(wrapper.find(ControlPanelSection)).toHaveLength(5);
+ expect(wrapper.find(Collapse.Panel)).toHaveLength(5);
});
});
diff --git a/superset-frontend/src/common/components/Collapse.tsx b/superset-frontend/src/common/components/Collapse.tsx
index b901bf4d5c..c6daa77cd1 100644
--- a/superset-frontend/src/common/components/Collapse.tsx
+++ b/superset-frontend/src/common/components/Collapse.tsx
@@ -26,11 +26,12 @@ interface CollapseProps extends AntdCollapseProps {
light?: boolean;
bigger?: boolean;
bold?: boolean;
+ animateArrows?: boolean;
}
const Collapse = Object.assign(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
- styled(({ light, bigger, bold, ...props }: CollapseProps) => (
+ styled(({ light, bigger, bold, animateArrows, ...props }: CollapseProps) => (
))`
height: 100%;
@@ -48,6 +49,20 @@ const Collapse = Object.assign(
font-size: ${({ bigger, theme }) =>
bigger ? `${theme.gridUnit * 4}px` : 'inherit'};
+ .ant-collapse-arrow svg {
+ transition: ${({ animateArrows }) =>
+ animateArrows ? 'transform 0.24s' : 'none'};
+ }
+
+ ${({ expandIconPosition }) =>
+ expandIconPosition &&
+ expandIconPosition === 'right' &&
+ `
+ .anticon.anticon-right.ant-collapse-arrow > svg {
+ transform: rotate(90deg) !important;
+ }
+ `}
+
${({ light, theme }) =>
light &&
`
@@ -56,6 +71,13 @@ const Collapse = Object.assign(
color: ${theme.colors.grayscale.light4};
}
`}
+
+ ${({ ghost, bordered, theme }) =>
+ ghost &&
+ bordered &&
+ `
+ border-bottom: 1px solid ${theme.colors.grayscale.light3};
+ `}
}
.ant-collapse-content {
height: 100%;
@@ -68,6 +90,18 @@ const Collapse = Object.assign(
}
}
}
+ .ant-collapse-item-active {
+ .ant-collapse-header {
+ ${({ expandIconPosition }) =>
+ expandIconPosition &&
+ expandIconPosition === 'right' &&
+ `
+ .anticon.anticon-right.ant-collapse-arrow > svg {
+ transform: rotate(-90deg) !important;
+ }
+ `}
+ }
+ }
`,
{
Panel: AntdCollapse.Panel,
diff --git a/superset-frontend/src/common/components/common.stories.tsx b/superset-frontend/src/common/components/common.stories.tsx
index 6c9abb0fbf..f46ded72c6 100644
--- a/superset-frontend/src/common/components/common.stories.tsx
+++ b/superset-frontend/src/common/components/common.stories.tsx
@@ -322,6 +322,16 @@ export const CollapseTextLight = () => (
);
+export const CollapseAnimateArrows = () => (
+
+
+ Hi! I am a sample content
+
+
+ Hi! I am another sample content
+
+
+);
export function StyledCronPicker() {
// @ts-ignore
const inputRef = useRef(null);
diff --git a/superset-frontend/src/explore/components/ControlPanelSection.jsx b/superset-frontend/src/explore/components/ControlPanelSection.jsx
deleted file mode 100644
index 43af950745..0000000000
--- a/superset-frontend/src/explore/components/ControlPanelSection.jsx
+++ /dev/null
@@ -1,117 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-import React from 'react';
-import PropTypes from 'prop-types';
-import { Panel } from 'react-bootstrap';
-import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls';
-import { styled } from '@superset-ui/core';
-
-const propTypes = {
- label: PropTypes.string,
- description: PropTypes.string,
- children: PropTypes.node.isRequired,
- startExpanded: PropTypes.bool,
- hasErrors: PropTypes.bool,
-};
-
-const defaultProps = {
- label: null,
- description: null,
- startExpanded: false,
- hasErrors: false,
-};
-
-const StyledPanelTitle = styled(Panel.Title)`
- & > div {
- display: flex;
- align-items: center;
- justify-content: space-between;
- }
-`;
-
-export default class ControlPanelSection extends React.Component {
- constructor(props) {
- super(props);
- this.state = { expanded: this.props.startExpanded };
- this.toggleExpand = this.toggleExpand.bind(this);
- }
-
- toggleExpand() {
- this.setState(prevState => ({ expanded: !prevState.expanded }));
- }
-
- renderHeader() {
- const { label, description, hasErrors } = this.props;
- return (
- label && (
-