Reactstrap: UncontrolledAccordion?

Created on 17 Feb 2017  路  16Comments  路  Source: reactstrap/reactstrap

Would be great to have a version of UncontrolledCollapse or perhaps more specifically an UncontrolledAccordion. Especially one that does something similar to bootstrap's data-parent:

To add accordion-like group management to a collapsible control, add the data attribute data-parent="#selector". Refer to the demo to see this in action.

https://v4-alpha.getbootstrap.com/components/collapse/#accordion-example

Right now I'll have to handle the mutually exclusive state logic myself.

enhancement help wanted up-for-grabs

All 16 comments

recompose is extremely useful for this, once you wrap your head around the API.

For instance, for an uncontrolled tooltip:

const StatefulTooltip = compose(
  withState("isOpen", "setOpen", false),
  withHandlers({
    toggle: ({ isOpen, setOpen }) => () => setOpen(!isOpen)
  }),
  mapProps(({ setOpen, ...rest }) => rest),
)(Tooltip);

(I know Reactstrap provides an uncontrolled tooltip, but this pattern can apply to any controlled component).

Accordion is essentially multiple Collapse components working together to ensure only one is open at a time. Not 100% sure how to make it uncontrolled in a similar way as the other uncontrolled component even with recompose in the mix.
An Accordion component may be needed to act as the controller on the children collapse.
BS4 uses data-parent to indicate that a collapse is apart of the accordion. This helps nested collapse components within the accordion not be apart of the accordion. Interesting things happen: https://codepen.io/TheSharpieOne/pen/qXdqbb so we cannot simply say any Collapse under an Accordion is part of the Accordion.

I'm just curious why there is no UncontrolledCollapse?

@foodgy The trigger event and element for the collapse is not directly tied to the collapse itself. Unlike the other Uncontrolled components, collapse can be triggered by different events from different elements. For instance, is the trigger element a button or a card header? Is the collapseable content adjacent, above or below the trigger? All of the variation make it more difficult to provide a single component to do it all easily, so the logic is left up to the developer.

We could have something like an UncontrolledCollapseCard, which looks like a Card where the CardHeader is the trigger. Multiple of these tied together with a little more logic could be an UncontrolledAccordion.

You can create an UncontrolledCollapse with a HOF. No other dependencies necessary.

import React, { Fragment, Component } from 'react';
import { Collapse } from 'reactstrap';

const createUncontrolledCollapse = (Toggler) =>
    class UncontrolledCollapse extends Component {

        state = {
            isOpen: false
        };

        toggle = () => {

            this.setState(({ isOpen }) => ({ isOpen: !isOpen }));

        };

        render () {

            return (
                <Fragment>
                    <Toggler onClick={this.toggle} />
                    <Collapse isOpen={this.state.isOpen} {...this.props} />
                </Fragment>
            );

        }

    };

export default createUncontrolledCollapse;

Then just use it:

export default () => {
        const UncontrolledCollapse = createUncontrolledCollapse((props) => <p {...props}>I am the toggler</p>);
        return (
            <UncontrolledCollapse>
                <p>I am the collapsible content</p>
            </UncontrolledCollapse>
        );
}

Let me know if you would accept a HOF like this in reactstrap and I'll make a PR that's a little more fleshed out. I mean this is a quick example.

If I am reading that correctly, it assumes the Toggler will be adjacent to the Collapse component (and coming before it). I don't think that is always the use case.
Coming back to this issue now, I think we can have this work similar to how the Popover and Tooltip work, at least in the way they get the "target" element which triggers the toggle.
This would allow the developer to put the toggler anywhere on the page and would probably be useful for the Collapse which often appears in the mobile navigation view.

<UncontrolledCollapse toggler="#my-toggle-button">
  <p>I am the collapsible content</p>
</UncontrolledCollapse>

@TheSharpieOne that sounds like a great idea. I was just referencing my use case above (it just happened to work that way). Could I work on this and submit a PR?

Yes, please!

Merged! This issue should now be closed.

The UncontrolledCollapse was added, but an Accordion is more advanced than a Collapse as it is multiple Collapse components tied together with some more logic to control them so that at most only one is open at a time.

@TheSharpieOne someone made an accordion using reactstrap Collapse => https://coreui.io/react/demo/#/base/collapses

It's a controlled component but... Maybe we can borrow the idea from there ?

They end up managing the state manually (seen here: https://github.com/coreui/coreui-free-react-admin-template/blob/master/src/views/Base/Collapses/Collapses.js) which is the only way to do it currently. Ideally it would be easier that needing all of that extra code.

We probably need an accordion component which controls _n_ number of Collapses and then we can make that thing uncontrolled.

The accordion component would probably work similar to how Tabs work, and then we can make that uncontrolled as well as Tabs in a similar way.

So does the gist above not correctly address the issue ?

@MichaelRWalker why not? Here is a sandbox :slightly_smiling_face:
https://codesandbox.io/s/reactstrap-accordion-7xchb

@iamandrewluca My mistake for not being more clear.
I meant your Gist is a good solution for the problem. i was more curious if it was going to be added to a PR

I actually just used a regular 'bootstrap' styled div with the class 'accordion'
<

Was this page helpful?
0 / 5 - 0 ratings

Related issues

juan-carlos-correa picture juan-carlos-correa  路  17Comments

HD-CMS picture HD-CMS  路  19Comments

twheys picture twheys  路  21Comments

thetric picture thetric  路  25Comments

ruszki picture ruszki  路  15Comments