rebassjs / rebass

:atom_symbol: React primitive UI components built with styled-system.
https://rebassjs.org
MIT License
7.94k stars 656 forks source link

Accordion Request #269

Closed mikebarkmin closed 6 years ago

mikebarkmin commented 7 years ago

An accordion component like bootstraps would be a great addition.

See: Bootstrap Accordion

jxnblk commented 7 years ago

Generally, I like this idea – I've thought about adding both <summary> and <details> components, along with a div-based, props-driven accordion, but haven't spent the time to think about how to implement those yet

JoshRosenstein commented 7 years ago

Was looking for something like accordions or collapsible panels. I ended up easily using rebass with react-collapsible. Below is react-collapsible example code embeded in rebass Panel Demo Code. This Example has Embedded accordions in the Panel, and makes the panel itself collapsible.

rebasscollapsepanel

import React from 'react'; import styled, { css } from 'styled-components'; import Collapsible from 'react-collapsible'; import { Panel, PanelHeader, PanelFooter, Provider,

} from 'rebass' import { Box } from 'grid-styled' import Section from './rebase/Section' // github.com/jxnblk/rebass/blob/master/docs/src/Section.js

const triggerSiblingExample = () =>

This is a sibling to the trigger which wont cause the Collapsible to open!
;

const CollapseDemo = styled.div` .Collapsible { background-color: white; }

.CollapsiblecontentInner { padding: 10px; border: 1px solid #ebebeb; border-top: 0; } .CollapsiblecontentInner p { margin-bottom: 10px; font-size: 14px; line-height: 20px; } .Collapsible__contentInner p:last-child { margin-bottom: 0; }

.Collapsibletrigger { display: block; font-weight: 400; text-decoration: none; color: #333333; position: relative; border: 1px solid white; padding: 10px; background: #00ac9d; color: white; } .Collapsibletrigger:after { font-family: 'FontAwesome'; content: '\f107'; position: absolute; right: 10px; top: 10px; display: block; transition: transform 300ms; } .Collapsibletrigger.is-open:after { transform: rotateZ(180deg); } .Collapsibletrigger.is-disabled { opacity: 0.5; background-color: grey; }

.CustomTriggerCSS { background-color: lightcoral; transition: background-color 200ms ease; }

.CustomTriggerCSS--open { background-color: darkslateblue; }

.Collapsible__custom-sibling { padding: 5px; font-size: 12px; background-color: #CBB700; color: black; }

`

export default () =>(

<Provider>
    <Section name='Panel Demo'>
        <Box my={3}>
            <Panel color='blue'>
                <Collapsible trigger=
                                 { <PanelHeader
                    color='white'
                    bg='blue'>
                    Hello
                </PanelHeader>}>
                <Box p={3}>
                    <CollapseDemo>
                        <Collapsible transitionTime={400} trigger="Then try this one">
                            <p>Would you look at that!</p>
                            <p>See; you can nest as many Collapsible components as you like.</p>

                            <Collapsible trigger="Mmmmm, it's all cosy nested here">
                                <p>And there's no limit to how many levels deep you go. Or how many you have on the same level.</p>
                                <Collapsible trigger="This is just another Collapsible">
                                    <p>It just keeps going and going! Well, actually we've stopped here. But that's only because I'm running out of things to type.</p>
                                </Collapsible>
                                <Collapsible trigger="But this one is open by default!" open={true}>
                                    <p>And would you look at that! This one is open by default. Sexy huh!?</p>
                                    <p>You can pass the prop of open=&#123;true&#125; which will make the Collapsible open by default.</p>
                                </Collapsible>
                                <Collapsible trigger="That's not all. Check out the speed of this one" transitionTime={100}>
                                    <p>Whoosh! That was fast right?</p>
                                    <p>You can control the time it takes to animate (transition) by passing the prop transitionTime a value in milliseconds. This one was set to transitionTime=&#123;100&#125;</p>
                                </Collapsible>

                            </Collapsible>
                        </Collapsible>

                        <Collapsible transitionTime={400} trigger="This one will blow your mind." easing={'cubic-bezier(0.175, 0.885, 0.32, 2.275)'}>
                            <p>Well maybe not. But did you see that little wiggle at the end. That is using a CSS cubic-beizer for the easing!</p>
                            <p>You can pass any string into the prop easing that you would declare in a CSS transition-timing-function. This means you have complete control over how that Collapsible appears.</p>
                        </Collapsible>

                        <Collapsible transitionTime={400} trigger="Oh and did I mention that I'm responsive?" triggerWhenOpen="Plus you can change the trigger text when I'm open too">
                            <p>That's correct. This collapsible section will animate to the height it needs to and then set it's height back to auto.</p>
                            <p>This means that no matter what width you stretch that viewport to, the Collapsible it will respond to it.</p>
                            <p>And no matter what height the content within it is, it will change height too.</p>
                            <h2>CSS Styles</h2>
                            <p>All of the style of the Collapsible (apart from the overflow and transition) are controlled by your own CSS too.</p>
                            <p>By default the top-level CSS class is Collapsible, but you have control over this too so you can easily add it into your own project. Neato!</p>
                            <p>So by setting the prop of classParentString=&#123;"MyNamespacedClass"&#125; then the top-level class will become MyNamespacedClass.</p>
                        </Collapsible>

                        <Collapsible lazyRender transitionTime={600} trigger="What happens if there's a shed-load of content?" easing={'cubic-bezier(0.175, 0.885, 0.32, 2.275)'} overflowWhenOpen="visible">
                            <p>Add the prop of <strong style={{ fontWeight: 'bold' }}>lazyRender</strong> and the content will only be rendered when the trigger is pressed</p>
                            <img src="https://lorempixel.com/320/240?random=1" />
                            <img src="https://lorempixel.com/320/240?random=2" />
                            <img src="https://lorempixel.com/320/240?random=3" />
                            <img src="https://lorempixel.com/320/240?random=4" />
                            <img src="https://lorempixel.com/320/240?random=5" />
                            <img src="https://lorempixel.com/320/240?random=6" />
                        </Collapsible>

                        <Collapsible trigger="You can customise the CSS a bit more too"
                                     triggerClassName="CustomTriggerCSS"
                                     triggerOpenedClassName="CustomTriggerCSS--open"
                                     contentOuterClassName="CustomOuterContentCSS"
                                     contentInnerClassName="CustomInnerContentCSS"
                        >
                            <p>This is the collapsible content. It can be any element or React component you like.</p>
                        </Collapsible>

                        <Collapsible trigger="You can disable them programatically too" open triggerDisabled>
                            <p>This one has it's trigger disabled in the open position. Nifty.</p>
                            <p>You also get the <strong>is-disabled</strong> CSS class so you can style it.</p>
                        </Collapsible>
                        <Collapsible trigger="You can have siblings to the trigger too which won't trigger the Collapsible" triggerSibling={triggerSiblingExample}>
                            <p>This one has it's trigger disabled in the open position. Nifty.</p>
                            <p>You also get the <strong>is-disabled</strong> CSS class so you can style it.</p>
                        </Collapsible>
                    </CollapseDemo>

                </Box>
                <PanelFooter color='blue'>
                    Footer
                </PanelFooter>
                </Collapsible>
            </Panel>
        </Box>
    </Section>
</Provider>

)

jxnblk commented 6 years ago

Closing this in favor of #403